通過借鑒他們在這一技術領域十年的經驗,谷歌云平臺團隊撰寫了一系列的文章分享其對容器的看法。谷歌的前兩篇文章提供了關于這個主題的總覽。這兩篇文章解釋了容器集群和他們所定義特征背后的邏輯。之后又向讀者展示了如何在Kubernetes上應用這一切。
容器能夠帶來一系列的好處。包括更簡單的部署模型,快速可用性和微服務架構理想的基礎設施層。像Docker之類的容器產品更關注于在單一計算機上操作。這就產生了協調多個容器的需求。或者用高級資深工程師和Kubernetes聯合創始人Joe Beda更喜歡的說法,“即興爵士樂表演”的管理需求,這個說法能夠更好地反映出容器管理對“實時條件和輸入”的反應。
像Kubernetes這樣的容器集群提供了與集群管理、網絡和命名有關的服務。他們“創建了一個抽象的層次,讓開發人員和管理員可以將需要改進的服務作為一個整體,改進其行為和性能,而不是服務的某個容器組件或基礎設施資源”。
隨著容器數量的迅速增加,容器協調的需求也隨之迅速地變得顯而易見。谷歌就是個極端的例子,每秒要啟動7000個容器,或每周要啟動20億個。這就是對容器集群的需求。
除了其他的要求之外,谷歌構建的容器集群還必須能夠做到在保持可用的狀態下完成更新,可擴展并且便于操控和監控。通過滿足這些要求,谷歌收益匪淺。首先,可以構建有清晰的合約和邊界的微服務。然后,清晰的邊界讓小型工程團隊能夠保持軟件的可管理和可擴展。容器集群具有自愈能力和無摩擦的水平擴展能力,并且有著高效的資源利用率。“集群運維團隊和應用運維團隊角色” 的專業化能力是另一個隱含的好處。Joe Beda舉例提到,“GMail的運維和開發團隊很少需要與集群運維團隊直接對話”。開發人員可以將注意力集中在構建服務上,而不需要考慮底層的基礎設施問題。
“優秀容器集群的要素”
Joe還分享了“優秀的容器集群管理器所需的要素”。包括動態的容器配置,以集合方式思考以及集群內的連接。
動態容器配置就是在考慮容器應該如何運行以和運行在何處的公開意向的前提下,找到一個可以運行給定載荷的位置。這是一個背包問題的實例。每個容器都有其自身的限制,如何在有限的可用計算資源內匹配各個容器呢?在安排給定的載荷時,集群必須要考慮可用容量(如CPU、RAM等),特殊的硬件需求以及實時變化的條件(如故障、自動擴展等)。Kubernetes用Pod解決了這個問題:
Pod(和一群鯨魚(a pod of whales)或豌豆莢(pea pod)里的含義一樣)由一組相互關聯的共享容量的Docker容器構成。Pod模型化為容器化環境下,特定于應用程序的一個“邏輯宿主”。其中可能包含一個或多個相互關聯并緊密耦合的容器——在前容器(pre-container)世界,他們會執行在同一個物理或虛擬主機上。
第二個要素是提供以集合方式思考的可能性。Kubernetes通過提供標簽和復制控制器使其成為可能。每個Pod可以有一系列的標簽,每個標簽是一個鍵值對。Pod通過標簽分組,例如根據應用層級或地理位置。之后標簽的使用可以有多種方式,例如由服務或復制控制器使用。復制控制器,顧名思義,用于保證大量的Pod拷貝能夠一直保持活動,從而為橫向擴展活動提供幫助。
Kubernetes標簽,來自于文章“是什么造就了容器集群?”
成功的容器集群的第三個要素是通信。當有多個容器,進而有多個微服務存在時,通信就成為了一個關鍵的組件。為了在無需知道它們各自的容器實際運行位置的情況下,微服務之間也可以互相通信,好的容器集群應該提供一個命名解析系統。命名解析系統在容器啟動或遷移之后能夠立即了解到全部變化是十分重要的。Kubernetes在標簽和Watch API模式的幫助下,提供了輕量級的服務發現方案。受Google Chubby論文的啟發,該模式提供了一種從服務傳遞異步事件的方式。Kubernetes團隊意識到并不是所有的客戶端都會為了使用這個API而重寫。因此Kubernetes提供服務代理的概念來處理這類場景。
[服務代理]是一個簡單的網絡負載均衡器/代理,以單一穩定的IP/端口形式暴露在網絡中,可以幫助完成命名查詢。
簡而言之,谷歌云平臺團隊將容器集群定義為:
一個動態配置和管理容器的系統,以Pod的形式組合在一起,連同所有的相互連接和通信渠道,運行在節點之上。
谷歌向容器化的轉移開始于將cgroups(控制群組的簡寫)加入Linux內核,以隔離一個進程集合的資源使用。通過簡化容器技術,Docker讓更大范圍的社區采用了容器技術,從而使這種技術得以推廣。