本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Borg:Kubernetes 的前身
Google 在生產環境中執行容器化工作負載已有十多年。無論是像 Web 前端和有狀態伺服器這樣的服務作業,像 Bigtable 和 Spanner 這樣的基礎設施系統,還是像 MapReduce 和 Millwheel 這樣的批處理框架,Google 的幾乎所有內容都以容器形式執行。今天,我們揭開了 Borg 的面紗,Borg 是 Google 長期以來傳聞的內部面向容器的叢集管理系統,並在學術計算機系統會議 Eurosys 上釋出了詳細資訊。您可以在此處找到該論文。
Kubernetes 直接繼承了 Borg 的血統。許多在 Google 從事 Kubernetes 工作的開發人員都曾是 Borg 專案的開發人員。我們將 Borg 的最佳思想融入了 Kubernetes,並試圖解決使用者多年來在 Borg 中發現的一些痛點。
為了讓您對此有所瞭解,以下是 Kubernetes 的四個功能,它們來自我們使用 Borg 的經驗:
- Pod。Pod 是 Kubernetes 中的排程單元。它是一個資源包,其中執行一個或多個容器。屬於同一個 Pod 的容器保證會一起排程到同一臺機器上,並且可以透過本地卷共享狀態。
Borg 有一個類似的抽象,稱為 alloc(“資源分配”的縮寫)。Borg 中 alloc 的常見用途包括:執行一個 Web 伺服器,該伺服器生成日誌,同時執行一個輕量級日誌收集程序,將日誌傳送到叢集檔案系統(類似於 fluentd 或 logstash);執行一個 Web 伺服器,該伺服器從磁碟目錄提供資料,該目錄由一個程序填充,該程序從叢集檔案系統讀取資料併為 Web 伺服器準備/暫存資料(類似於內容管理系統);以及在儲存分片旁邊執行使用者定義的處理函式。Pod 不僅支援這些用例,而且還提供了一個類似於在單個 VM 中執行多個程序的環境——Kubernetes 使用者可以在 Pod 中部署多個共存、協作的程序,而無需放棄一個應用程式一個容器部署模型的簡單性。
Service。儘管 Borg 的主要作用是管理任務和機器的生命週期,但執行在 Borg 上的應用程式受益於許多其他叢集服務,包括命名和負載均衡。Kubernetes 使用 Service 抽象支援命名和負載均衡:Service 有一個名稱,並對映到由標籤選擇器定義的一組動態 Pod(請參閱下一節)。叢集中的任何容器都可以使用 Service 名稱連線到 Service。在幕後,Kubernetes 會自動在與標籤選擇器匹配的 Pod 之間對連線到 Service 的連線進行負載均衡,並跟蹤 Pod 隨著時間因故障重新排程而執行的位置。
標籤。Borg 中的容器通常是相同或幾乎相同的容器集合中的一個副本,這些容器對應於 Internet 服務的某個層(例如 Google 地圖的前端)或批處理作業的工作器(例如 MapReduce)。這個集合被稱為 Job,每個副本被稱為 Task。雖然 Job 是一個非常有用的抽象,但它可能受到限制。例如,使用者通常希望將整個服務(由許多 Job 組成)作為一個單一實體進行管理,或者統一管理其服務的幾個相關例項,例如獨立的金絲雀和穩定釋出軌道。另一方面,使用者經常希望推斷和控制 Job 中的任務子集——最常見的例子是在滾動更新期間,Job 的不同子集需要具有不同的配置。
Kubernetes 透過使用標籤(使用者附加到 Pod(實際上是系統中的任何物件)的任意鍵/值對)來組織 Pod,從而支援比 Borg 更靈活的集合。使用者可以透過在其 Pod 上使用“job:<jobname>”標籤來建立等同於 Borg Job 的分組,但他們也可以使用附加標籤來標記服務名稱、服務例項(生產、暫存、測試),以及通常是其 Pod 的任何子集。標籤查詢(稱為“標籤選擇器”)用於選擇應將操作應用於哪些 Pod 集。總而言之,標籤和複製控制器允許非常靈活的更新語義,以及跨越 Borg Job 等效的操作。
- 每個 Pod 一個 IP。在 Borg 中,機器上的所有任務都使用該主機的 IP 地址,因此共享主機的埠空間。雖然這意味著 Borg 可以使用普通的網路,但它給基礎設施和應用程式開發人員帶來了許多負擔:Borg 必須將埠排程為資源;任務必須預先宣告它們需要多少埠,並將其作為啟動引數來使用哪些埠;Borglet(節點代理)必須強制執行埠隔離;命名和 RPC 系統必須處理埠和 IP 地址。
由於諸如 flannel 或內置於公共雲中的軟體定義覆蓋網路的出現,Kubernetes 能夠為每個 Pod 和 Service 提供自己的 IP 地址。這消除了管理埠的基礎設施複雜性,並允許開發人員選擇他們想要的任何埠,而不是要求他們的軟體適應基礎設施選擇的埠。後一點對於簡化在 Kubernetes 上執行現成的開源應用程式至關重要——Pod 可以被視為類似於 VM 或物理主機,可以訪問完整的埠空間,而無需知道它們可能與同一個物理機器上的其他 Pod 共享。
隨著基於容器的微服務架構越來越受歡迎,Google 從內部執行此類系統中學到的經驗教訓引起了外部 DevOps 社群日益增長的興趣。透過揭示我們的叢集管理器 Borg 的一些內部工作原理,並將我們的下一代叢集管理器構建為開源專案 (Kubernetes) 和公共託管服務 (Google Container Engine),我們希望這些經驗教訓能夠惠及 Google 之外的更廣泛社群,並推動容器排程和叢集管理領域的技術發展。