1. 程式人生 > 其它 >k8s網路之Flannel網路

k8s網路之Flannel網路

一 簡介

Flannel是CoreOS團隊針對Kubernetes設計的一個網路規劃服務,簡單來說,它的功能是讓叢集中的不同節點主機建立的Docker容器都具有全叢集唯一的虛擬IP地址。

在預設的Docker配置中,每個節點上的Docker服務會分別負責所在節點容器的IP分配。這樣導致的一個問題是,不同節點上容器可能獲得相同的內外IP地址。並使這些容器之間能夠之間通過IP地址相互找到,也就是相互ping通。

Flannel的設計目的就是為叢集中的所有節點重新規劃IP地址的使用規則,從而使得不同節點上的容器能夠獲得“同屬一個內網”且”不重複的”IP地址,並讓屬於不同節點上的容器能夠直接通過內網IP通訊。

Flannel實質上是一種“覆蓋網路(overlaynetwork)”,也就是將TCP資料包裝在另一種網路包裡面進行路由轉發和通訊,目前已經支援udp、vxlan、host-gw、aws-vpc、gce和alloc路由等資料轉發方式,預設的節點間資料通訊方式是UDP轉發。

簡單總結flannel特點

1.使叢集中的不同Node主機建立的Docker容器都具有全叢集唯一的虛擬IP地址。

2.建立一個覆蓋網路(overlay network),通過這個覆蓋網路,將資料包原封不動的傳遞到目標容器。覆蓋網路是建立在另一個網路之上並由其基礎設施支援的虛擬網路。覆蓋網路通過將一個分組封裝在另一個分組內來將網路服務與底層基礎設施分離。在將封裝的資料包轉發到端點後,將其解封裝。

3.建立一個新的虛擬網絡卡flannel0接收docker網橋的資料,通過維護路由表,對接收到的資料進行封包和轉發(vxlan)。

4.etcd保證了所有node上flanned所看到的配置是一致的。同時每個node上的flanned監聽etcd上的資料變化,實時感知叢集中node的變化。

二 Flannel對網路要求提出的解決辦法

2.1 互不衝突的ip

1.flannel利用Kubernetes API或者etcd用於儲存整個叢集的網路配置,根據配置記錄叢集使用的網段。

2.flannel在每個主機中執行flanneld作為agent,它會為所在主機從叢集的網路地址空間中,獲取一個小的網段subnet,本主機內所有容器的IP地址都將從中分配。

如測試環境中ip分配:

1.master節點

2.node1

3.node2

在flannel network中,每個pod都會被分配唯一的ip地址,且每個K8snode的subnet各不重疊,沒有交集。

2.2 pod之間互相訪問

  • flanneld將本主機獲取的subnet以及用於主機間通訊的Public IP通過etcd儲存起來,需要時傳送給相應模組。
  • flannel利用各種backend mechanism,例如udp,vxlan等等,跨主機轉發容器間的網路流量,完成容器間的跨主機通訊。

三 Flannel架構原理

架構圖

各個元件的解釋:

Cni0:網橋裝置,每建立一個pod都會建立一對veth pair。其中一端是pod中的eth0,另一端是Cni0網橋中的埠(網絡卡)。Pod中從網絡卡eth0發出的流量都會發送到Cni0網橋裝置的埠(網絡卡)上。

Cni0裝置獲得的ip地址是該節點分配到的網段的第一個地址。

Flannel.1: overlay網路的裝置,用來進行vxlan報文的處理(封包和解包)。不同node之間的pod資料流量都從overlay裝置以隧道的形式傳送到對端。

Flanneld:flannel在每個主機中執行flanneld作為agent,它會為所在主機從叢集的網路地址空間中,獲取一個小的網段subnet,本主機內所有容器的IP地址都將從中分配。同時Flanneld監聽K8s叢集資料庫,為flannel.1裝置提供封裝資料時必要的mac,ip等網路資料資訊。

不同node上的pod的通訊流程:

  1. pod中產生資料,根據pod的路由資訊,將資料傳送到Cni0
  2. Cni0根據節點的路由表,將資料傳送到隧道裝置flannel.1
  3. Flannel.1檢視資料包的目的ip,從flanneld獲得對端隧道裝置的必要資訊,封裝資料包。
  4. Flannel.1將資料包傳送到對端裝置。對端節點的網絡卡接收到資料包,發現數據包為overlay資料包,解開外層封裝,併發送內層封裝到flannel.1裝置。
  5. Flannel.1裝置檢視資料包,根據路由表匹配,將資料傳送給Cni0裝置。
  6. Cni0匹配路由表,傳送資料給網橋上對應的埠。

