Kubernetes進階 -- Flannel網絡插件vxlan,host-gw,udp

  • flannelcoreoskubernets提供的網絡解決方案,主要爲打通跨節點的容器通信,其中vxlan模式爲flannel實現的一種後端模式,其他模式還包括udp, host-gw等。

vxlan

簡述

  • VxLAN(Virtual eXtensible Local Area Network,虛擬擴展局域網)技術很好地解決了現有VLAN技術無法滿足大二層網絡需求的問題。VxLAN技術是一種大二層的虛擬網絡技術,主要原理是引入一個UDP格式的外層隧道作爲數據鏈路層,而原有數據報文內容作爲隧道淨荷加以傳輸。由於外層採用了UDP作爲傳輸手段,淨荷數據可以輕鬆地在二三層網絡中傳送。VxLAN已成爲業界主流的虛擬網絡技術之一,IETF正在制定相關標準。VxLAN技術的特點在於如下幾個方面。
  • VXLAN主要解決現階段大規模雲計算數據中心虛擬網絡不足的問題。VMware ESXi、Open vSwitch、當前主流的網絡芯片均已支持VXLAN:它備受業界關注,未來有可能成爲網絡虛擬化技術當中的主流技術之一,如此看來,它的發展和應用前景還是值得期待的。

原理

  • VXLAN(Virtual eXtensible Local Area Network)是一種隧道技術,能在三層網絡的基礎上建立二層以太網網絡隧道,從而實現跨地域的二層互連。

  • VXLAN採取了將原始以太網報文封裝在UDP數據包裏的封裝格式。將原來的二層數據幀加上VXLAN頭部一起封裝在一個UDP數據包裏。

  • VXLAN頭部包含有一個VXLAN標識(即VNI,VXLAN Network Identifier),只有在同一個VXLAN上的虛擬機之間才能相互通信。VNI在數據包之中佔24比特,故可支持1600萬個VXLAN的同時存在,遠多於VLAN的4094個,因此可適應大規模租戶的部署。

  • VXLAN一般通過安裝在服務器上的軟件實現報文的封裝與解封裝,網絡只要IP路由可達即可。VXLAN實現了應用與物理網絡的解耦,但網絡與虛擬機還是相互獨立的。業界一般通過網絡控制器(如SDN,Software Defined Network)實現VXLAN網絡與雲業務的聯動。當虛擬機發生遷移後,虛機/存儲控制器會把虛擬機遷移信息通知給網絡控制器,網絡控制器根據虛擬機遷移的新位置,重新調整網絡配置,從而實現網絡與雲業務的聯動。也就是說,物理網絡可以是傳統的三層IP網絡,路由可達即可。虛擬機可跨三層IP網絡遠距離遷移,不再受限於二層技術。物理網絡也無需允許所有VLAN通過。接入交換機需要學習的MAC地址的數量也大大減少,削弱了網絡設備MAC地址表項規格對虛擬機規模的約束。

  • VXLAN網絡設備主要有三種角色,分別是VTEP(VXLAN Tunnel EndPoint)、VXLAN網關、VXLANIP網關。

    • VTEP是直接與終端連接的設備,負責原始以太報文的VXLAN封裝和解封裝。
    • VXLAN網關除了具備VTEP的功能外,還負責VLAN報文與VXLAN報文之間的映射和轉發。VXLAN的虛擬機與傳統VLAN的虛擬機之間互訪,通過VXLAN網關來完成。
    • VXLANIP網關具有VXLAN網關的所有功能,此外,還負責處理不同VXLAN之間的報文通信。不同VXLAN的虛擬機之間需要互訪,必須經過VXLANIP網關完成。

在這裏插入圖片描述
node1的容器1通過cni0的網關接口,通過flannel的vxlan模式進行封裝,通過eth0網卡出去,進行udp傳輸,裏面搭載了vxlan的封裝協議數據包,傳輸給node2,到達node2後,內核進行識別解封,然後node2的flannel設備再次進行解封,在到達cni0,這樣就相當於已經到達了集羣的內部了,然後把信息注入到node2的容器2。

結點在啓動的時候,會啓動flanneld服務,查詢k8s的apiserver,從etcd獲取分配子網的信息,並向etcd進行註冊:

