【kubernetes】网络虚拟网卡对veth pair、flannel网络模型实现原理
补课:虚拟网卡对veth pair什么是虚拟网卡对veth pair?Virtual Ethernet Pair简称veth pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样.netns相关命令#创建veth pair[root@centos ~]# ip link add tap1 type veth peer name tap2#创建namespace
补课:虚拟网卡对veth pair
什么是虚拟网卡对veth pair?
Virtual Ethernet Pair简称veth pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样.
netns相关命令
#创建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
查看host/container veth pair 关系
可以通过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 网络
- docker网络有哪些?
# docker network ls
NETWORK ID NAME DRIVER SCOPE
742bf53d2d37 bridge bridge local
9a4b4bcd0780 host host local
f03248be6b9c none null local
还有共享其他容器的网络空间,加起来4种。
- bridge是使用独立的net ns,还有虚拟网卡对实现网络模式。
- host是共享主机的net ns实现网络模式。
- none只有lo网络,但是K8S的网络插件会通过CNI的方式实现创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等等。
- 共享其他容器的net ns,这个是pod中应用容器会join到pause容器的net ns中。
2. docker的host是如何实现的?
# docker run -it --rm --network host busybox /bin/sh
# docker inspect -f '{{.State.Pid}}' 3a90b29a303c
# cd /proc/63880/ns/
net的空间地址是和系统的ns地址一致
2.1 如何看到系统有多少netns?
#ip netns list
#不是通过ip netns 创建的是用这个命令看不到的
3.docker的bridge模式是如何实现的?
- 同一主机内的2个bridge网络的容器互相访问,容器的路由是指向docker0地址,通过虚拟网卡对将数据发送到docker0,而docker0相当于二层交换机,将2个容器的访问数据互相转发。
- docker0将容器的数据 发送到外界,是通过iptables实现的。
3.1 docker0是什么?
docker0:docker容器网络采用Bridge(桥接模式)形式下的网络接口,可以简单理解为虚拟的交换机和路由器
3.2 bridge通信过程?
容器eth0@if7: 172.17.0.2/16 --> 主机veth423bfe6@if6 --> 主机docker0: 172.17.0.1/16
ps:图片摘自:Bridge网络实现原理
3.3 虚拟网卡对怎么和docker0网卡交互的?
# 进入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网络
3.4 docker0网卡是怎么将容器数据通过eth0转发出去的?
#查看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发送出去
3.5 补课:SNAT机制,数据包分析?外部回来的数据是如何处理的?
根据路由设置,如果外界收到的包拆包后,收到的目标地址是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将数据交给正确的容器地址。
k8s的网络实现
k8s如何管理docker网络
通过CNI接口对docker网络进行管理实现创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等等。
网络模式
- overlay模式
flannel的vxlan
calico的ipip - underlay模式
flannel的host-gw
calico的BGP
flannel的 vxlan模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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)
主机端网络流量情况
那么docker0到flannel0是如何实现的?
- veth卡会桥接在cni0的网桥上。
# brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.a26027094489 no vethada78762
docker0 8000.0242a95731e7 no
- 数据包走到了cni0的网桥后,根据已经的目标ip,10.244.1.2,可以查找路由表,根据路由和掩码,选择对应的iface,也就是flannel.1。且下一跳,也就是10.244.1.0。
[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
- 进入到flannel.1如何知道应该发向哪个物理机呢。这个时候,其实是通过arp来获取。可以通过arp命令查看到对应的mac地址。
# arp -e
Address HWtype HWaddress Flags Mask Iface
10.244.1.0 ether 3e:01:ed:47:de:7f CM flannel.1
- 这个mac地址在vxlan中,可以通过bridge fdb show来进行查看。可以看到,如果是发向3e:01:ed:47🇩🇪7f的地址,则目标机器在10.10.10.217机器上。则数据就会流转到10.10.10.217上了。经过vxlan封包后的数据包就会经过em1设备发向到10.10.10.217上。
# bridge fdb show
3e:01:ed:47:de:7f dev flannel.1 dst 10.10.10.217 self permanent
- 在10.10.10.217上,首先经过了iptables链,而后在flannel.1的Iface上则接收到该数据包。这里我们可以看到,flannel.1的mac地址就是3e:01:ed:47🇩🇪7f。
这里我曾经就是遇到过被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的Directrouting模式
VXLAN还有另外一种功能,VXLAN也支持类似host-gw的玩法,如果两个节点在同一网段时使用host-gw通信,如果不在同一网段中,即 当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。
结合了Host-gw和VXLAN,这就是VXLAN的Directrouting模式
calico的IPIP模式
待补充
calico的BGP模式
待补充
引用:
171vr.cn
更多推荐
所有评论(0)