Kubernetes能保證鏈路層的連通性嗎?IaaS和SaaS平臺VXLAN對比分析

0x00 原由

昨天,我在研究容器網絡的時候,同事忽然問了我一個問題: Kubernetes 上的容器能支持跨主機二層通訊?這個問題一下把我問住了,我感受本身這幾天的容器網絡都白學了,我居然無言以對。。但這個問題也激起了我強烈的好奇心,我怎麼也要弄個明白。node

0x01 思考

在被問到這個問題後,我開始進行了思考。首先不管是 IaaS 平臺的網絡或者是 PaaS 平臺的網絡架構跨宿主機通訊的方式主要也就如下幾種方式:網絡

  • Host-gw
  • UDP
  • VXLAN
  • GRE
  • IPSec

其實從根本上看,我認爲只有 Overlay 網絡和 Host-gw 這兩種。Overlay 在我看來就是和隧道協議的原理是差很少的,就是在承載網絡協議上面再定義新的協議。而 Host-gw 則是經過配置路由了,使宿主機成爲一個路由器,像是把網絡架構從三維壓縮到了二維,從而讓容器和宿主機展開在同一平面上。架構

但因爲 Host-gw 經過宿主機進行了路由轉發, 天然兩個宿主機上把原始容器的 mac 地址也修改了,無疑是沒法進行二層通訊的。而 UDP 封裝的是三層的數據包,因此也是沒法進行鏈路層通訊的。那麼只剩下 VXLAN 了。tcp

VXLAN 相比 UDP 和其餘的一些隧道協議的好處如數據包內核態封裝解封裝,24位 VXLANID,支持組播和二層通訊等等。因此我把但願所有寄託在 VXLAN 上了。加上以前有搭建過 OpenStack 而且平時也常用雲主機,同一 VPC 內的雲主機能夠二層通訊這我是知道的。因此我認爲在 Kubernetes 上使用 VXLAN 也是能夠二層通訊的。學習

然而,事實並無這麼簡單。首先讓咱們看一下 IaaS 平臺上 VXLAN 是如何工做的。spa

0x02 VXLAN in OpenStack

協議圖

在 IaaS 平臺上,VXLAN 的協議格式以下圖所示:插件

clipboard.png
能夠看到跨宿主機通訊的報文就是 外層數據幀 + VXLAN 頭 + 內層數據幀。
那麼問題來了,兩臺虛擬機通訊,一臺是是 A,一臺是 B,他們通訊存在以下問題:blog

  1. A 往 B 發數據時,A 是怎麼知道 B 的 mac 地址的呢?
  2. 誰能知道 A 和 B 的宿主機的 IP 地址?
  3. 誰來封裝和解封裝 A 和 B 的數據包?

答案是 VTEP,全部宿主機上的 VTEP 都在一個組播組內,他們之間經過組播通訊,因此上面的這幾件事都是 VTEP 負責幹。那麼天然 VTEP 知道各臺虛擬機在哪臺宿主機上了,不知道就在組播組內問一下,而後本身學習記住 mac 地址。以下圖所示:進程

clipboard.png

在 VTEP 的幫助下,各個虛擬機就能達到了跨宿主機通訊的目的。ip

0x03 VXLAN in kubernetes

Kubernetes 上的網絡管理須要經過第三方的插件,如 Flannel,weave,calico 等。這裏咱們使用 Flannel VXLAN。在Kubernetes 上使用 VXLAN 一樣也要新建一個 VTEP 設備,如 flannel.1。

本覺得,在 IaaS 平臺上,使用 VXLAN 協議能夠跨主機二層通訊,那麼一樣在 Kubernetes 上 使用 VXLAN ,容器也能夠實現二層通訊啦?然而事實證實我仍是太年輕了。

在容器裏面用 tcpdump 抓包發現,內層報文的源 mac 地址和目的 mac 地址並非容器的的 mac 地址,而是源宿主機和目標宿主機 flannel.1 的 mac 地址,以下圖所示:

clipboard.png

這就讓人很困惑了,這又是爲啥呢。原來 VTEP 是個鏈路層的端點設備,在 OpenStack 等 IaaS 平臺上可能是用 OpenvSwitch 來實現 VTEP 的功能,OpenvSwitch 的功能很是強大,他能夠自動的學習各個宿主機上的虛擬機的 mac 地址,而且經過 openflow 協議的流表作數據包的操做。

而在 Kubernetes 上就不同了, VTEP 他並非經過組播的方式來學習容器的 Mac 地址。而是每臺 Kubernetes node 啓動時,flannel 進程會把他的子網, flannel.1 網卡 mac 地址寫入到 Etcd 裏面,並下發到每臺 node 上,從而每臺主機上都會創建發往目標網段的路由,並由 flannel.1 發出。以下圖所示:

clipboard.png

然而此時 flannel.1 只知道發送目標 flannel.1 的 mac 地址,並不知道對方的宿主機 ip,那麼怎麼封裝外層幀呢?這個時候 flannel 設備會查到 FBD,根據 mac 地址找到對方的宿主機地址 ip。同時,VTEP 還把 VNI 設置爲 1,這個也是 VTEP 識別是否是歸本身處理的數據幀的一個重要的標識,並最終組裝成以下所示的包發往對方:

clipboard.png

那麼也就能夠解釋爲何內部數據幀的 mac 地址爲何是 VTEP 設備的 mac 地址了。

0x04 結論

至此,咱們能夠得出結論了。Kubernetes 沒法保證二層網絡互通,由於 flannel.1 設備並無學習到容器的 mac 地址,因此若是一個容器 A 發往容器 B ,那麼容器 A 並不知道容器 B 的 mac 地址。
那麼若是想要實現容器跨主機二層通訊,那麼可能須要像 OpenvSwtich 同樣,全部的 VTEP 設備加入到一個組播組中,而且要具備學習 mac 的能力。

0x05 總結

VXLAN 的一些功能 flannel 都沒有用到,好比flannel 上 VXLAN 的VNI 都是設置爲 1,沒法對網絡作一個隔離。總的來講在 flannel 使用 VXLAN更多的只是做爲 UDP 模式的一種替代,只是把封裝、解封裝放在內核態了,而且從三層降爲二層。固然,通常狀況下容器網絡三層互通也夠用了。

相關文章
相關標籤/搜索