Kubernetes網路插件Flannel的三種工作模式

  • 2019 年 10 月 22 日
  • 筆記

跨主機通訊的一個解決方案是Flannel,由CoreOS推出,支援3種實現:UDP、VXLAN、host-gw
udp模式:使用設備flannel.0進行封包解包,不是內核原生支援,上下文切換較大,性能非常差
vxlan模式:使用flannel.1進行封包解包,內核原生支援,性能較強
host-gw模式:無需flannel.1這樣的中間設備,直接宿主機當作子網的下一跳地址,性能最強
host-gw的性能損失大約在10%左右,而其他所有基於VXLAN「隧道」機制 的網路方案,性能損失在20%~30%左右

一、UDP模式(性能差)

核心就是通過TUN設備flannel0實現(TUN設備是工作在三層的虛擬網路設備,功能是:在作業系統內核和用戶應用程式之間傳遞IP包)
相比兩台宿主機直接通訊,多出了flanneld的處理過程,這個過程,使用了flannel0這個TUN設備,僅在發出IP包的過程中就要經過了三次用戶態到內核態的數據拷貝(linux的上下文切換代價比較大),所以性能非常差
原理如下:

以flanel0為例,作業系統將一個IP包發給flanel0,flanel0把IP包發給創建這個設備的應用程式:flanel進程(內核態->用戶態)
相反,flanel進程向flanel0發送一個IP包,IP包會出現在宿主機的網路棧中,然後根據宿主機的路由表進行下一步處理(用戶態->內核態)
當IP包從容器經過docker0出現在宿主機,又根據路由表進入flanel0設備後,宿主機上的flanneld進程就會收到這個IP包

flannel管理的容器網路里,一台宿主機上的所有容器,都屬於該宿主機被分配的「子網」,子網與宿主機的對應關係,存在Etcd中(例如Node1的子網是100.96.1.0/24,container-1的IP地址是100.96.1.2)
當flanneld進程處理flannel0傳入的IP包時,就可以根據目的IP地址(如100.96.2.3),匹配到對應的子網(比如100.96.2.0/24),從Etcd中找到這個子網對應的宿主機的IP地址(10.168.0.3)
然後flanneld在收到container-1給container-2的包後,把這個包直接封裝在UDP包里,發送給Node2(UDP包的源地址,就是Node1,目的地址是Node2)
每台宿主機的flanneld都監聽著8285埠,所以flanneld只要把UDP發給Node2的8285埠就行了。然後Node2的flanneld再把IP包發送給它所管理的TUN設備flannel0,flannel0設備再發給docker0

二、VXLAN模式(性能較好)

什麼是VXLAN?

VXLAN,即Virtual Extensible LAN(虛擬可擴展區域網),是Linux本身支援的一網種網路虛擬化技術。VXLAN可以完全在內核態實現封裝和解封裝工作,從而通過「隧道」機制,構建出覆蓋網路(Overlay Network)

VXLAN的設計思想是:
在現有的三層網路之上,「覆蓋」一層虛擬的、由內核VXLAN模組負責維護的二層網路,使得連接在這個VXLAN二nfcu網路上的「主機」(虛擬機或容器都可以),可以像在同一個區域網(LAN)里那樣自由通訊。
為了能夠在二nfcu網路上打通「隧道」,VXLAN會在宿主機上設置一個特殊的網路設備作為「隧道」的兩端,叫VTEP:VXLAN Tunnel End Point(虛擬隧道端點)
原理如下:

flanel.1設備,就是VXLAN的VTEP,即有IP地址,也有MAC地址
與UPD模式類似,當container-發出請求後,上的地址10.1.16.3的IP包,會先出現在docker網橋,再路由到本機的flannel.1設備進行處理(進站)
為了能夠將「原始IP包」封裝並發送到正常的主機,VXLAN需要找到隧道的出口:上的宿主機的VTEP設備,這個設備資訊,由宿主機的flanneld進程維護

VTEP設備之間通過二層數據楨進行通訊
源VTEP設備收到原始IP包後,在上面加上一個目的MAC地址,封裝成一個導去數據楨,發送給目的VTEP設備(獲取 MAC地址需要通過三層IP地址查詢,這是ARP表的功能)

封裝過程只是加了一個二層頭,不會改變「原始IP包」的內容
這些VTEP設備的MAC地址,對宿主機網路來說沒什麼實際意義,稱為內部數據楨,並不能在宿主機的二層網路傳輸,Linux內核還需要把它進一步封裝成為宿主機的一個普通的數據楨,好讓它帶著「內部數據楨」通過宿主機的eth0進行傳輸,Linux會在內部數據楨前面,加上一個我死的VXLAN頭,VXLAN頭裡有一個重要的標誌叫VNI,它是VTEP識別某個數據楨是不是應該歸自己處理的重要標識。
在Flannel中,VNI的默認值是1,這也是為什麼宿主機的VTEP設備都叫flannel.1的原因

一個flannel.1設備只知道另一端flannel.1設備的MAC地址,卻不知道對應的宿主機地址是什麼。
在linux內核裡面,網路設備進行轉發的依據,來自FDB的轉發資料庫,這個flannel.1網橋對應的FDB資訊,是由flanneld進程維護的
linux內核再在IP包前面加上二層數據楨頭,把Node2的MAC地址填進去。這個MAC地址本身,是Node1的ARP表要學習的,需
Flannel維護,這時候Linux封裝的「外部數據楨」的格式如下

然後Node1的flannel.1設備就可以把這個數據楨從eth0發出去,再經過宿主機網路來到Node2的eth0
Node2的內核網路棧會發現這個數據楨有VXLAN Header,並且VNI為1,Linux內核會對它進行拆包,拿到內部數據楨,根據VNI的值,所它交給Node2的flannel.1設備

三、host-gw模式(性能最高)

這是一種純三層網路的方案,性能最高

howt-gw模式的工作原理,就是將每個Flannel子網的下一跳,設置成了該子網對應的宿主機的IP地址,也就是說,宿主機(host)充當了這條容器通訊路徑的「網關」(Gateway),這正是host-gw的含義
所有的子網和主機的資訊,都保存在Etcd中,flanneld只需要watch這些數據的變化 ,實時更新路由表就行了。
核心是IP包在封裝成楨的時候,使用路由表的「下一跳」設置上的MAC地址,這樣可以經過二層網路到達目的宿主機