本文詳解之flannel-Vxlan模式

本文詳解之flannel-Vxlan模式

VXLAN簡介 工作在內核態

VXLAN全稱Virtual Extensible LAN,是一種虛擬化隧道通信技術,主要是為了突破VLAN的最多4096個子網的數量限制,以滿足大規模雲計算數據中心的需求。VLAN技術的缺陷是VLAN Header預留的長度只有12 bit,故最多隻能支持2的12次方即4096個子網的劃分,無法滿足雲計算場景下主機數量日益增長的需求。當前VXLAN的報文Header內有24 bit,可以支持2的24次方個子網,並通過VNI(Virtual Network Identifier)來區分不同的子網,相當於VLAN當中的VLAN ID。

不同於其他隧道協議,VXLAN是一個一對多的網絡,並不僅僅是一對一的隧道協議。一個VXLAN設備能通過像網橋一樣的學習方式學習到其他對端的IP地址,也可以直接配置靜態轉發表。

當採用VXLAN模式時,flanneld在啟動時會通過Netlink機制與Linux內核通信,建立一個VTEP(Virtual Tunnel Access End Point)設備flannel.1 (命名規則為flannel.[VNI],VNI默認為1),類似於交換機當中的一個網口。

可以通過ip -d link查看VTEP設備flannel.1的配置信息,從以下輸出可以看到,VTEP的local IP為172.16.130.244,destination port為8472。

[root@10-10-88-192 ~]# ip -d link show flannel.1
5: flannel.1:  mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT
 link/ether a2:5e:b0:43:09:a7 brd ff:ff:ff:ff:ff:ff promiscuity 0
 vxlan id 1 local 172.16.130.244 dev eth1 srcport 0 0 dstport 8472 nolearning ageing 300 addrgenmode eui64
[root@10-10-88-192 ~]#

在UDP模式下由flanneld進程進行網絡包的封包和解包的工作

VXLAN模式下解封包的事情交由內核處理,那麼此時FlannnelD的作用是什麼呢?帶著這個疑問我們先來簡單看一下VXLAN Backend是如何工作的。

VXLAN Backend工作原理

當flanneld啟動時將創建VTEP設備(默認為flannel.1,若已經創建則跳過),並將VTEP設備的相關信息上報到etcd當中,而當在Flannel網絡中有新的節點發現時,各個節點上的flanneld將依次執行以下流程:

1. 在節點當中創建一條該節點所屬網段的路由表,主要是能讓Pod當中的流量路由到flannel.1接口。

通過route -n可以查看到節點當中已經有兩條flannel.1接口的路由:

[root@10-10-88-192 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.88.254 0.0.0.0 UG 0 0 0 eth0
10.10.88.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
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
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1003 0 0 eth1
172.16.130.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
[root@10-10-88-192 ~]#

2. 在節點當中添加一條該節點的IP以及VTEP設備的靜態ARP緩存。

可通過arp -n命令查看到master節點當中已經緩存了另外兩個節點以及VTEP的ARP信息(已刪除無關ARP緩存信息)

[root@10-10-88-192 ~]# arp -n
Address HWtype HWaddress Flags Mask Iface
10.244.2.0 ether 42:7f:69:c7:cd:37 CM flannel.1
10.244.1.0 ether 7a:2c:d0:7f:48:3f CM flannel.1
172.16.130.140 ether fa:89:cf:03:e3:01 C eth1
172.16.130.164 ether fa:88:2a:44:2b:01 C eth1

3. 在節點當中添加一條該節點的轉發表。

通過bridge命令查看節點上的VXLAN轉發表(FDB entry),MAC為對端VTEP設備即flannel.1的MAC,IP為VTEP對應的對外IP(可通過flanneld的啟動參數--iface=eth1指定,若不指定則按默認網關查找網絡接口對應的IP),可以看到已經有兩條轉發表。

[root@10-10-88-192 ~]# bridge fdb show dev flannel.1
42:7f:69:c7:cd:37 dst 172.16.130.164 self permanent
7a:2c:d0:7f:48:3f dst 172.16.130.140 self permanent
[root@10-10-88-192 ~]#

VXLAN Backend配置

跟UDP Backend一樣,將Flannel Backend修改為VXLAN只需要將Flannel ConfigMap當中的Backend type字段修改為VXLAN即可。由於VXLAN類型相對UDP複雜並且有較好的靈活性,這裡簡單說一下VXLAN當中的幾個配置選項:

  • VNI(Number):VXLAN Identifier,默認為1
  • Port(Number):用於發送VXLAN UDP報文的端口,默認為8472
  • DirectRouting(Boolean):當兩臺主機處於同一個網段當中時,啟用後將採用直接路由的方式進行跨節點網絡通信(此時工作模式跟後面要講的host-gw Backend一樣),只有當兩臺主機處於不同的網段當中時才會採用VXLAN進行封包,默認為關閉狀態。
root@10-10-88-192 ~]# kubectl get cm -o yaml -n kube-system kube-flannel-cfg
apiVersion: v1
data:
 cni-conf.json: |
 {
 "name": "cbr0",
 "type": "flannel",
 "delegate": {
 "isDefaultGateway": true
 }
 }
 net-conf.json: |
 {
 "Network": "10.244.0.0/16",
 "Backend": {
 "Type": "vxlan"
 }
 }
kind: ConfigMap
metadata:
 creationTimestamp: 2018-10-30T08:34:01Z
 labels:
 app: flannel
 tier: node
 name: kube-flannel-cfg
 namespace: kube-system
 resourceVersion: "33872104"
 selfLink: /api/v1/namespaces/kube-system/configmaps/kube-flannel-cfg
 uid: 8d981eff-dc1e-11e8-8103-fa900126bc00
[root@10-10-88-192 ~]#

同樣在更新配置後delete pod使配置生效,並可以通過Flannel的日誌查看到Backend已經更新為VXLAN模式:

同樣可以通過netstat -ulnp命令查看VXLAN監聽的端口:

[root@10-10-88-192 ~]# kubectl logs -f -n kube-system kube-flannel-ds-7bjfm
I0318 03:24:02.148654 1 main.go:487] Using interface with name eth1 and address 172.16.130.244
I0318 03:24:02.148754 1 main.go:504] Defaulting external address to interface address (172.16.130.244)
I0318 03:24:02.207525 1 kube.go:130] Waiting 10m0s for node controller to sync
I0318 03:24:02.207596 1 kube.go:283] Starting kube subnet manager
I0318 03:24:03.207695 1 kube.go:137] Node controller sync successful
I0318 03:24:03.207729 1 main.go:234] Created subnet manager: Kubernetes Subnet Manager - 10-10-88-192
I0318 03:24:03.207735 1 main.go:237] Installing signal handlers
I0318 03:24:03.207812 1 main.go:352] Found network config - Backend type: vxlan
I0318 03:24:03.227332 1 vxlan.go:119] VXLAN config: VNI=1 Port=0 GBP=false DirectRouting=false
I0318 03:24:03.587362 1 main.go:299] Wrote subnet file to /run/flannel/subnet.env
I0318 03:24:03.587379 1 main.go:303] Running backend.
I0318 03:24:03.587390 1 main.go:321] Waiting for all goroutines to exit
I0318 03:24:03.587418 1 vxlan_network.go:56] watching for new subnet leases
[root@10-10-88-192 ~]# netstat -ulnp | grep 8472
udp 0 0 0.0.0.0:8472 0.0.0.0:* -
[root@10-10-88-192 ~]#

但跟UDP模式下查看flanneld監聽的端口的區別為,最後一欄顯示的不是進程的ID和名稱,而是一個破折號“-”,這說明UDP的8472端口不是由用戶態的進程在監聽的,也證實了VXLAN模塊工作在內核態模式下。

本文詳解之flannel-Vxlan模式

倆個容器跨節點網絡通信實現流程為:

1. 同UDP Backend模式,容器A當中的IP包通過容器A內的路由表被髮送到cni0

2. 到達cni0當中的IP包通過匹配host A當中的路由表發現通往10.244.2.194的IP包應該交給flannel.1接口

3. flannel.1作為一個VTEP設備,收到報文後將按照VTEP的配置進行封包,首先通過etcd得知10.244.2.194屬於節點B,並得到節點B的IP,通過節點A當中的轉發表得到節點B對應的VTEP的MAC,根據flannel.1設備創建時的設置的參數(VNI、local IP、Port)進行VXLAN封包

4. 通過host A跟host B之間的網絡連接,VXLAN包到達host B的eth1接口

5. 通過端口8472,VXLAN包被轉發給VTEP設備flannel.1進行解包

6. 解封裝後的IP包匹配host B當中的路由表(10.244.2.0),內核將IP包轉發給cni0

7. cni0將IP包轉發給連接在cni0上的容器B

VXLAN模式相比UDP模式高效,減少了udp封包解包的過程,也減少了內核態和用戶態的切換


分享到:


相關文章: