K8S Flannel容器跨主機通信淺析


k8s集群有多台宿主機的情況下,不同宿主機上的容器如何通過 ip地址進行相互訪問呢 ,下面就根據k8s的網絡模型,分析一下k8s集群容器的跨主機通信是如何實現的。

Flannel

Flannel是CoreOS推出的,是k8s的一種簡單的三層網絡方案。在k8s中可以借助這個網絡插件實現不同宿主機節點之前的跨主機通訊。

Flannel有三種實現,分別是:

  1. UDP
  2. VXLAN
  3. host-gw

UDP是Flannel最早采用的方法之一,但性能較差,因為其從用戶態到內核態的切換次數較為頻繁,所以現在主要用的是Linux內核本身就支持的VXLAN網絡虛擬化技術,下面會通過k8s的flannel插件來看看是 如何實現跨主機通訊的。

K8S實例

當前分別創建了三個虛擬機master、k8s-node1、k8s-node2當做k8s的三個節點。添加flannel插件:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

可以看到三個節點的ip:

  • master: 192.168.10.200
  • k8s-node1: 192.168.10.201
  • k8s-node2: 192.168.10.202

VXLAN 模塊會在現有的三層網絡之上覆蓋一層由它負責維護一個二層網絡,使得在這個二層網絡中的設備可以像在同一個局域網中一樣通信。VXLAN在宿主機上設置一個特殊的網絡設備叫作 VTEP,即:VXLAN Tunnel End Point(虛擬隧道端點)。VTEP設備的作用是負責在Linux內核中對二層數據幀進行封裝和解封。

每台宿主機上都會有一個名為flannel.1的設備,這個設備就是VXLAN的VTEP設備,如圖所示,k8s-node1上有一個flannel.1設備,它既有ip地址,又有mac地址。

在k8s集群中通過deployment_busybox.yml起了三個busybox的pod,一個在k8s-node1,兩個在k8s-node2。

現在,通過k8s-node1上的pod中的容器(下面用container1代替)訪問在k8s-node2上的pod中的容器(下面用container2代替),基於VXLAN的跨主機通信流程圖如下所示。

container1的ip是10.244.5.2/24,它要去訪問container2的ip是10.244.6.4/24。

首先進入container1,通過route -n查看容器內部的路由表

請求的ip是10.244.6.4,匹配第二條路由規則,走etho設備,而etho設備以Veth Pair的方式連接在k8s-node1的cni0網橋上,同個宿主機中docker容器通信是走docker0網橋,在k8s集群中替換為cni0網橋,作用和docker0網橋類似,都是二層交換設備。請求會通過cni0網橋到達宿主機上,而k8s-node1節點的路由表如下所示

10.244.6.0這條記錄是在節點加入Flannel網絡的時候,flanneld這個進程在路由表中添加的,請求匹配到 10.244.6.0 這條規則,走到flannel.1這個VETP設備,經過flannel.1這個設備轉發到地址是10.244.6.0的網關。而10.244.6.0恰恰就是k8s-node2上flannel.1設備的ip地址。

既然是要組成二層網絡,所以flannel.1 VETP設備接收到原始ip包后,要加上目的mac地址封裝成二層數據幀。獲取ip對應的mac地址就需要通過ARP,flanneld進程在節點加入Flannel的網絡時已經幫我們在ARP表中插入了一條ARP記錄。

可以看到10.244.6.0這個ip對應的mac地址是6a:2f:7d:e5:3f:2e。獲取目的mac地址之后,就可以得到一個二層數據幀。

但現在得到的二層數據幀還無法在宿主機的網絡中傳輸,因為現在只有目的VETP設備的mac地址,而源宿主機需要目的宿主機的ip和mac地址。所以Linux內核會把這個二層數據幀前面加一個VXLAN頭,封裝到一個UDP包中從宿主機中發送出去,VXLAN頭的作用是標識這個被包裹的數據幀是供VXLAN使用的。那么如何獲取目的宿主機的ip和mac地址呢。宿主機上會有一個FDB表,它和ARP表的區別是ARP表是三層轉發,而FDB表用於二層轉發,flannel.1在這里相當於起到一個二層網橋設備的作用。

我們在k8s-node1上通過之前獲取到的目的VETP設備的mac地址可以查詢到目的宿主機的ip是192.168.10.202,而目的宿主機的mac地址可以通過k8s-node1的正常ARP學習得到,並不需要特意維護一份,所以最終得到在宿主機網絡中傳輸的二層數據幀格式如下所示

k8s-node2節點的ens33網卡接收到這個請求之后對數據幀進行解包,Linux內核會根據該數據幀攜帶的VXLAN Header中的信息將內層包裹的VETP設備的二層數據幀轉到k8s-node2上的flannel.1設備,然后flannel.1會再次對數據幀進行解包,拿到k8s-node1節點容器要發送請求的內容,根據路由表把請求轉到cni0網橋,最終到達container2容器。

以上就是個人對k8s容器跨主機通信實現的理解,如果有誤,可以在評論區指出,謝謝~!

參考鏈接

轉發於網絡


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM