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

我們如何在 Kubernetes 中執行 Kubernetes 又名 Kubeception

Giant Swarm 的容器基礎架構最初的目標是為開發人員提供一種簡單的方式來部署容器化的微服務。我們第一代產品廣泛使用 fleet 作為基礎層,用於我們的基礎架構組件以及排程使用者容器。

為了讓我們的使用者能夠更強大地管理他們的容器,我們在 2016 年初將 Kubernetes 導入到我們的堆疊中。然而,由於我們需要一種快速的方式來彈性地啟動和管理不同使用者的 Kubernetes 叢集,並使其具有彈性,因此我們保留了底層的 fleet 層。

由於我們堅持在容器中執行所有底層基礎架構組件,fleet 讓我們可以彈性地使用 systemd unit 檔案以宣告方式定義我們的基礎架構組件。我們自行開發的部署工具讓我們能夠部署和管理基礎架構,而無需使用命令式組態管理工具。

然而,fleet 只是一個分散式 init 系統,而不是一個完整的排程和協調系統。除了我們在工具方面的大量工作外,它還需要在同儕之間的通訊、其協調迴圈以及我們必須努力解決的穩定性方面進行重大改進。此外,Kubernetes 使用率的提升將確保更快地發現和修復問題。

由於我們在使用者端導入 Kubernetes 方面取得了良好的經驗,並且隨著最近 rktnetesstackanetes 等技術的發展,我們覺得現在也是時候將我們的基礎層遷移到 Kubernetes 了。

為何在 Kubernetes 中使用 Kubernetes

現在,您可能會問,為什麼有人想要在 Kubernetes 叢集內執行多個 Kubernetes 叢集?我們瘋了嗎?答案是進階的多租戶使用案例以及其可操作性和自動化。

Kubernetes 自身帶有不斷增長的多租戶使用案例功能集。然而,我們的目標是為使用者提供完全託管的 Kubernetes,而不會限制他們使用任何原生 Kubernetes 環境所獲得的功能,包括對節點的特權存取權限。此外,在更大的企業情境中,單一 Kubernetes 叢集及其內建的隔離機制通常不足以滿足合規性和安全性要求。更進階的(防火牆)分區或分層安全概念很難透過單一安裝來重現。使用命名空間隔離,特權存取和防火牆分區幾乎無法在不繞過安全措施的情況下實作。

現在您可以設定多個完全獨立(且聯邦式)的 Kubernetes 安裝。然而,自動化這些叢集的部署和管理將需要額外的工具和複雜的監控設定。此外,我們希望能夠根據需要啟動和關閉叢集、擴展它們、更新它們、追蹤哪些叢集可用,並能夠彈性地將它們分配給組織和團隊。實際上,此設定可以與聯邦控制平面結合使用,以透過一個 API 端點將部署聯合到叢集。

如果有一個適用於此的 API 和前端,豈不是更好嗎?

Giantnetes 登場

基於上述需求,我們著手建構我們稱之為 Giantnetes 的東西 - 或者如果您喜歡電影,則稱為 Kubeception。在最基本的抽象層面上,它是一個外部 Kubernetes 叢集(實際的 Giantnetes),用於執行和管理多個完全隔離的使用者 Kubernetes 叢集。

實體機器是透過使用我們的 CoreOS Container Linux 啟動工具 Mayu 來引導啟動的。Giantnetes 組件本身是自我託管的,也就是說,kubelet 負責自動引導啟動位於 manifests 資料夾中的組件。您可以將其稱為 Kubeception 的第一層。

一旦 Giantnetes 叢集執行起來,我們就會使用它來排程使用者 Kubernetes 叢集以及我們用於管理和保護它們的工具。

我們選擇 Calico 作為 Giantnetes 網路外掛程式,以確保安全性、隔離以及在 Giantnetes 上執行的所有應用程式的正確效能。

