自1.0版釋出以來,Kubernetes已經擁有了一種非常基本的網路外掛形式,大約與Docker的Libnetwork和容器網路模型(CNM)一起推出。與Libnetwork不同,Kubernetes外掛系統仍保留其“alpha”標識。
現在Docker的網路外掛支援已經釋出並得到支援,我們得到的一個明顯問題就是為什麼Kubernetes還沒有採用它。畢竟,供應商幾乎肯定會為Docker編寫外掛 我們都會更好地使用相同的驅動程式,對吧?
在進一步討論之前,重要的是要記住Kubernetes是一個支援多個容器執行時的系統,Docker只是其中一個。配置網路只是每個執行時的一個方面,所以當人們問“Kubernetes是否支援CNM?”時,他們的真正意思是“kubernetes是否支援使用Docker執行時的CNM驅動程式?”如果我們能夠跨執行時實現通用網路支援,那再好不了,但這不是一個明確的標的。
的確,Kubernetes並沒有在Docker執行時採用CNM/Libnetwork。事實上,我們一直在研究由CoreOS提出的替代容器網路介面(CNI)模型和App Container規範的一部分。為什麼?有許多原因,無論是技術還是非技術。
首先,Docker網路驅動程式的設計中有一些基本假設會給我們帶來麻煩。Docker有一個“本地”和“全域性”驅動程式的概念。本地驅動程式(如“橋”)是以單節點為中心的,不會執行任何跨節點協調。全域性驅動程式(例如“Overlay”)依靠Libkv(一個鍵值儲存抽象)來跨節點進行協調。這個鍵值儲存是另一個外掛介面,並且是非常低階的(鍵和值,沒有語意含義)。
要在Kubernetes叢集中執行諸如Docker overlay驅動程式之類的東西,我們需要叢集管理員執行一個完全不同的Consul實體,etcd或Zookeeper(請參閱多主機網路),否則我們將不得不提供我們自己的被Kubernetes支援的Libkv實現。
後者聽起來很有吸引力,我們試圖實現它,但是libkv介面是非常低階的,並且schema是在Docker內部定義的。我們不得不直接暴露底層的鍵值儲存,或者提供鍵值語意(在我們的結構化API之上,它本身是在鍵值系統上實現的)。由於效能,可擴充套件性和安全性原因,這兩者都不具有吸引力。最終結果是,整個系統將顯得更加複雜,但是使用Docker網路的標的應該是件簡化事情。
對於願意並能夠執行必要的基礎設施以滿足Docker全域性驅動程式並自行配置Docker的使用者,Docker網路應該“只是工作”。Kubernetes不會妨礙這樣的設定,無論專案的方向如何,該選項都應該可用。然而,對於預設安裝,實際結論是,這對使用者來說是一種不必要的負擔,因此我們無法使用Docker的全域性驅動程式(包括“Overlay”),這消除了使用Docker外掛的許多價值。
Docker的網路模型提出了許多對Kubernetes無效的假設。在Docker版本1.8和1.9中,它包含一個從根本上有缺陷的“發現”實現,導致容器中的/etc/hosts檔案損壞(docker#17190), 並且這不容易關閉。在版本1.10中,Docker計劃捆綁一個新的DNS伺服器,目前還不清楚這是否可以關閉。
容器級命名不是Kubernetes的正確抽象 -我們已經有了我們自己的服務命名,發現和系結的規則,並且我們已經有了我們自己的DNS樣式和伺服器(基於完善的SkyDNS)。捆綁的解決方案不足以滿足我們的需求,但也不是無法使用的。由於本地/全域性的劃分,Docker具有行程內和行程外(“遠端”)外掛。我們調查了是否可以繞過libnetwork(從而跳過上述問題)並直接驅動Docker遠端外掛。不幸的是,這意味著我們不能使用任何Docker行程內外掛,特別“bridge”和“overlay”,這再次消除了libnetwork的很多實用性。
另一方面,CNI在哲學上與Kubernetes更加一致。它比CNM簡單得多,不需要守護行程,並且至少可以跨平臺(CoreOS的rkt容器執行時支援它)。跨平臺意味著有機會啟用網路配置,這些配置將在執行時間內保持一致(例如Docker,Rocket,Hyper)。
它遵循UNIX做好一件事的哲學。 此外,包裝CNI外掛並生成更加定製的CNI外掛也很簡單 – 可以使用簡單的shell指令碼完成。 CNM在這方面要複雜得多。這使CNI成為快速開發和迭代的有吸引力的選擇。早期的原型已經證明,可以將kubelet中幾乎100%的當前硬編碼網路邏輯彈出到外掛中。
我們分析了為Docker寫一個Bridge的CNM驅動,執行CNI驅動,事實證明這非常複雜。
首先,CNM和CNI模型非常不同,所以沒有一個“方法”排隊。我們仍然有上面討論的全域性與本地和鍵值問題。假設這個驅動程式會宣告自己是本地的,我們必須從Kubernetes獲得有關邏輯網路的資訊。不幸的是,Docker驅動程式很難對映到像Kubernetes這樣的其他控制平面。具體而言,驅動程式不會被告知容器所連線的網路的名稱 只是Docker在內部分配的ID。這使得驅動程式難以映射回到另一個系統中存在的任何網路概念。
這個問題和其他問題已經由網路供應商提供給Docker開發人員,並且通常以“按預期工作”(lbnetwork#139,libnetwork#486,libnetwork#514,libnetwork#865,docker#18864)關閉,儘管它們使非Docker第三方系統更難以整合。
在整個調查過程中,Docker已經明確表示,他們對於偏離當前過程或委託控制的想法並不是很開放。這對我們來說是非常令人擔憂的,因為Kubernetes補充了Docker並增加了很多功能,但存在於Docker本身之外。由於所有這些原因,我們選擇投資CNI作為Kubernetes外掛模型。這會有一些不幸的副作用。他們中的大多數都相對較小(例如,Docker檢查不會顯示IP地址),但有些是重要的。
特別是,由Docker執行啟動的容器可能無法與Kubernetes啟動的容器進行通訊,如果網路整合商想要與Kubernetes完全整合,則必須提供CNI驅動程式。另一方面,Kubernetes將變得更簡單和更靈活,並且早期引導的許多醜陋(例如配置Docker使用我們的橋)將會消失。
隨著我們沿著這條道路前進,我們一定會保持眼睛和耳朵的暢通,以便更好地整合和簡化。如果您對我們如何做到這一點有想法,我們真的很想聽到他們,可以透過slack.k8s.io和郵件串列找到我們。
連結:https://kubernetes.io/blog/2016/01/why-kubernetes-doesnt-use-libnetwork/
關於Kubernetes技術內容和總結,請點選閱讀原文參考<Kubernetes技術和實戰總結>電子書,獲取更多技術內容,具體內容如下所示。
推薦閱讀:
溫馨提示:
請搜尋“ICT_Architect”或“掃一掃”二維碼關註公眾號,點選原文連結獲取更多電子書詳情。
求知若渴, 虛心若愚