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

DIY:使用 Kubernetes 建立自己的雲(第 3 部分)

本文進入了最有趣的階段,深入探討了在 Kubernetes 中執行 Kubernetes。重點介紹了 Kamaji 和 Cluster API 等技術,以及它們與 KubeVirt 的整合。

之前的討論已經涵蓋了在裸金屬上準備 Kubernetes 以及如何將 Kubernetes 轉變為虛擬機器管理系統。本文是該系列的最後一篇,解釋瞭如何利用以上所有內容,構建一個功能齊全的託管 Kubernetes,並只需單擊一下即可執行虛擬 Kubernetes 叢集。

首先,讓我們深入瞭解 Cluster API。

Cluster API

Cluster API 是 Kubernetes 的一個擴充套件,它允許將 Kubernetes 叢集作為另一個 Kubernetes 叢集中的自定義資源進行管理。

Cluster API 的主要目標是為描述 Kubernetes 叢集的基本實體並管理其生命週期提供統一的介面。這使得建立、更新和刪除叢集的過程自動化,從而簡化了擴充套件和基礎設施管理。

在 Cluster API 的上下文中,有兩個術語:管理叢集租戶叢集

  • 管理叢集 是一個用於部署和管理其他叢集的 Kubernetes 叢集。該叢集包含所有必要的 Cluster API 元件,並負責描述、建立和更新租戶叢集。它通常僅用於此目的。
  • 租戶叢集 是使用者叢集或使用 Cluster API 部署的叢集。它們透過在管理叢集中描述相關資源來建立。然後,終端使用者使用它們來部署應用程式和服務。

重要的是要理解,物理上,租戶叢集不一定必須與管理叢集執行在相同的基礎設施上;更常見的情況是,它們執行在其他地方。

A diagram showing interaction of management Kubernetes cluster and tenant Kubernetes clusters using Cluster API

一張展示管理 Kubernetes 叢集和租戶 Kubernetes 叢集使用 Cluster API 進行互動的圖表

為了執行,Cluster API 利用了 提供者(providers) 的概念,這些提供者是負責被建立叢集特定元件的獨立控制器。在 Cluster API 中,有幾種型別的提供者。主要的有:

  • 基礎設施提供者,負責提供計算基礎設施,例如虛擬機器或物理伺服器。
  • 控制平面提供者,它提供 Kubernetes 控制平面,即 kube-apiserver、kube-scheduler 和 kube-controller-manager 元件。
  • 引導提供者,用於為正在建立的虛擬機器和伺服器生成 cloud-init 配置。

要開始使用,你需要安裝 Cluster API 本身以及每種型別的一個提供者。你可以在專案的文件中找到支援的提供者的完整列表。

對於安裝,您可以使用 clusterctl 實用程式,或者使用Cluster API Operator 作為更具宣告性的方法。

選擇提供者

基礎設施提供者

要使用 KubeVirt 執行 Kubernetes 叢集,必須安裝KubeVirt 基礎設施提供者。它能夠在執行 Cluster API 的同一管理叢集中部署工作節點的虛擬機器。

控制平面提供者

Kamaji 專案為在管理叢集內以容器形式執行租戶叢集的 Kubernetes 控制平面提供了一個現成的解決方案。這種方法有幾個顯著的優點:

  • 成本效益:在容器中執行控制平面避免了為每個叢集使用單獨的控制平面節點,從而顯著降低了基礎設施成本。
  • 穩定性:透過消除複雜的多層部署方案來簡化架構。不再是依次啟動虛擬機器然後在其中安裝 etcd 和 Kubernetes 元件,而是一個簡單的控制平面,它被部署並作為 Kubernetes 內部的常規應用程式執行,並由一個 operator 管理。
  • 安全性:叢集的控制平面對終端使用者是隱藏的,減少了其元件被攻破的可能性,並且還消除了使用者對叢集證書庫的訪問。這種對使用者不可見的控制平面組織方式常被雲提供商使用。

載入程式提供者

使用 Kubeadm 作為引導提供者,這是 Cluster API 中準備叢集的標準方法。該提供者是作為 Cluster API 本身的一部分開發的。它只需要一個已安裝 kubelet 和 kubeadm 的準備好的系統映象,並允許生成 cloud-init 和 ignition 格式的配置。

值得注意的是,Talos Linux 也支援透過 Cluster API 進行配置,併為此提供了提供者。雖然之前的文章討論了使用 Talos Linux 在裸金屬節點上設定管理叢集,但對於配置租戶叢集,Kamaji+Kubeadm 的方法具有更多優勢。它便於在容器中部署 Kubernetes 控制平面,從而無需為控制平面例項設定單獨的虛擬機器。這簡化了管理並降低了成本。

