Kubernetes 系列 一 容器網絡

我們知道容器是使用 Linux 的 Namespace 隔離開的進程。不同容器的網絡環境是使用 Network Namespace 隔離的。那麼一臺主機上兩個獨立的 Network Namespace 空間內的容器是如何通信的呢?

我們知道在一臺主機上啓動的兩個不同的服務之間是可以直接使用 127.0.0.1 或者 localhost 通信的,是因爲他們同處在一個 Network Namespace。而容器之間的 Network Namespace 導致他們擁有自己的 IP 和端口,所有也就無法使用 localhost(127.0.0.1)進行通信了。

既然不同容器的 IP 是不一樣的,我們可以把不同的容器比作是不同主機上的進程。如果需要兩臺主機進行通信,那麼需要使用一根網線將兩臺主機連接起來;如果需要多臺主機間互相通信,則需要將它們都連接在一臺交換機上

這臺在 Docker 裏的 “交換機” 叫做 docker0 網橋。所有的容器需要使用 “一根網線” 連接在 docker0 網橋上,這跟網線叫做 Veth Pair 虛擬設備

“交換機” 有了,也用 “網線” 將主機和 “交換機” 連接上了,那麼容器之間就可以通信了。

docker0 網橋可以理解爲交換機設備。交換機是在二層網絡上通過 ARP 廣播(Address Resolution protocol)獲取 IP 地址對應的 MAC 地址。docker0 也是一樣,容器收到 docker0 的 ARP 請求後會將自己的 MAC 地址返回給 docker0。

Veth Pair 虛擬設備可以理解爲是網線,我們知道在網線一頭寫入的數據將會傳輸到另一頭。Veth Pair 虛擬設備也是一樣,在一頭寫入的數據將會傳輸到另一頭,而 Veth Pair 的 “兩頭” 指的是兩張虛擬網卡。

我們來看下容器間通訊的示意圖:

容器的 eth0 網卡和插在 docker0 上的網卡 vethxxxx 正是那根連接容器和虛擬機的 “網線”(Veth Pair 虛擬設備)。

上面我們講解的是同一臺主機上的容器之間互相通訊的過程。而如果某臺主機上的容器需要和其他主機通信呢?

我們還是一樣做如下的類比:

如果某臺主機需要訪問到其他交換機集羣的主機,那麼就需要路由器來處理三層網絡了。

那從容器的視角上看路由器是什麼呢?是在宿主機上的 eth0 網卡。上述的類比可以增加一條:

我們知道,當交換機通過 IP 無法找到對應的 MAC 地址時,就將數據包轉發給上層的路由器,由路由器處理數據包。

在容器的視角里則是:當 docker0 網橋找不到對應的 MAC 地址時,將數據包轉發給宿主機的 eth0 網卡。

其示意圖如下:

****如果某臺主機上的容器需要和**其他主機上的容器通信是怎樣做到的呢?**例如下圖中的 Container 1 需要訪問 Container 3,我們將宿主機之間的容器通信過程叫做的跨主通信。

容器的跨主通信僅有 eth0 網卡是不夠的,因爲 eth0 網卡無法記錄其子網有哪些(可以將所有容器通過 docker0 網橋組成了子網)。這個時候就得提到 flannel 項目,flannel 項目在每臺宿主機上都有安裝一個 flanneld 進程,正是這個進程來做主機間的數據包轉發的。

flanneld 在從 etcd 中讀取每臺宿主機和子網的對應關係,從而知道將數據包發送給哪臺數據包,而 flanneld 在每臺宿主機上都監聽着 8285 端口,只需要將數據封裝成 UDP 包發送給對應宿主機的 8285 端口就行。

封裝爲 UDP 包爲最早期 flannel 項目的實現方式,VXLAN 方式爲在宿主間打通一條隧道進行通訊,逐漸取代了 UDP 方式。

而在 Kubernetes 並沒有使用 Docker 的 Docker0 網橋來進行容器間的通訊,取而代之的是實現了一套與 Docker0 網橋功能幾乎一樣的 CNI 網橋。同時 Flannel 項目直接內置到 CNI 插件裏了。

在部署 Kubernetes 時,其中一步就是安裝 CNI 包。在 CNI 包裏有創建網絡設備的二進制文件,例如 bridge、ipvlan 等,還有負責分配 IP 地址的二進制文件 dhcp,還包括有 flannel 開源社區維護的一些組件。

kubernetes 的 CNI 插件使得容器間訪問,跨主機容器間訪問,容器自己訪問自己都是互通的,下節將詳細帶來 CNI 插件的實現過程。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/GMFwTUMOEitKJkAS9E5ROQ