[root@server3 ~]# cd /run/flannel/
[root@server3 flannel]# cat subnet.env 
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.1.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
[root@server3 flannel]# ps ax |grep flannel
 6852 ?        Ssl    0:02 /opt/bin/flanneld --ip-masq --kube-subnet-mgr
17554 pts/0    S+     0:00 grep --color=auto flannel

ip a
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether 26:c1:ab:a2:5d:20 brd ff:ff:ff:ff:ff:ff		
    inet 10.244.1.0/32 scope global flannel.1		//就是flannel的ip地址
       valid_lft forever preferred_lft forever
    inet6 fe80::24c1:abff:fea2:5d20/64 scope link 
[root@server2 manifest]# kubectl get pod -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
deployment-example-846496db9d-6jvqv   1/1     Running   0          65m   10.244.2.69   server4   <none>           <none>
deployment-example-846496db9d-xbqwz   1/1     Running   0          65m   10.244.1.93   server3   <none>           <none>

當前我們server3和server4各有一個pod,他們的信息都保存在master主機的etcd中。
他們是屬於不同網段的.他們要通訊的話是跨主機的。

[root@server3 flannel]# ip route
default via 172.25.254.67 dev ens3 
10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink 
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1 		*
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink 					*
169.254.0.0/16 dev ens3 scope link metric 1002 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.25.254.0/24 dev ens3 proto kernel scope link src 172.25.254.3

我們可以看出要訪問10.244.1.0/24這個網段要走cni0的網卡,數據包先到達cni0網卡上,在從cni0網卡路由出去:

[root@server3 flannel]# brctl show
bridge name	bridge id		STP enabled	interfaces
cni0		8000.ee2a6f7b5ebe	no		veth95f9a72c	
docker0		8000.024255b8b349	no
可以看出一端在pod中,一端在cni0網卡上,他們通過虛擬網絡進行通訊

當我們想訪問10.244.2.0/24網段是需要走10.244.2.0這個網關,使用flannel.1這個設備。這就是爲什麼從cni0出來到達flannel設備。10.244.2.0正是server4上的flannel.1這個設備:

[root@server4 flannel]# ip a
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether f6:5f:84:9e:d8:36 brd ff:ff:ff:ff:ff:ff
    inet 10.244.2.0/32 scope global flannel.1
       valid_lft forever preferred_lft forever
    inet6 fe80::f45f:84ff:fe9e:d836/64 scope link 

flannel封裝VNI

然後server3的flannel開始封裝VNI,它有源地址和目的地地址組成。

[root@server3 flannel]# ip neigh 
10.244.1.93 dev cni0 lladdr 12:d0:2d:d9:49:89 STALE
10.244.2.0 dev flannel.1 lladdr f6:5f:84:9e:d8:36 PERMANENT

源地址:10.244.1.93 mac:12:d0:2d:d9:49:89

目的地址:10.244.2.69 mac: f6:5f:84:9e:d8:36

由於目前server3上還不能知道 10.244.2.69 的mac地址,所以會把 10.244.2.0 網關的mac地址加上,這個對應的是server4上 flannel.1 的 mac 地址。

eth0封裝

通過 eth0 走 udp 協議,我們纔可以到達 node2 主機,所以我們還要獲取 node2 的 eth0 的mac地址。這時我們flannel封裝的信息會在eth0封裝的信息的內部。

[root@server3 flannel]# bridge fdb show
。。。
f6:5f:84:9e:d8:36 dev flannel.1 dst 172.25.254.4 self permanent		
。。。

告訴我們要訪問 f6:5f:84:9e:d8:36 需要發送到 172.25.254.4 上,它的mac地址是:

[root@server3 flannel]# arp -an
? (10.244.1.91) at ca:66:fa:19:85:83 [ether] on cni0
? (172.25.254.1) at 52:54:00:65:28:86 [ether] on ens3
? (172.25.254.2) at 52:54:00:df:b5:2f [ether] on ens3
? (169.254.169.254) at <incomplete> on ens3
? (10.244.2.0) at f6:5f:84:9e:d8:36 [ether] PERM on flannel.1
? (172.25.254.4) at 52:54:00:c4:e4:e5 [ether] on ens3		//這裏

