什麼原因讓Kubernetes放棄Libnetwork技術?
自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使用我們的橋)將會消失。
鏈接:https://kubernetes.io/blog/2016/01/why-kubernetes-doesnt-use-libnetwork/
※如果使用Docker後,還需要OpenStack嗎?
※Kubernetes是什麼?為什麼也稱為K8S?
TAG:架構師技術聯盟 |