docker bridge 到 k8s pod 跨節點網絡通訊機制演進

2020 還沒來得及品味就即將過去一個季度,願剩下的時光不被辜負。進入正題,docker container是單進程模式,可以解決一些單一的問題,在現實中,咱們經常須要多個進程放在一個「盒子」裏、或者多個節點共同完成通訊過程,接下來,說下這個過程的網絡通訊是如何實現的?
css


一、docker 網絡模式
能夠經過以下命令行查看docker網絡模式
[root@localhost ~]# docker network lsNETWORK ID NAME DRIVER SCOPEc250329fad3c bridge bridge localc7c3d1f77969 compose_extnetwork bridge local199b85fbf2fa host host localb488be9da3d6 none null local
  • 共享主機網絡模式 - hostjava

host指的是共享主機的網絡和端口,可是破壞了 container 的隔離性;node

  • 無網絡模式 - nonenginx

其中無網絡模式是指加入此模式下的容器都不能通訊,比較雞肋;web

  • 自定義docker

自定義主要用於實現DNS解析和服務發現,特殊場景下定製使用;bash

  • 默認網絡模式 - bridge微信

網橋是 docker 默認網絡模式,也是平時用的最多的一種,這裏主要對 docker 的 bridge 模式作詳細講解。網絡


二、docker 橋接如何實現同一個宿主機不一樣容器之間的通訊
       其實主要用到兩個技術知識點:
  • docker啓動後創建名爲docker0的虛擬網橋。
  • 容器啓動時在主機上建立一對虛擬網卡veth pair設備。這一對虛擬設備完成一組數據完整流通的鏈路,數據從一個設備進入,從另外一個設備出來。容器中重命名爲eth0,宿主機上的以veth*顯示並插在docker0網橋上。能夠經過以下命令查看,docker0上插了 veth42f3f11 和 vethe8589bd 兩張虛擬設備,見(a)圖。
[root@localhost ~]# brctl showbridge name bridge id STP enabled interfacesbr-c7c3d1f77969 8000.02429160f0dd no docker0 8000.02420a13dd3a no veth42f3f11 vethe8589bd



(a)
那麼你可能會有疑問,多個容器之間又是如何通訊的呢?以下圖所示:

(b)
架構

其原理也很是簡單,如圖(b)所示,container1 ping container2(172.0.0.3)網絡時,同一宿主機中的兩個容器網絡默認是互通的,其中docker0扮演二層交換機的角色。


經過命令查看container路由信息表,以下所示:
bash-4.4# routeKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Ifacedefault 172.17.0.1 0.0.0.0 UG 0 0 0 eth0172.17.0.0 * 255.255.0.0 U 0 0 0 eth0bash-4.4#
container1 訪問172.17.0.3匹配到第二條路由規則;網關是0.0.0.0,這是一條直連規則,意思是匹配到該規則的網絡地址通過本機eth0網卡,再經過二層網絡doceker0 直接發送到目的主機。docker0之因此可以作到從veth虛擬設備中接受數據和發送數據,是由於veth至關於docker0網橋的從設備,故docker0可以直接處理來自於veth上網絡數據包,進而直接轉發到container2,就完成從一個容器到另一個容器的通訊。見(b)圖所示。

若是訪問外部網絡,也很是簡單,數據包先通過docker0網卡,根據宿主機路由規則鏈接到eth0網卡,轉發到外部網絡。見(c)圖所示。

(c)

docker 在默認網絡設置狀況下,節點A 的docker0 跟節點B 的docker0 沒有任何關聯,網絡也是不通的,這就致使不能知足咱們跨節點通訊要求。Kubernetes 的 Pod 又是經過何種方式實現的呢?


三、pod 通訊機制

若是要說明 pod 的通訊機制,要從一個鏡像提及,在 kubectl 安裝kubernetes 的時候必定會看到 k8s.gcr.io/pause 這個鏡像,不知道有沒有疑問,這個究竟是幹嗎的?其它幾個鏡像顧名思義,可是這個【暫停】是什麼?沒錯,他就是用來 hold 一個 Pod 內部多個 Container 網絡通訊。

若是在計算節點上運行 docker ps 命令
[root@k8s-client1 ~]# docker ps |grep sp-nginxe34adacf9be1        0a81924719d1             "/usr/local/nginx/b…"   3 seconds ago       Up 2 seconds                            k8s_sp_nginx-deployment-84b5d9cb66-hkfp6_default_5c27af26-6b7e-11ea-8d03-70fd45ac3f1f_0f245174b9a51        0a81924719d1             "/usr/local/nginx/b…"   5 seconds ago       Up 4 seconds                            k8s_sp_nginx-deployment-84b5d9cb66-zfbhr_default_5c281ef0-6b7e-11ea-8d03-70fd45ac3f1f_0


如上所示,你能夠看到在建立 nginx pod 過程當中,不只建立了一個nginx 容器,並附帶了一個 pause 容器,並且 pause 容器是在 nginx容器以前建立的,這個被暫停的容器把全部的容器收納到一塊兒,一個基礎容器,惟一目的就是保存全部的命名空間。容器中 pod 共享同一個 IP 地址。故同一個 Pod 中 Container 能夠作到直接經過 localhost 直接通訊,那麼同一個節點多個 Pod 之間如何通訊的呢?

(d)

pause 容器啓動以前,會爲容器建立虛擬一對 ethernet 接口,一個保留在宿主機 vethxxx(插在網橋上),一個保留在容器網絡命名空間內,並重命名爲eth0。兩個虛擬接口的兩端,從一端進入,另外一端出來。任何 Pod 鏈接到該網橋的 Pod 均可以收發數據。如(d)圖所示。



四、跨 node pod 通訊

跨節點 Pod 通訊,至關於建立一個整個集羣公用的【 網橋 】而後把集羣中全部的 Pod 鏈接起來,就能夠通訊了。

(e)

其中跨整個集羣的 Pod ip 是惟一的,當報文從一個節點轉發到另一個節點時,報文首先經過 veth,而後經過網橋,轉發到物理適配器網卡,最後轉發到其它節點的虛擬網橋,進而到達 veth 目標容器。如(e)圖所示。
其實現方式有 Flannel、calico、weave 等。
注意 k8s 的網橋跟 docker0  網橋功能相似,可是 k8s 並無複用 docker0 網橋,其緣由是 Kubernetes 爲了鏈接 infra 容器更加方便,而是從新實現了 CNI 網絡接口功能,它容許網絡插件使用 CNI 接口,好比 flannel,它自己實現也通過幾個過程,其本質上來講,是基於「隧道」機制實現。示意圖(f)所示:

(f)

五、總結

本文由淺到深的講解了 docker 網絡模式實現以及 Kubernetes Pod 跨節點之間通訊原理和實現方式。簡單介紹了dockers、Kubernetes網絡通訊方式,其內部經過網卡、迴環設備、路由表、iptables等實現,若是你是個喜歡深究的人,能夠研究下組網過程。


推薦


Kubernetes排障指南
Kubernetes裏的Service到底是如何工做的呢?
Kubernetes中如何使用ClusterDNS進行服務發現?
Kubernetes入門培訓(內含PPT)
從Ice到Kubernetes容器技術,微服務架構經歷了什麼?


原創不易,隨手關注或者」在看「,誠摯感謝!

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索