CNStack 多叢集服務:基於 OCM 打造完善的叢集管理能力

阿里云云原生發表於2023-03-14
作者:學靖

概述

隨著 Kubernetes 在企業業務中的應用和發展,單叢集內的管理能力已經趨於完善,越來越多的客戶期望在多雲、多叢集場景部署其業務,因此需要提供相應的多雲、多叢集管理能力。

CNStack 多叢集服務是 CNStack 面向多叢集、多雲場景提供的雲原生服務,能夠統一管理 CNStack 平臺建立的、阿里雲上的、客戶自建的和其他雲上的 Kubernetes 叢集。

在 CNStack 2.0 中,CNStack 多叢集服務是以雲服務(cnstack-multicluster)的形式存在,這樣一方面在單叢集模式下使用者可以完全聚焦叢集內管理,另一方面也便於多叢集服務能力獨立演進,更加敏捷高效。該服務在 CNStack2.0 中主要提供以下功能,並會逐步在後續版本上線更多能力(如多叢集資源分發、應用跨叢集故障遷移、多叢集Service等)。

  • 擴充套件 OCM [ 1]  的叢集註冊能力,提供更加完善的註冊相關的叢集管理能力
  • 提供多種分發資源的模式:
    • 基於 OCM ManifestWork API 的 Pull 模式
    • 基於 Cluster Gateway 的 Push 模式
  • 支援實現多叢集多租戶管理,多叢集統一認證和鑑權
  • 為平臺和雲服務/雲元件提供管控叢集(Hub Cluster)和被管理叢集(Managed Cluster)之間的跨叢集高可用互訪能力

完善的叢集註冊能力

基於 Kubernetes,雲原生 PaaS 團隊和紅帽等技術夥伴開源了 CNCF Open Cluster Management(OCM)專案。而 CNStack 多叢集服務則是基於 OCM 專案,提供了多叢集的建立、註冊、取消註冊等生命週期管理能力,允許使用者以 Kubernetes 自定義資源宣告的方式描述需要建立或者納管的叢集。該服務透過擴充套件 OCM,打造了非常完善的叢集註冊能力。

架構

CNStack 多叢集服務註冊架構如下圖所示:

 title=

  • UI Backend

為 UI 提供多叢集服務所有相關的 APIs。

  • OCM Hub/Agent

OCM 相關元件,用以實現基礎的叢集註冊能力。元件主要包括 registration-operator [ 2] registration [ 3]  和 work [ 4] ,分為 hub 端和 agent 端,OCM Hub 則為在 Hub Cluster 部署的元件,OCM Agent 則為在 Managed Cluster 部署的元件。

  • Cluster Import Controller

實現了 CNStack 所擴充套件的叢集管理能力。

  • Cluster Gateway

cluster-gateway [ 5]  是一個多叢集閘道器,用於將 Kubernetes api 流量路由到多個 Kubernetes 叢集的閘道器APIServer。它是一個 Aggregated APIServer,可整合 OCM。

  • Managed ServiceAccount

managed-serviceaccount [ 6] 這裡是用於讓 Cluster Gateway 以 Kubernetes ServiceAccount 的 token 的方式而非 x509證書的方式訪問被管理叢集的 Kubernetes api。它將 ServiceAccount 同步到被管理叢集中,並從這些被同步的 ServiceAccount 收集 token,然後同步回 hub 叢集。

  • CNStack Agent

自動採集叢集廠商及核心元件狀態等資訊。

完整的叢集生命週期管理

OCM 中使用 ManagedCluster API 來表示被管理叢集的期望狀態和當前狀態,並建立了註冊、取消註冊叢集生命週期的管理。雖然 OCM 在 ManagedCluster 的定義和叢集註冊的設計上足夠優秀,但其並不能完全滿足我們的需求,因此我們在 CNStack 2.0 中擴充套件了叢集的生命週期管理,使其更加完整。

宣告式註冊(透過建立 ManagedCluster 觸發註冊)