然後,為了建立內部 Kubernetes 叢集,我們啟動幾個 Pod,它們配置網路橋接器、建立憑證和權杖,並為未來的叢集啟動虛擬機器。為此,我們使用輕量級技術,例如 KVM 和 qemu 來佈建 CoreOS Container Linux VM,這些 VM 成為內部 Kubernetes 叢集的節點。您可以將其稱為 Kubeception 的第二層。

目前,這表示我們正在啟動具有 Docker 容器的 Pod,而 Docker 容器又使用 KVM 和 qemu 啟動 VM。但是,我們正在研究使用 rkt qemu-kvm 來執行此操作,這將導致為我們的 Giantnetes 使用 rktnetes 設定。

內部 Kubernetes 叢集的網路解決方案有兩個層級。它基於 flannel 的伺服器/用戶端架構模型和 Calico BGP 的組合。雖然 flannel 用戶端用於在每個虛擬化的內部 Kubernetes 叢集的 VM 之間建立網路橋接器,但 Calico 在虛擬機器內部執行,以連接不同的 Kubernetes 節點,並為內部 Kubernetes 建立單一網路。透過使用 Calico,我們在每個 Kubernetes 叢集內部模擬 Giantnetes 網路解決方案,並提供基本元件,以透過 Kubernetes 網路策略 API 來保護和隔離工作負載。

關於安全性,我們的目標是盡可能地分離權限,並使事情可稽核。目前,這表示我們使用憑證來保護對叢集的存取,並加密構成叢集的所有組件(即 VM 到 VM、Kubernetes 組件彼此之間、etcd master 到 Calico worker 等)之間的通訊。為此,我們為每個叢集建立一個 PKI 後端,然後根據需要在 Vault 中為每個服務頒發憑證。每個組件都使用不同的憑證,因此,如果任何組件或節點受到入侵,都可以避免暴露整個叢集。我們還定期輪換憑證。

為了確保從外部存取每個內部 Kubernetes 叢集的 API 和服務,我們在 Giantnetes 中執行多層 HAproxy 網域名稱伺服器控制器設定,將 Kubernetes VM 連接到硬體負載平衡器。

使用 kubectl 檢視 Giantnetes

讓我們看看 Giantnetes 的最小範例部署。

Screen Shot 2016-11-14 at 12.08.40 PM.png

在上面的範例中,您可以看到在 Giantnetes 之上的 VM 容器中執行的使用者 Kubernetes 叢集 customera。我們目前使用 Jobs 來進行網路和憑證設定。

窺視使用者叢集內部,您會看到 DNS Pod 和 helloworld 正在執行。

Screen Shot 2016-11-14 at 12.07.28 PM.png

這些使用者叢集中的每一個都可以獨立排程和使用。它們可以根據需要啟動和關閉。

結論

總而言之,我們可以展示 Kubernetes 如何不僅能夠輕鬆地自我託管,而且還能彈性地排程大量內部 Kubernetes 叢集,同時確保更高的隔離性和安全性。此設定中的一個亮點是安裝的可組合性和自動化,以及 Kubernetes 組件之間穩健的協調。這讓我們能夠輕鬆地根據需要建立、銷毀和重新排程叢集,而不會影響使用者或損害基礎架構的安全性。它還允許我們透過僅在叢集建立時變更一些引數來啟動具有不同大小和組態甚至版本的叢集。

此設定仍處於早期階段,我們的藍圖計劃在許多領域進行改進,例如透明升級、叢集的動態重新配置和擴展、效能改進以及(甚至更多)安全性。此外,我們期待透過利用 Kubernetes 運作工具不斷發展的狀態和即將推出的功能(例如 Init Containers、Scheduled Jobs、Pod 和 Node affinity 與 anti-affinity 等)來改進我們的設定。

最重要的是,我們正在努力使內部 Kubernetes 叢集成為可以由自訂控制器管理的第三方資源。結果將非常像 CoreOS 的 Operator 概念。為了確保廣大社群可以從這個專案中受益,我們將在不久的將來開源它。