【kubernetes】網路虛擬網路卡對veth pair、flannel網路模型實現原理

^白開水^發表於2020-12-06

補課:虛擬網路卡對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

相關文章