在 CNStack 2.0 的架構設計中,採用“所有管理物件都是資源”的程式設計模型,所以我們的叢集管理也採用宣告式的 API,即透過宣告 ManagedCluster 來完成註冊。這樣被管理叢集的期望狀態和當前狀態都呈現在資源(ManagedCluster)上。

OCM 本身對叢集註冊的管理主要是透過手動或者 clusteradm 去被管理叢集部署 OCM Agent,之後由 OCM Agent 在 Hub 叢集自動建立 ManagedCluster。另外 OCM 雖然也允許使用者在部署 OCM Agent 之前建立 ManagedCluster,但仍然存在問題:OCM Agent 只會在建立 ManagedCluster 時候上報 CABundle 到 ManagedCluster 上。這個問題會導致我們無法透過宣告 ManagedCluster 來觸發註冊,因為 ManagedCluster 不會由 OCM Agent 來建立,而是由 CNStack 管控元件建立,這樣就無法在管控叢集中使用 ManagedCluster.spec.managedClusterClientConfigs 去訪問被管理叢集(如 Cluster Gateway 的 Const 模式就是透過這種方式訪問的)。

所以我們透過:

1)自動化部署 OCM Agent

2)修復 OCM Agent 只會在建立 ManagedCluster 時候上報 CABundle [ 7]  實現了宣告式叢集註冊。

涵蓋建立和刪除叢集的生命週期

CNStack 平臺可以建立叢集,為了統一管理,我們擴充套件了 ManagedCluster,讓其也涵蓋了建立和刪除叢集的生命週期,使用者可以透過宣告 ManagedCluster 來建立期望的叢集,並在建立後註冊。刪除亦然。

和透過註冊管理的三方叢集相比,多叢集服務對於自己建立的叢集,擁有完全的生命週期管理許可權,包括叢集建立、修改、擴縮容以及刪除。使用者只需要按照提示準備若干臺 Linux 機器,並確保這些機器可被從平臺所在節點透過 SSH 訪達(密碼或者秘鑰),然後根據指引填寫叢集表單,就可以快速建立一套 K8s 叢集。

值得一提的是,對於自建叢集的生命週期管理能力,由阿里巴巴開源的叢集映象技術和 ACK 發行版來提供底層支援,也就是說,使用者透過多叢集管理服務建立的叢集,就是一套標準的 ACK 發行版,具備以下優勢:

阿里巴巴開源的叢集映象技術:

https://github.com/sealerio/sealer

ACK 發行版:
https://github.com/AliyunContainerService/ackdistro

  • 無需使用阿里云云就可以感受和阿里雲 ACK 一致的使用體驗,相較社群版 K8s 更為穩定
  • 不依賴公網,可在離線環境完成分鐘級的建立和運維,支援 RHEL/Anolis/Kylin 等多種作業系統
  • 內建網路外掛(hybridnet)、儲存外掛(open-local/csi-hostpath)、運維外掛(npd/l-zero),且支援 IPv6雙棧、GPU、多架構等特性
  • 內建叢集預檢工具,可以在叢集部署之前檢查出可能影響叢集穩定性的隱患
  • 內建叢集健康檢查工具,可以一鍵檢查叢集是否健康
  • 支援對 K8s 管控元件進行隔離和容量管理,以提升 etcd 效能以及 OS 穩定性

擴充套件註冊成功狀態

叢集是否註冊成功,在不同的產品或場景中判斷條件往往不同。在 CNStack 2.0 中,就需在 OCM 的 ManagedClusterConditionAvailable 為 true 基礎上,增加對一些管控元件狀態的判斷,才可認為該叢集最終註冊完成。

為了擴充套件性和靈活性,CNStack2.0中,我們參考 Kubernetes Pod Readiness Gates [ 8]  的設計,在 ManagedCluster API 上做了擴充套件,使得可以自定義符合業務需求的叢集註冊成功的狀態。

增強取消註冊能力

