flannel原理之udp模式解析

2021-10-11 18:26:29 字數 3581 閱讀 3231

flannel一共有udp、vxlan、host-gw三種工作模式,如果開啟了directrouting的話,會使用vxlan和host-gw組合,不跨網段就使用host-gw,跨網段就使用vxlan。對於host-gw和vxlan我們在前面的文章中有過簡單地介紹,在這篇文章我們來分析一下flannel的udp模式,雖然這種模式現在基本上已經不在生產上用了,但通過對udp模式的了解,可以讓我們更好地理解linux中的虛擬網路裝置tun,以及為我們提供一種在使用者態干涉協議棧資料的思路。

當flannel以udp模式執行的時候,每個節點會有兩個守護程序以及乙個binary檔案:

另外,在每個節點還會:

下面一步步地解釋上面的部件是怎麼聯動起來並完成跨主機的pod之間的通訊的,在下面我們建立的tun裝置名為tun0。

首先介紹一下準備的環境:

host1:

物理網絡卡eth0 ip:10.57.4.20;linux veth裝置veth1,沒有設定ip位址;linux tun裝置tun0,設定了ip為10.244.1.1

主機路由三條,一條是預設閘道器;另外兩條直連路由,分別到pod1和去往10.244.0.0/16

有乙個容器叫pod1,位址為10.244.1.3

host2:

物理網絡卡eth0 ip:10.57.4.21;linux veth裝置veth1,沒有設定ip位址;linux tun裝置tun0,設定了ip為10.244.2.1

主機路由三條,一條是預設閘道器;另外兩條直連路由,分別到pod2和去往10.244.0.0/16

有乙個容器叫pod2,位址為10.244.2.3

另外在兩主機上都:

下面我們將通過乙個例子來詳細說明資料報的傳送和接收的全過程,這裡binary檔案flannel的工作就不再說明了,這並非本文的重點。

我們假設pod2有乙個web服務在執行,當我們從pod1傳送乙個http請求給pod2時,會經歷以下步驟:

資料報從pod1的使用者程序出來,進入pod1的協議棧,協議棧發現要去往目的地並非在相同網段,於是設定了下一跳為預設閘道器169.254.2.2,通過arp查到預設閘道器的ip對應的mac為主機veth1的mac位址,於是把veth1的mac位址填進目標mac位址,完成mac頭的封裝,把包傳送到veth1,進入主機host1的網路協議棧。

資料報在host1的網路協議棧經過route判斷,發現目標位址10.244.2.3並非本機位址,因為本機開啟了路由**,所以走forward鏈。

主機協議棧在主機路由中為資料報尋找合適的路由,匹配到去往10.244.0.0/16網段的包應該走tun0,於是從tun0**出去。

tun0是乙個linux tun裝置,從協議棧收的包,會被另一端的使用者程序收到,在這裡tun0的另一端由flanneld程序開啟(就是開啟了/dev/net/tun這個檔案),於是flanneld收到了資料報。

flanneld檢視資料報的ip頭,發現目的地是10.244.2.3,於是從自己的路由中找去這個目的地下一跳,從kube-flannel傳來的資訊指示10.244.2.0/24這個子網在主機10.57.4.21上(這一步已經在kube-flannel和flanneld程序啟動後就立刻完成了),於是flanneld程序經過一些必要的處理後,把從tun0來的資料報(包括tcp頭、ip頭)當成資料,通過開啟的udp埠發往10.57.4.21的udp8285埠。

這時候由pod1的協議棧發出來的包,已經變成了另乙個包的資料區的資料,從host1的eth0出來的資料報的結構如下:

主機網段按正常的流程把資料報傳輸到了host2的eth0網絡卡上,來看看接收的全過程:

eth0接收到資料報經過一些必要的處理後,扔到上層網路協議棧,在route階段,協議棧發現目標位址為本機位址,所以走input鏈。

經過協議棧層層的剝頭處理,最終host2的使用者態程序flanneld會收到這個包,因為經過協議棧的處理,到flanneld手裡的資料已經沒有了mac頭、ip頭、和udp頭,只剩下資料區了。

flanneld根據自己執行的機制,把來自udp埠的資料經過必要的處理後(例如ttl遞減,重新計算校驗和等)寫到/dev/net/tun檔案,然後對端的tun0會立刻接收到資料,此時tun0接收到的資料如下所示:

tun0接收到資料報,又會再走回主機的網路協議棧,在主機的網路協議棧的routing判決時,發現目標位址為10.244.2.3,並非本機位址,而主機又開啟了路由**,於是走forward鏈。

主機協議棧在主機路由中為資料報尋找合適的路徑,匹配到去往10.244.2.3有一條直連路由veth1,於是從veth1**出去。

veth1的傳送會觸發另一端的接收,veth0接收到後,扔到pod2上層的網路協議棧,經過routing判決,發現是本機位址,送往上層協議,最由把資料給到開啟80埠的web服務。

從10.244.2.3回包的流程也類似。

可以看到,flannel的udp模式在一次跨主機的pod與pod通訊的過程中,需要兩次切換使用者態與核心態,所以效能其實遠低於vxlan模式,雖然vxlan模式用的也是udp協議,但因為是在核心態完成資料報的處理,所以效能要遠高於udp模式。

在flannel的原始碼中,flanneld是由c語言直接實現的,關鍵**在/backend/udp/proxy_adm64.c,而kube-flannel則是由go語言實現的,關鍵部分在/backend/udp/cproxy_adm64.go。

proxy_adm64.c中最關鍵的就是tun_to_udp和udp_to_tun,光是看名字就已經明白了用途,而且**還賊精簡:

static

inttun_to_udp

(int tun,

int sock,

char

*buf, size_t buflen)if(

!decrement_ttl

(iph)

)sock_send_packet

(sock, buf, pktlen, next_hop)

;_active:

return1;

}static

intudp_to_tun

(int sock,

int tun,

char

*buf, size_t buflen)

tun_send_packet

(tun, buf, pktlen)

;_active:

return1;

}

不明白為什麼flannel還要無端實現乙個udp模式,據說是因為作者實現udp模式時,linux的核心還不支援vxlan,但我去網上查了一下,linux核心從3.7開始支援vxlan,到3.12開始對vxlan已經完備:

而3.7是2023年底發布的,3.12是2023年2月發布的,flannel**的初次提交是2023年,應該不是這個原因,而且從實現上來說,明顯是vxlan更容易實現。

歡迎關注滴普科技官網 www.deepexi.com

通訊原理之UDP協議(四)

udp是傳輸層協議,和tcp協議處於乙個分層中,但是與tcp協議不同,udp協議並不提供超時重傳,出錯重傳等功能,也就是說其是不可靠的協議。2.1.udp埠號 由於很多軟體需要用到udp協議,所以udp協議必須通過某個標誌用以區分不同的程式所需要的資料報。埠號的功能就在於此,例如某乙個udp程式a在...

socket程式設計學習之UDP模式

1 目的 根據udp程式設計模式 編寫乙個可以進行通訊的程序。2 編寫檔案主要包括 3 各個檔案詳細 如下 公共標頭檔案 utili.h include include include include include define buffer max size 256 char sendbuf b...

UDP打洞原理

許多p2p軟體比如skype,qq,電驢之類需要不同內網的兩台機子進行通訊,而路由器的nat機制決定了內網訪問外網容易,而外網訪問內網困難,那如何才能做到這一點呢?有辦法 打洞 具體實現方法需要一台伺服器,現在假設兩台內網pc,a和b想用埠40000通訊,閘道器分別為nata,natb.伺服器為s,...