工作原理

Cluster API 中的主要物件是 Cluster 資源,它充當所有其他資源的父級。通常,此資源引用另外兩個資源:一個描述控制平面的資源和一個描述基礎設施的資源,每個資源都由一個單獨的提供者管理。

與 Cluster 不同,這兩個資源沒有標準化,它們的型別(kind)取決於您正在使用的具體提供者。

A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API

一張圖表,展示了 Cluster 資源與其在 Cluster API 中連結的資源之間的關係。

在 Cluster API 中,還有一個名為 MachineDeployment 的資源,它描述了一組節點,無論是物理伺服器還是虛擬機器。這個資源的功能類似於標準的 Kubernetes 資源,如 Deployment、ReplicaSet 和 Pod,提供了一種宣告式描述一組節點和自動擴充套件的機制。

換句話說,MachineDeployment 資源允許您宣告式地描述叢集的節點,根據指定的引數和請求的副本數量自動化它們的建立、刪除和更新。

A diagram showing the relationship of a Cluster resource and its children in Cluster API

一張展示 MachineDeployment 資源及其在 Cluster API 中的子資源關係的圖表

為了建立機器,MachineDeployment 引用一個用於生成機器本身的模板和一個用於生成其 cloud-init 配置的模板。

A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API

一張圖表,展示了 MachineDeployment 資源與它在 Cluster API 中連結的資源之間的關係。

要使用 Cluster API 部署一個新的 Kubernetes 叢集,您需要準備以下一組資源:

  • 一個通用的 Cluster 資源
  • 一個 KamajiControlPlane 資源,負責由 Kamaji 操作的控制平面
  • 一個 KubevirtCluster 資源,描述 KubeVirt 中的叢集配置
  • 一個 KubevirtMachineTemplate 資源,負責虛擬機器模板
  • 一個 KubeadmConfigTemplate 資源,負責生成令牌和 cloud-init
  • 至少一個 MachineDeployment 來建立一些工作節點

完善叢集

在大多數情況下,這已經足夠了,但根據所使用的提供商,您可能還需要其他資源。您可以在 Kamaji 專案文件中找到為每種提供商建立的資源示例。

在這個階段,你已經有了一個準備好的租戶 Kubernetes 叢集,但到目前為止,它只包含 API 工作節點和一些核心外掛,這些外掛是任何 Kubernetes 叢集安裝中標準包含的:kube-proxyCoreDNS。為了完全整合,你還需要安裝幾個元件。

要安裝額外的元件,您可以使用一個單獨的 Cluster API Add-on Provider for Helm,或者使用在之前文章中討論過的同一個 FluxCD

在使用 FluxCD 建立資源時,可以透過引用由 Cluster API 生成的 kubeconfig 來指定目標叢集。然後,安裝將直接在其中執行。因此,FluxCD 成為一個通用工具,用於管理管理叢集和使用者租戶叢集中的資源。

A diagram showing the interaction scheme of fluxcd, which can install components in both management and tenant Kubernetes clusters

一張圖表,展示了 fluxcd 的互動方案,它可以在管理 Kubernetes 叢集和租戶 Kubernetes 叢集中安裝元件。

這裡討論的是哪些元件?通常,這套元件包括以下內容:

CNI 外掛

為了確保租戶 Kubernetes 叢集中 Pod 之間的通訊,有必要部署一個 CNI 外掛。這個外掛建立了一個虛擬網路,允許 Pod 之間相互互動,並且傳統上作為 Daemonset 部署在叢集的工作節點上。你可以選擇並安裝任何你認為合適的 CNI 外掛。

A diagram showing a CNI plugin installed inside the tenant Kubernetes cluster on a scheme of nested Kubernetes clusters

一張圖表,在一個巢狀的 Kubernetes 叢集方案中,展示了一個安裝在租戶 Kubernetes 叢集內部的 CNI 外掛。

雲控制器管理器(Cloud Controller Manager)

Cloud Controller Manager (CCM) 的主要任務是將 Kubernetes 與雲基礎設施提供商的環境整合起來(在您的情況下,是管理所有租戶 Kubernetes 工作節點的管理 Kubernetes 叢集)。以下是它執行的一些任務:

  1. 當建立型別為 LoadBalancer 的服務時,CCM 會啟動建立雲負載均衡器的過程,該負載均衡器將流量引導至您的 Kubernetes 叢集。
  2. 如果從雲基礎設施中移除了一個節點,CCM 會確保它也從您的叢集中移除,從而維護叢集的當前狀態。
  3. 使用 CCM 時,節點被新增到叢集時會帶有一個特殊的汙點 `node.cloudprovider.kubernetes.io/uninitialized`,這允許在必要時處理額外的業務邏輯。成功初始化後,此汙點將從節點上移除。