叢集取消註冊是透過刪除 ManagedCluster 來觸發的,主要清理註冊叢集過程中在 hub叢集和被管理叢集上建立的資源。在 CNStack 2.0 中這樣的能力還不夠,還會存在以下問題和隱患:

    1. 在取消註冊時,實現多叢集能力的元件也需要清理資源,且需要在清理 OCM Agent 之前完成,否則會在 Hub 叢集和被管理叢集造成垃圾
    2. 叢集取消註冊時,ManifestWork 和 ManagedClusterAddon 等資源不回收會影響叢集的二次註冊和叢集對應 namespace 無法刪除

針對問題 a,我們允許使用者先清理自己建立的資源,然後才執行基礎的取消註冊邏輯(解除安裝 OCM Agent 和清理後設資料)。允許使用者給 ManagedCluster 新增自定義 finalizer,在資源清理完後,刪除相應 finalizer,CNStack 多叢集服務會檢測 ManagedCluster,在沒有使用者自定義 finalizer 以後,才會執行基礎的取消註冊邏輯。

針對問題 b,CNStack 多叢集服務基於問題 a 的機制,在叢集取消註冊時去清理掉叢集相關的 ManifestWork、ManagedClusterAddon 等資源,以確保不會有相應問題出現。

適應不同網路場景的多種註冊模式

在 CNStack 2.0 中,我們從設計上來說,支援兩種註冊模式:Auto 和 Manual。Auto 模式,適用於 Hub 叢集和被管理叢集網路可以互通的場景。這種方式更加自動化,通訊結構更簡單。Manual 模式,適用於只有被管理叢集可以訪問到 Hub 叢集的場景。這種方式比較適用於納管那些因安全性考慮不對外開放的叢集。不過這種模式因為某些原因在 CNStack 2.0 中尚未對使用者透出,後續版本會補齊。

多種分發資源的模式

CNStack 2.0 對多叢集的資源下發支援 Pull 和 Push 兩種模式。支援兩種模式讓多叢集能力更加靈活。

  • Pull 模式

Pull 模式是基於 OCM ManifestWork API 的,OCM 自身提供的能力。該模式的主要優點在於每個被管理叢集都由 agent,可以極大分攤管控叢集的壓力。架構如下圖所示: title=

  • Push 模式

Push 模式是基於 Cluster-Gateway 實現的。該模式的主要優點在於操作方面,也不需要考慮往每個被管理叢集安裝 Agent。架構如下所示:

 title=

使用 Cluster Gateway 除了具備路由透明,許可權一致,通訊安全的能力,還有一個好處是:無論是 Auto 模式還是 Manual 模式,在整合註冊成功後,我們都可以統一使用 Cluster Gateway 訪問被管理叢集的資源。

當然,我們在使用過程中也發現和修復了 Cluster Gateway 的一些問題,最主要的是其在整合 OCM 時的效能問題:在整合 OCM 跨多個叢集訪問時的效能遠落後於直接透過被管理叢集 kubeconfig 訪問,嚴重影響多叢集資源下發和多叢集聚合能力。其主要原因是:Cluster Gateway 在整合 OCM 後,頻繁訪問 Hub 叢集 APIServer,獲取 ManagedCluster,造成 APIServer 限頻,從而 RT 遠高於直接透過 kubeconfig 訪問時的 RT。我們透過增加快取 (Inforemer) [ 9] 解決了該效能問題,從單個 Get 請求的 Benchmark 結果看 RT 減少 95%,與直接透過 kubeconfig 訪問被管理叢集相差無幾。

多叢集多租戶管理與統一認證與鑑權

CNStack 2.0 中,在多叢集雲服務的幫助下,租戶管理與認證和鑑權也擴充套件至多叢集。這裡主要是利用 OCM ManifestWork 機制,將租戶、角色相關資源分發到多個叢集。

