本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

rktnetes 將 rkt 容器引擎帶到 Kubernetes

編者按:這篇博文是關於 Kubernetes 1.3 新特性的系列深度文章之一

作為 Kubernetes 1.3 的一部分,我們很高興地報告,我們將可互換容器引擎引入 Kubernetes 的工作已初見成效。我們親切地稱之為“rktnetes”的功能已包含在 Kubernetes 1.3 版本中,可用於開發。rktnetes 將對 CoreOS rkt 的支援整合到 Kubernetes 中,作為叢集節點上的容器執行時,並且現在是 Kubernetes 主線原始碼的一部分。對於注重容器可移植性的開發人員和運維專業人員來說,嘗試使用不同的容器引擎執行 Kubernetes 比以往任何時候都更容易。

PayPal 服務 Xoom 的高階 MTS 和架構師 Mark Petrovic 表示:“我們發現 CoreOS 的 rkt 在 Kubernetes 中是一個引人注目的容器引擎,因為它與底層 systemd 的組合方式。rkt 執行時只承擔它需要承擔的責任,然後在適當的時候委託給其他系統服務。這種關注點分離對我們來說很重要。”

什麼是 rktnetes?

rktnetes 是一個暱稱,指代使 Kubernetes 節點能夠使用 rkt 容器引擎(而非 Docker)執行應用程式容器的程式碼。此更改為 Kubernetes 增加了新功能,例如以靈活的隔離級別執行容器。rkt 探索了一種替代的容器執行時架構方法,旨在反映 Unix 清晰分離、模組化工具的哲學。為支援 rktnetes 所做的工作也為 Kubernetes 的未來可能性開闢了道路,例如支援多種容器映象格式,以及整合針對特定用例或平臺量身定製的其他容器執行時。

為什麼 Kubernetes 需要 rktnetes?

rktnetes 不僅僅關乎 rkt。它還關乎完善和實踐 Kubernetes 介面,併為未來其他模組化執行時鋪平道路。雖然 Docker 容器引擎廣為人知,並且目前是預設的 Kubernetes 容器執行時,但可插拔的容器環境帶來了許多好處。例如,某些叢集可能需要非常具體的容器引擎實現,而確保 Kubernetes 設計足夠靈活以支援替代執行時(從 rkt 開始)有助於保持元件之間的介面清晰簡潔。

關注點分離:分解單體容器守護程式

Kubernetes 當前使用的容器執行時強加了一些設計決策。在這樣一個快速發展的領域中,嘗試其他容器執行架構是值得的。如今,當 Kubernetes 向節點發送請求以開始執行 Pod 時,它透過每個節點上的 kubelet 與預設容器執行時的中央守護程式通訊,該守護程式負責管理節點的所有容器。

rkt 不實現單體容器管理守護程式。(值得注意的是,預設容器執行時正在重構其原始的單體架構。)rkt 設計從第一天起就嘗試最大限度地應用模組化原則,包括重用經過充分測試的系統元件,而不是重新實現它們。

構建容器映象的任務在 rkt 中從容器執行時核心中抽象出來,並由獨立的實用程式實現。持續的容器生命週期管理也採用了相同的方法。一個單一的二進位制檔案 rkt 配置環境並準備容器映象以供執行,然後啟動容器應用程式及其隔離環境。此時,rkt 程式已完成其“一項工作”,容器隔離器接管。

Kubernetes 用於跟蹤每個節點上叢集工作的容器引擎和 Pod 狀態查詢 API 由單獨的服務實現,將協調和編排功能與核心容器執行時隔離。雖然 API 服務尚未完全實現當前預設容器引擎的所有 API 功能,但它已經有助於將容器與核心執行時中的故障和升級隔離,並提供預期 API 的只讀部分以查詢容器元資料。

模組化容器隔離級別

透過 rkt 管理容器執行,Kubernetes 可以利用 CoreOS 容器引擎的模組化 *stage1* 隔離機制。典型的容器在 rkt 下執行,在一個由 Linux 核心名稱空間、cgroups 和其他設施構建的軟體隔離環境中。以這種常見方式隔離的容器仍然與系統上的所有其他容器共享一個單一的核心,從而實現了輕量級的執行應用程式隔離。

然而,rkt 提供了可插拔的隔離環境,稱為 stage1,以改變容器的執行和隔離方式。例如,rkt fly stage1 在主機名稱空間(PID、掛載、網路等)中執行容器,賦予容器在主機系統上更大的許可權。Fly 用於容器化更底層的系統和網路軟體,例如 kubelet 本身。在隔離譜系的另一端,KVM stage1 將標準應用程式容器作為獨立的虛擬機器執行,每個虛擬機器都位於自己的 Linux 核心之上,由 KVM 虛擬機器管理器管理。這種隔離級別對於高安全性多租戶叢集工作負載非常有用。