根據雲提供商的不同,CCM 可以在租戶叢集內部或外部執行。

KubeVirt 雲提供商設計為安裝在外部的父管理叢集中。因此,在租戶叢集中建立型別為 LoadBalancer 的服務會觸發在父叢集中建立 LoadBalancer 服務,這些服務將流量引導至租戶叢集。

A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of services it manages from the parent to the child Kubernetes cluster

一張圖表,在一個巢狀 Kubernetes 叢集的方案中,展示了一個安裝在租戶 Kubernetes 叢集外部的 Cloud Controller Manager,以及它管理的從父 Kubernetes 叢集到子 Kubernetes 叢集的服務對映。

CSI 驅動程式

容器儲存介面(Container Storage Interface,CSI)在與 Kubernetes 中的儲存互動方面分為兩個主要部分:

  • csi-controller:該元件負責與雲提供商的 API 互動,以建立、刪除、附加、分離和調整卷的大小。
  • csi-node:這個元件在每個節點上執行,並根據 kubelet 的請求,幫助將卷掛載到 Pod 上。

在使用 KubeVirt CSI 驅動的背景下,出現了一個獨特的機會。由於 KubeVirt 中的虛擬機器執行在管理 Kubernetes 叢集內部,那裡有功能齊全的 Kubernetes API 可用,這為在使用者租戶叢集外部執行 csi-controller 開闢了道路。這種方法在 KubeVirt 社群中很受歡迎,並提供了幾個關鍵優勢:

  • 安全性:此方法向終端使用者隱藏了內部雲 API,僅透過 Kubernetes 介面提供對資源的訪問。因此,它降低了從使用者叢集直接訪問管理叢集的風險。
  • 簡單與便利:使用者無需在他們的叢集中管理額外的控制器,從而簡化了架構並減輕了管理負擔。

然而,CSI-node 必須執行在租戶叢集內部,因為它直接與每個節點上的 kubelet 互動。這個元件負責將卷掛載和解除安裝到 Pod 中,需要與直接發生在叢集節點上的程序緊密整合。

KubeVirt CSI 驅動程式充當訂購卷的代理。當在租戶叢集內部建立一個 PVC 時,會在管理叢集中建立一個 PVC,然後將建立的 PV 連線到虛擬機器。

A diagram showing a CSI plugin components installed on both inside and outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of persistent volumes it manages from the parent to the child Kubernetes cluster

一張圖表,展示了在一個巢狀 Kubernetes 叢集方案中,CSI 外掛元件同時安裝在租戶 Kubernetes 叢集內外的情況,以及它管理的從父 Kubernetes 叢集到子 Kubernetes 叢集的持久卷對映。

叢集自動擴縮器

Cluster Autoscaler 是一個多功能的元件,可以與各種雲 API 配合工作,其與 Cluster-API 的整合只是可用功能之一。為了正確配置,它需要訪問兩個叢集:租戶叢集,用於跟蹤 Pod 並確定是否需要新增新節點;以及管理 Kubernetes 叢集,它在此處與 MachineDeployment 資源互動並調整副本數量。

雖然 Cluster Autoscaler 通常在租戶 Kubernetes 叢集內部執行,但在這種情況下,建議出於前面描述的相同原因將其安裝在外部。這種方法更易於維護,也更安全,因為它阻止了租戶叢集的使用者訪問管理叢集的管理 API。

A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters

一張圖表,在一個巢狀的 Kubernetes 叢集方案中,展示了一個安裝在租戶 Kubernetes 叢集外部的 Cluster Autoscaler。

Konnectivity

我還想提及另一個額外的元件——Konnectivity。你很可能稍後會需要它來讓你的租戶 Kubernetes 叢集中的 Webhook 和 API 聚合層正常工作。這個主題在我的一篇之前的文章中有詳細介紹。

與上面介紹的元件不同,Kamaji 允許您輕鬆啟用 Konnectivity,並將其作為租戶叢集的核心元件之一進行管理,與 kube-proxy 和 CoreDNS 並列。

結論

現在你擁有一個功能齊全的 Kubernetes 叢集,具備動態擴充套件、自動配置卷和負載均衡器的能力。

接下來,您可能會考慮從您的租戶叢集收集指標和日誌,但這超出了本文的範圍。

當然,部署 Kubernetes 叢集所需的所有元件都可以打包到一個 Helm Chart 中,並作為一個統一的應用程式進行部署。這正是我們在我們的開放 PaaS 平臺 Cozystack 上組織一鍵部署託管 Kubernetes 叢集的方式,您可以在那裡免費試用文章中描述的所有技術。