Virtual Ethernet Pair简称veth pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样.
#创建veth pair
[root@centos ~]# ip link add tap1 type veth peer name tap2
#创建namespace:ns1和ns2
[root@centos ~]# ip netns add ns1
[root@centos ~]# ip netns add ns2
#把两个tap分别迁移到对应的namespace中去
[root@centos ~]# ip link set tap1 netns ns1
[root@centos ~]# ip link set tap2 netns ns2
#分别给两个tap绑定IP
[root@centos ~]# ip netns exec ns1 ip addr add local 192.168.50.1/24 dev tap1
[root@centos ~]# ip netns exec ns2 ip addr add local 192.168.50.2/24 dev tap2
#将两个tap设置为up
[root@centos ~]# ip netns exec ns1 ifconfig tap1 up
[root@centos ~]# ip netns exec ns2 ifconfig tap2 up
#ping测试
[root@centos ~]# ip netns exec ns2 ping 192.168.50.1
PING 192.168.50.1 (192.168.50.1) 56(84) bytes of data.
64 bytes from 192.168.50.1: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 192.168.50.1: icmp_seq=2 ttl=64 time=0.025 ms
64 bytes from 192.168.50.1: icmp_seq=3 ttl=64 time=0.027 ms
可以通过iflink和ifindex查看
在容器里面执行
# cat /sys/class/net/eth0/iflink
7
在主机遍历/sys/class/net下网卡内子目录ifindex的值和容器里面查出来的iflink值相当的veth名字
# cat /sys/class/net/
## find /sys/devices/virtual/net -type f -name "ifindex" |xargs grep "7"
/sys/devices/virtual/net/veth423bfe6/ifindex:7
引用:
Linux虚拟网络基础——veth pair
veth pair 介绍
查看host/container veth pair 关系
# docker network ls
NETWORK ID NAME DRIVER SCOPE
742bf53d2d37 bridge bridge local
9a4b4bcd0780 host host local
f03248be6b9c none null local
还有共享其他容器的网络空间,加起来4种。
# docker run -it --rm --network host busybox /bin/sh
# docker inspect -f '{{.State.Pid}}' 3a90b29a303c
# cd /proc/63880/ns/
net的空间地址是和系统的ns地址一致
#ip netns list
#不是通过ip netns 创建的是用这个命令看不到的
docker0:docker容器网络采用Bridge(桥接模式)形式下的网络接口,可以简单理解为虚拟的交换机和路由器
容器eth0@if7: 172.17.0.2/16 --> 主机veth423bfe6@if6 --> 主机docker0: 172.17.0.1/16
ps:图片摘自:Bridge网络实现原理
# 进入bridge网络的容器然后查看路由
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
可以看出容器数据通过虚拟网卡对的方式,数据进入veth423bfe6@if6虚拟网络,然后路由到docker0网络
#查看iptables策略
#iptables-save
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
#查看主机路由表
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.145.2 0.0.0.0 UG 0 0 0 ens33
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 ens33
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.145.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33
可以看出主机路由没有进行特殊路由,而是通过iptables收到数据如果不在路由表中,则将数据进行SNAT后通过主机的Gateway发送出去
根据路由设置,如果外界收到的包拆包后,收到的目标地址是172.17.0.0的网段,就会交给docker0处理。
#先进行tcpdump抓包
tcpdump 172.17.0.2 -w /tmp/172.17.0.2.cap
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-inZKyfAU-1607219010879)(k8s网络.assets/1607133798695.png)]
TCP数据传输是通过4元组,出去的数据建立的链接包含原地址端口和目标地址端口,回来的数据也是按照原路的端口回来,所以数据最终交给docker0,而docker0也会记录session将数据交给正确的容器地址。
通过CNI接口对docker网络进行管理实现创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iAhG8dtP-1607219010880)(https://xuxinkun.github.io/img/flannel/flannel.png)] ](https://img-blog.csdnimg.cn/20190304124933913.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01hdHJpeEdvZA==,size_16,color_FFFFFF,t_70)
主机端网络流量情况
# brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.a26027094489 no vethada78762
docker0 8000.0242a95731e7 no
[root@node-64-216 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 em1
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 em1
10.244.0.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.1.0 10.244.1.0 255.255.255.0 UG 0 0 0 flannel.1
# arp -e
Address HWtype HWaddress Flags Mask Iface
10.244.1.0 ether 3e:01:ed:47:de:7f CM flannel.1
# bridge fdb show
3e:01:ed:47:de:7f dev flannel.1 dst 10.10.10.217 self permanent
这里我曾经就是遇到过被iptables的forward链拦住的情况。如果数据包在216的flannel.1上可以监测到,但是217的flannel.1中断了,则可以检查216到217之间的路由情况以及217的iptables链的情况。
[root@node-64-217 ~]# ip add
2: em1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 90:b1:1c:33:b4:b1 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.217/24 brd 10.10.10.255 scope global em1
valid_lft forever preferred_lft forever
152: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default
link/ether 3e:01:ed:47:de:7f brd ff:ff:ff:ff:ff:ff
inet 10.244.1.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
153: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
link/ether 36:11:ab:93:2f:6f brd ff:ff:ff:ff:ff:ff
inet 10.244.1.1/24 scope global cni0
valid_lft forever preferred_lft forever
154: veth7f8b8e9e@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master cni0 state UP group default
link/ether 06:2f:35:74:cd:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
到达flannel.1后,根据路由表,查看10.244.1.2的路由应送到217的cni0的网桥上。
[root@node-64-217 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 em1
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 em1
10.244.0.0 10.244.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
这里我们查看cni0的网桥信息。
[root@node-64-217 ~]# brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.3611ab932f6f no veth5a89e906
veth7f8b8e9e
到达网桥后,就可以根据地址将数据送到10.244.1.2的对应的veth上,进而在容器中收到对应的数据包了。
以上就是两个处于不同物理机上的容器间发送数据包的流程。相比较来说,从容器到物理机的ping就简单多了。这个流程就是veth->cni0->em1->对端物理机ip。这里就不详细叙述了。
同一台物理机上不同容器的ping只需要经过cni0的网桥就可以了。
引用:
flannel vxlan工作基本原理及常见排障方法
VXLAN还有另外一种功能,VXLAN也支持类似host-gw的玩法,如果两个节点在同一网段时使用host-gw通信,如果不在同一网段中,即 当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。
结合了Host-gw和VXLAN,这就是VXLAN的Directrouting模式
待补充
待补充
引用:
k8s与网络–Flannel解读
171vr.cn