四 通訊流程

4.1 pod1中的容器到cni0

Pod1與Pod3能夠互相ping通

Ping包的dst ip為192.20.1.43,根據路由匹配到最後一條路由表項,去往192.20.0.0/12的包都轉發給192.20.0.1。

192.20.0.1為cni0的ip地址。

4.2 cni0到flannel1.1

當icmp包達到cni0之後,cni0發現dst為192.20.1.43,cni根據主機路由表來查詢匹配項。

根據最小匹配原則,匹配到圖上的一條路由表項。去往192.20.1.0/24網段的包,傳送192.20.1.0閘道器,閘道器裝置是flannel.1。

4.3 Flannel.1

flannel.1為vxlan裝置,當資料包來到flannel.1時,需要將資料包封裝起來。此時的dst ip為192.20.1.43,src ip為192.20.0.51。資料包繼續封裝需要知道192.20.1.43 ip地址對應的mac地址。此時,flannel.1不會發送arp請求去獲得192.20.1.42的mac地址,而是由Linux kernel將一個“L3 Miss”事件請求傳送的使用者空間的flanned程式。Flanned程式收到核心的請求事件之後,從etcd查詢能夠匹配該地址的子網的flannel.1裝置的mac地址,即發往的pod所在host中flannel.1裝置的mac地址。Flannel在為Node節點分配ip網段時記錄了所有的網段和mac等資訊,所以能夠知道。互動流程如下圖所示:

flanned將查詢到的資訊放入master node host的arp cache表中:

到這裡,vxlan的內層資料包就完成了封裝。格式是這樣的:

簡單總結這個流程:

  1. 資料包到達flannel.1,通過查詢路由表,知道資料包要通過flannel.1發往192.20.1.0
  2. 通過arp cache表,知道了目的ip192.20.1.0的mac地址。

kernel需要檢視node上的fdb(forwarding database)以獲得內層封包中目的vtep裝置所在的node地址。因為已經從arp table中查到目的裝置mac地址為52:77:71:e6:4f:58,同時在fdb中存在該mac地址對應的node節點的IP地址。如果fdb中沒有這個資訊,那麼kernel會向用戶空間的flanned程式發起”L2 MISS”事件。flanneld收到該事件後,會查詢etcd,獲取該vtep裝置對應的node的”Public IP“,並將資訊註冊到fdb中。

當核心獲得了發往機器的ip地址後,arp得到mac地址,之後就能完成vxlan的外層封裝。

4.4 對端flannel.1

Node節點的eth0網絡卡接收到vxlan裝置包,kernal將識別出這是一個vxlan包,將包拆開之後轉給節點上的flannel.1裝置。這樣資料包就從傳送節點到達目的節點,flannel.1裝置將接收到一個如下的資料包:

目的地址為192.20.1.43,flannel.1查詢自己的路由表,根據路由表完成轉發。

根據最下匹配原則,flannel.1將去往192.20.1.0/24的流量轉發到cni0上去。

4.5 cni0到pod

cni0是一個網橋裝置。當cni0拿到資料包之後,通過veth pair,將資料包傳送給pod。檢視Node節點中的網橋。

在node節點上通過arp解析可以開出,192.20.1.43的mac地址為66:57:8e:3d:00:85

該地址為pod的網絡卡eth0的地址。

同時通過veth pair的配對關係可以看出,pod中的eth0是veth pair的一端,另一端在node節點行上,對應的網絡卡是vethd356ffc1@if3。所以,在cni0網橋上掛載的pod的veth pair為vethd356ffc1,即:

eth0@if50和vethd356ffc1@if3組成的一對veth,pair。其效果相當於將pod中的eth0直接插在到cni0上。所以簡單總結cni0轉發流量的原理:

  1. 首先通過arp查找出ip地址對應的mac地址
  2. 將流量轉發給mac地址所在eth0網的對應的veth pair埠
  3. veth pair埠接收到流量,直接將流量注入到pod的eth0網絡卡上。

五,不同後端的封裝

Flannel可以指定不同的轉發後端網路,常用的有hostgw,udp,vxlan等。

5.1 hostgw

hostgw是最簡單的backend,它的原理非常簡單,直接新增路由,將目的主機當做閘道器,直接路由原始封包。

例如,我們從etcd中監聽到一個EventAdded事件subnet為10.1.15.0/24被分配給主機Public IP 192.168.0.100,hostgw要做的工作就是在本主機上新增一條目的地址為10.1.15.0/24,閘道器地址為192.168.0.100,輸出裝置為上文中選擇的叢集間互動的網絡卡即可。

優點:簡單,直接,效率高

缺點:要求所有的pod都在一個子網中,如果跨網段就無法通訊。

5.2 UDP

如何應對Pod不在一個子網裡的場景呢?將Pod的網路包作為一個應用層的資料包,使用UDP封裝之後在叢集裡傳輸。即overlay。

上圖來自flannel官方,其中右邊Packer的封裝格式就是使用udp完成overlay的格式

當容器10.1.15.2/24要和容器10.1.20.2/24通訊時,

1.因為該封包的目的地不在本主機subnet內,因此封包會首先通過網橋轉發到主機中。

2.在主機上經過路由匹配,進入網絡卡flannel.1。(需要注意的是flannel.1是一個tun裝置,它是一種工作在三層的虛擬網路裝置,而flanneld是一個proxy,它會監聽flannel.1並轉發流量。)

3.當封包進入flannel.1時,flanneld就可以從flanne.1中將封包讀出,由於flanne.1是三層裝置,所以讀出的封包僅僅包含IP層的報頭及其負載。

4.最後flanneld會將獲取的封包作為負載資料,通過udp socket發往目的主機。

5.在目的主機的flanneld會監聽Public IP所在的裝置,從中讀取udp封包的負載,並將其放入flannel.1裝置內。

6.容器網路封包到達目的主機,之後就可以通過網橋轉發到目的容器了。

優點:Pod能夠跨網段訪問

缺點:隔離性不夠,udp不能隔離兩個網段。

5.3 Vxlan

vxlan和上文提到的udp backend的封包結構是非常類似的,不同之處是多了一個vxlan header,以及原始報文中多了個二層的報頭。

當初始化叢集裡,vxlan網路的初始化工作:

主機B加入flannel網路時,它會將自己的三個資訊寫入etcd中,分別是:subnet 10.1.16.0/24、Public IP 192.168.0.101、vtep裝置flannel.1的mac地址MAC B。之後,主機A會得到EventAdded事件,並從中獲取上文中B新增至etcd的各種資訊。這個時候,它會在本機上新增三條資訊:

1)路由資訊:所有通往目的地址10.1.16.0/24的封包都通過vtep裝置flannel.1裝置發出,發往的閘道器地址為10.1.16.0,即主機B中的flannel.1裝置。

2) fdb資訊:MAC地址為MAC B的封包,都將通過vxlan發往目的地址192.168.0.101,即主機B

3)arp資訊:閘道器地址10.1.16.0的地址為MAC B

事實上,flannel只使用了vxlan的部分功能,由於VNI被固定為1,本質上工作方式和udp backend是類似的,區別無非是將udp的proxy換成了核心中的vxlan處理模組。而原始負載由三層擴充套件到了二層,但是這對三層網路方案flannel是沒有意義的,這麼做也僅僅只是為了適配vxlan的模型。vxlan詳細的原理參見文後的參考文獻,其中的分析更為具體,也更易理解。

總的來說,flannel更像是經典的橋接模式的擴充套件。我們知道,在橋接模式中,每臺主機的容器都將使用一個預設的網段,容器與容器之間,主機與容器之間都能互相通訊。要是,我們能手動配置每臺主機的網段,使它們互不衝突。接著再想點辦法,將目的地址為非本機容器的流量送到相應主機:如果叢集的主機都在一個子網內,就搞一條路由轉發過去;若是不在一個子網內,就搞一條隧道轉發過去。這樣以來,容器的跨網路通訊問題就解決了。而flannel做的,其實就是將這些工作自動化了而已。

六 存在問題

1.不支援pod之間的網路隔離。Flannel設計思想是將所有的pod都放在一個大的二層網路中,所以pod之間沒有隔離策略。

2.裝置複雜,效率不高。Flannel模型下有三種裝置,數量經過多種裝置的封裝、解析,勢必會造成傳輸效率的下降。

原文連結: https://www.cnblogs.com/goldsunshine/p/10740928.html