1.flannel的UDP模式
不同節點pod間通信(UDP模式)

發送流程
1.發送數據報文,發現是不同網段,但找不到路由,轉給默認網關cni0
2.cni0查看宿主機路由表:去往目的pod所在網段轉給tun設備flannel0,而后由flanneld進程截獲,由它指導內核封裝數據報文,由于flanneld進程在啟動之初會收集各pod網段與k8s節點網卡對應關系并傳給apiserver或etcd集群,同時規定flanneld進程凡是收到pod的數據報文都要轉給對應的節點網卡,flanneld查詢到源pod和目的pod所在的節點網卡地址后,指導內核生成路由規則,將報文轉給本節點網卡
3.報文從物理網卡進入公網傳給對端物理網卡
接收流程
1.物理網卡對報文外層進行解封,將原始報文暴露出來
2.物理網卡將解封后的原始報文轉交給flanneld進程(凡是給pod的報文都交由flanneld進程)而后指導內核將報文轉給對應的flannel0
3.flannel0查看路由表后,發現目的pod所在網段的網關為cni0
4.cni0將報文轉給pod
發送過程解析
到達宿主機以后,宿主機啟動路由表查詢過程。
#5.3.1:在k8s-1節點上查詢:

#5.3.2:flannel0為tun設備,發送給flannel0接口的RAW IP包(無MAC信息)將被flanneld進程接收到,flanneld進程接收到RAW IP包后在原有的基礎上進行UDP封包.UDP封包的形式為:172.12.1.11:src port -> 172.12.1.12:8285。
此時在flannel0上抓包:

#抓包的wireshark解包格式為:

#5.3.3:flanneld在啟動時會將該節點的網絡信息通過api-server保存到etcd當中,故在發送報文時可以通過查詢etcd得到10.244.1.7這個容器的IP屬于172.12.1.12。
#5.3.4:flanneld將封裝好的UDP報文從用戶空間發往Linux內核協議棧,然后經ens33發出,從這里可以看出網絡包在通過ens33發出前先是加上了UDP頭(8個字節),再然后加上了IP頭(20個字節)進行封裝,這也是為什么flannel0的MTU要比ens33的MTU小28個字節的原因(防止封裝后的以太網幀超過ens33的MTU而在經過ens33時被丟棄)
#此時在ens33上抓包:

#wireshark 解開包的形式如上。
此過程中flanneld的作用:
#UDP封包解包
#節點上的路由表的動態更新
UDP模式的缺點
相比于兩臺宿主機之間的直接通信,基于 Flannel UDP 模式的容器通信多了一個額外的步驟,即 flanneld 的處理過程。而這個過程,由于使用到了 flannel0 這個 TUN 設備,僅在發出IP包的過程中,就需要經過三次用戶態與內核態之間的數據拷貝,如下所示:

第一次:用戶態的容器進程發出的 IP 包經過 docker0 網橋進入內核態;
第二次:IP 包根據路由表進入 TUN(flannel0)設備,從而回到用戶態的 flanneld 進程;
第三次:flanneld 進行 UDP 封包之后重新進入內核態,將 UDP 包通過宿主機的 eth0 發出去。
此外,Flannel 進行 UDP 封裝和解封裝的過程,也都是在用戶態完成的。在 Linux 操作系統中,上述這些上下文切換和用戶態操作的代價其實是比較高的,這也正是造成 Flannel UDP 模式性能不好的主要原因。
浙公網安備 33010602011771號