src: 172.25.254.3 mac:52:54:00:fa:bc:3a
dst: 172.25.254.4 mac:52:54:00:c4:e4:e5
然後把flannel的數據包在封裝進來,就是下面這樣:

src: 172.25.254.3 mac:52:54:00:fa:bc:3a
dst: 172.25.254.4 mac:52:54:00:c4:e4:e5


  源地址:10.244.1.93   mac:12:d0:2d:d9:49:89
  目的地址:10.244.2.69    mac:   f6:5f:84:9e:d8:36

然後server4上內核進行識別,flannel再進行解封,在通過cni0就可以訪問到pod內部了。

這就是爲什麼在訪問svc的時候有時會卡頓,就是因爲訪問時調度到的後端結點有時需要跨主機,所以纔會卡頓。

host-gw

flannel中包含了幾種backend,vxlan只是其中的一種,其中還有udp的方式,以及另一種在二層的方式host-gw。

host-gw 不會封裝數據包,而是在主機的路由表中創建到其他主機 subnet 的路由條目,從而實現容器跨主機通信。

[root@server2 manifest]# kubectl delete -f kube-flannel.yml 
//刪除之前的組件
[root@server2 manifest]# vim kube-flannel.yml
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "host-gw"	//把類型改爲host-gw
      }
[root@server2 manifest]# kubectl apply -f kube-flannel.yml 	//應用

[root@server2 manifest]# kubectl get pod -n kube-system 

kube-flannel-ds-amd64-7jrft       1/1     Running   0          2m44s
kube-flannel-ds-amd64-dq4j6       1/1     Running   0          2m44s
kube-flannel-ds-amd64-pkjnn       1/1     Running   0          2m44s

然後我們就可以發現flannel.1這個隧道網卡就不見了因爲我們現在用不到這個設備了,直接走主機的網關。
要求在二層上必須是相通的。但在大型的私有云上不只有一個網絡段,就不適用了。

[root@server1 harbor]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server1 harbor]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server1 harbor]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server1 harbor]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

就一點也不卡頓了。

[root@server3 flannel]# ip route
default via 172.25.254.67 dev ens3 
10.244.0.0/24 via 172.25.254.2 dev ens3 
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1 
10.244.2.0/24 via 172.25.254.4 dev ens3 	//直接轉發到254.4上,沒有像vxlan一樣走flannel。
169.254.0.0/16 dev ens3 scope link metric 1002 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.25.254.0/24 dev ens3 proto kernel scope link src 172.25.254.3

udp方式存在的弊端太多了,就不再介紹。

flannel主要是負責網絡通信的,不具網絡備策略功能,而k8s的另一種網絡插件 calico 則在flannel的基礎上可以定製網絡策略,在每個結點上加一個路由器。功能更強。

直連路由

對於二層網段相同的可以採用 直連路由的方式,相當於host-gw 的方式,對於不同的則採用 flannel 的方式。

[root@server2 manifest]# vim kube-flannel.yml
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan",
        "Directrouting": true		//直連路由
[root@server2 manifest]# kubectl apply -f kube-flannel.yml

[root@server3 flannel]# ip a

6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default 
    link/ether 26:c1:ab:a2:5d:20 brd ff:ff:ff:ff:ff:ff
    inet 10.244.1.0/32 scope global flannel.1		//隧道設備又出來了,不通網絡段走這裏
       valid_lft forever preferred_lft forever
    inet6 fe80::24c1:abff:fea2:5d20/64 scope link
[root@server3 flannel]# ip iroute
Object "iroute" is unknown, try "ip help".
[root@server3 flannel]# ip route
default via 172.25.254.67 dev ens3 
10.244.0.0/24 via 172.25.254.2 dev ens3 
10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1 
10.244.2.0/24 via 172.25.254.4 dev ens3 		//但是網關依然在這裏,同段走這裏
169.254.0.0/16 dev ens3 scope link metric 1002 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.25.254.0/24 dev ens3 proto kernel scope link src 172.25.254.3 

[root@rhel7host ~]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@rhel7host ~]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@rhel7host ~]# curl 172.25.254.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@rhel7host ~]# 
訪問依然很順暢。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章