补课:虚拟网卡对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 网络

  1. 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模式是如何实现的?

  1. 同一主机内的2个bridge网络的容器互相访问,容器的路由是指向docker0地址,通过虚拟网卡对将数据发送到docker0,而docker0相当于二层交换机,将2个容器的访问数据互相转发。
  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

img

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)

主机端网络流量情况

flannel

那么docker0到flannel0是如何实现的?
  1. veth卡会桥接在cni0的网桥上。
# brctl show                 
bridge name     bridge id               STP enabled     interfaces
cni0            8000.a26027094489       no              vethada78762
docker0         8000.0242a95731e7       no
  1. 数据包走到了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
  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
  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
  1. 在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工作基本原理及常见排障方法

flannel的VXLAN的Directrouting模式

VXLAN还有另外一种功能,VXLAN也支持类似host-gw的玩法,如果两个节点在同一网段时使用host-gw通信,如果不在同一网段中,即 当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。
结合了Host-gw和VXLAN,这就是VXLAN的Directrouting模式

calico的IPIP模式

待补充

calico的BGP模式

待补充

引用:

k8s与网络–Flannel解读

171vr.cn

Logo

开源、云原生的融合云平台

更多推荐