使用者對被管理叢集的訪問是使用平臺 UI 或者是平臺提供的 kubeconfig 去訪問的,請求會經過管控叢集的 Management Gateway,Management Gateway 會對請求的使用者進行統一認證。而多叢集鑑權則是透過偽裝(Impersonation) [ 10] 結合下發到被管理叢集的 RBAC 完成,主要流程是 Management Gateway 在認證之後會為請求增加 Impersonate-User Header,再經過 Cluster Gateway 將請求發到被管理叢集的 Kube APIServer。

關於偽裝,這裡有個細節是,請求經過 Hub Kube APIServer 以後,Impersonate-User 這個 header 會被丟棄("Impersonate-"為字首的幾個都會被丟棄)。而 Cluster Gateway 是 Aggregated APIServer,請求都會先到達 Hub Kube APIServer,再到達 Cluster Gateway,因此請求在到達 Cluster Gateway 時已經沒有這個Impersonate-User 這個 header 了。而 Cluster Gateway 有個 ClientIdentityPenetration feature gate,開啟時,可以從請求的 context 中獲取 User 資訊(Name、Groups、Extra),並將其設定到 Header 中。因此 Cluster Gateway 開啟 ClientIdentityPenetration feature gate 後可以保證多叢集鑑權能夠成功完成。

 title=

管控叢集與被管理叢集的互訪

在 CNStack 2.0 中,平臺和雲服務/雲元件有些元件是需要跨管控叢集與被管理叢集通訊的,因此我們在管控叢集與被管理叢集之間構建了通路。架構圖如下所示:

 title=

管控叢集中所有控制面請求都收斂在 Management Gateway,資料面請求收斂在 Ingress Controller;被管理叢集上服務都由 Ingress Controller 代理。

為了遮蔽網路聯通的複雜性,比如對應閘道器代理的 IP 和埠發生變化等,無論是管控叢集訪問被管理叢集 Ingress Controller,還是被管理叢集訪問管控叢集 Management Gateway 和 Ingress Controller,我們都提供透過 Kuberetes Headless Service 實現路由的通路。

CNStack 2.0 中,對被管理叢集的 Kubernetes API 的訪問都經由 Management Gateway 轉 Cluster Gateway 到達被管理叢集 Kube APIServer。使用 Cluster Gateway 的優勢,前文也有表述,具備路由透明,許可權一致,通訊安全的能力,並且方便統一訪問方式。

對於被管理叢集上業務想要透過域名訪問 Ingress Controller 所代理的管控服務時,可以透過增加一個對映到 Headless Service 對應閘道器代理(Management Gateway/Ingress Controller)的 ExternalName Service,然後配合管控叢集上 Ingress 物件的定義,在業務中使用${ExternalName Service}.${Serviece Namespace}.svc訪問。

展望

從多雲、多叢集的領域來說,做好叢集管理是第一步,它很重要,在不同廠商、不同位置、不同網路的叢集都被註冊到管控平臺後,使用者往往期望將應用擴充套件到多個叢集,並期望能提供如應用跨叢集故障遷移、多叢集 Service、容災備份、就近訪問等場景能力。伴隨應用管理而來的還有相關安全合規的策略管理。CNStack 多叢集服務期望後續能夠逐步把這樣的能力展示給使用者。

相關連結

[1] OCM

https://open-cluster-management.io/

[2] registration-operator

https://github.com/open-cluster-management-io/registration-operator

[3] registration

https://github.com/open-cluster-management-io/registration

[4] work

https://github.com/open-cluster-management-io/work

[5] cluster-gateway

https://github.com/oam-dev/cluster-gateway

[6] managed-serviceaccount

https://github.com/open-cluster-management-io/managed-serviceaccount

[7] OCM Agent 只會在建立 ManagedCluster 時候上報 CABundle

https://github.com/open-cluster-management-io/registration/pull/270

[8] Pod Readiness Gates

https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate

[9] 增加快取(Inforemer)

https://github.com/oam-dev/cluster-gateway/pull/117

[10] 偽裝(Impersonation)

https://kubernetes.io/docs/reference/access-authn-authz/authe...

相關文章