目前,rktnetes 可以透過設定 kubelet 的 `--rkt-stage1-image` 選項,使用 KVM stage1 在節點上以 VM 隔離執行所有容器。存在實驗性工作,可以透過 Kubernetes 註解宣告 Pod 的適當 stage1,以基於每個 Pod 選擇 stage1 隔離方案。KVM 容器和標準 Linux 容器可以混合在同一個叢集中。

rkt 如何與 Kubernetes 協作

Kubernetes 目前透過 Docker 守護程式提供的 API 與預設容器引擎通訊。rktnetes 與 rkt 的通訊方式略有不同。首先,Kubernetes 改變節點容器狀態(如何啟動和停止 Pod,或為故障轉移或擴縮重新排程它們)的方式與協調器查詢 Pod 元資料以進行定期只讀簿記的方式存在區別。兩種不同的設施實現了這兩種不同的情況。

管理微服務生命週期

每個叢集節點上的 kubelet 與 rkt 通訊以準備容器及其環境到 Pod,並與 Linux 服務管理框架 systemd 通訊以呼叫和管理 Pod 程序。然後,Pod 作為 systemd 服務進行管理,kubelet 透過 dbus 傳送 systemd 命令來操作它們。生命週期管理,例如重新啟動失敗的 Pod 和終止已完成的程序,由 systemd 在 kubelet 的指示下處理。

用於讀取 Pod 資料的 API 服務

一個獨立的 rkt api-service 實現了 Kubernetes 所期望的 Pod 內省機制。雖然每個節點的 kubelet 使用 systemd 作為服務啟動、停止和重新啟動 Pod,但它聯絡 API 服務以讀取容器執行時元資料。這包括基本的編排資訊,例如節點上執行的 Pod 數量、這些 Pod 的名稱和網路,以及 Pod 配置、資源限制和儲存卷的詳細資訊(想想 kubectl describe 子命令顯示的資訊)。

Pod 日誌被寫入日誌檔案後,API 服務也會將其提供給 kubectl logs 和其他取證子命令。API 服務從日誌檔案中讀取資料,並將 Pod 日誌資料提供給 kubelet,以響應控制平面請求。

這種到容器環境的雙重介面是一個非常活躍的開發領域,計劃是 API 服務將擴充套件以提供 Pod 操作命令的方法。底層機制將繼續牢記關注點分離,但會向 kubelet 隱藏更多細節。隨著時間的推移,kubelet 用於控制 rktnetes 容器引擎的方法與預設容器執行時介面的差異將越來越小。

試用 rktnetes

那麼,今天您可以用 rktnetes 做些什麼呢?目前,rktnetes 通過了所有適用的 Kubernetes “端到端”(又稱“e2e”)測試,向 cAdvisor 提供標準指標,使用 CNI 管理網路,處理每個容器/Pod 的日誌,並自動垃圾回收舊容器和映象。Kubernetes 在 rkt 上執行已經提供了 Kubernetes 叢集模組化、靈活的容器執行時所需的基本功能,並且它已經成為我們 CoreOS 開發環境的一個功能部分。

開發人員和早期採用者可以遵循 rktnetes 備註 中的已知問題,瞭解測試人員可能遇到的問題和障礙。此列表將實現 rktnetes 與現有容器執行時和 API 功能對等所需的高階元件進行分組。我們希望您也能在您的 Kubernetes 叢集中試用 rktnetes。

立即將 rkt 與 Kubernetes 結合使用

入門指南 在 rkt 上執行 Kubernetes 詳細介紹了啟動 rktnetes 叢集的步驟,從 `kubelet --container-runtime=rkt` 到網路和啟動 Pod。本介紹還概述了使用 Kubernetes 的 `kube-up.sh` 指令碼在 GCE 上啟動叢集所需的配置。

最近的工作也旨在讓 rktnetes 叢集的建立變得更加容易。雖然尚未合併,但一個正在進行的拉取請求建立了一個單一的 rktnetes 配置開關,以便在使用 coreos-kubernetes 配置工具部署 Kubernetes 叢集時選擇 rkt 作為容器引擎。您還可以檢視 rktnetes workshop 專案,該專案只需一個 `vagrant up` 命令即可在幾乎任何開發人員工作站上啟動單節點 rktnetes 叢集。

我們很高興看到更廣泛的 Kubernetes 和 CoreOS 社群設計出各種實驗來測試 rktnetes,我們歡迎您的意見——以及拉取請求!