本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
我們如何用 Kubernetes 執行 Kubernetes,又名 Kubeception
Giant Swarm 的容器基礎設施最初的目標是為開發人員提供一種簡便的方式來部署容器化微服務。我們的第一代產品廣泛使用 fleet 作為基礎設施元件的基礎層,並用於排程使用者容器。
為了讓使用者更強大地管理其容器,我們在2016年初將 Kubernetes 引入了我們的堆疊。然而,由於我們需要一種快速、靈活地啟動和管理不同使用者的 Kubernetes 叢集並保持彈性的方式,我們保留了底層 fleet 層。
由於我們堅持在容器中執行所有底層基礎設施元件,fleet 為我們提供了使用 systemd 單元檔案宣告性地定義基礎設施元件的靈活性。我們自主開發的部署工具使我們能夠部署和管理基礎設施,而無需命令式配置管理工具。
然而,fleet 只是一個分散式 init,而不是一個完整的排程和編排系統。除了在工具方面做了大量工作外,它還需要在同行之間的通訊、其協調迴圈和穩定性方面進行顯著改進,這是我們必須努力的。此外,Kubernetes 使用率的提高將確保問題更快地被發現和修復。
由於我們在使用者端引入 Kubernetes 方面積累了良好的經驗,並且最近有了 rktnetes 和 stackanetes 等發展,我們覺得是時候也將我們的基礎層遷移到 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 虛擬機器,這些虛擬機器將成為內部 Kubernetes 叢集的節點。您可以稱之為 Kubeception 的第二層。
目前,這意味著我們正在啟動帶有 Docker 容器的 Pod,這些容器又會啟動帶有 KVM 和 qemu 的虛擬機器。然而,我們正在研究使用 rkt qemu-kvm 來實現這一點,這將導致為我們的 Giantnetes 使用 rktnetes 設定。
內部 Kubernetes 叢集的網路解決方案分為兩層。它結合了 flannel 的伺服器/客戶端架構模型和 Calico BGP。flannel 客戶端用於在每個虛擬化內部 Kubernetes 叢集的虛擬機器之間建立網路橋接,而 Calico 在虛擬機器內部執行,用於連線不同的 Kubernetes 節點併為內部 Kubernetes 建立單個網路。透過使用 Calico,我們模仿了每個 Kubernetes 叢集內部的 Giantnetes 網路解決方案,並透過 Kubernetes 網路策略 API 提供了用於保護和隔離工作負載的原語。
在安全性方面,我們力求儘可能地分離許可權並使事情可審計。目前,這意味著我們使用證書來保護對叢集的訪問,並加密構成叢集的所有元件之間的通訊(即虛擬機器到虛擬機器、Kubernetes 元件之間、etcd 主節點到 Calico 工作節點等)。為此,我們為每個叢集建立一個 PKI 後端,然後按需在 Vault 中為每個服務頒發證書。每個元件使用不同的證書,從而避免在任何元件或節點受到損害時暴露整個叢集。我們還會定期輪換證書。
為了確保從外部訪問每個內部 Kubernetes 叢集的 API 和服務,我們在 Giantnetes 中運行了一個多級 HAproxy 入口控制器設定,將 Kubernetes 虛擬機器連線到硬體負載均衡器。
用 kubectl 檢視 Giantnetes
讓我們來看一個 Giantnetes 的最小示例部署。
在上面的示例中,您看到一個使用者 Kubernetes 叢集 customera
在 Giantnetes 上的 VM 容器中執行。我們目前使用 Jobs 進行網路和證書設定。
檢視使用者叢集內部,您會看到 DNS Pod 和一個 helloworld 正在執行。
這些使用者叢集中的每一個都可以獨立排程和使用。它們可以按需啟動和關閉。
結論
總而言之,我們展示了 Kubernetes 如何不僅能夠輕鬆地自託管,還能靈活地排程多個內部 Kubernetes 叢集,同時確保更高的隔離性和安全性。此設定的一個亮點是安裝的可組合性和自動化以及 Kubernetes 元件之間強大的協調。這使我們能夠按需輕鬆建立、銷燬和重新排程叢集,而不會影響使用者或損害基礎設施的安全性。它還允許我們透過在叢集建立時更改一些引數來啟動具有不同大小和配置甚至版本的叢集。
此設定仍處於早期階段,我們的路線圖計劃在許多領域進行改進,例如透明升級、叢集的動態重新配置和擴充套件、效能改進以及(更多)安全性。此外,我們期待透過利用不斷發展的 Kubernetes 操作工具和即將推出的功能(例如 Init 容器、計劃任務、Pod 和節點親和性以及反親和性等)來改進我們的設定。
最重要的是,我們正在努力使內部 Kubernetes 叢集成為第三方資源,然後可以透過自定義控制器進行管理。結果將非常類似於 CoreOS 的 Operator 概念。為了確保廣大社群能夠從這個專案中受益,我們將在不久的將來將其開源。