天天看點

Clusterpedia 使用心得

作者:DaoCloud 道客
Clusterpedia 使用心得

Kubernetes 帶來的雲原生技術革命已席卷全球,越來越多的業務應用運作在 Kubernetes 平台上,随着業務規模的擴充,叢集數量與日俱增,多叢集内部資源管理和檢索越來越複雜,多雲管理面臨巨大挑戰。在多叢集時代,我們可以通過 Cluster-api 來批量建立管理叢集,使用 Karmada/Clusternet 來分發部署應用。不過我們貌似還是缺少了什麼功能,我們要如何去統一地檢視多個叢集中的資源呢?

Clusterpedia,名字借鑒自 Wikipedia,同樣也展現了 Clusterpedia 的核心理念 —— 多叢集的百科全書。

通過聚合多叢集資源,在相容 Kubernetes OpenAPI 的基礎上額外提供了更加強大的檢索功能,讓使用者更快更友善地在多叢集中擷取到想要的任何資源。

01

術語

Kube-APIServer:API 伺服器是 Kubernetes 控制平面的元件, 該元件負責公開了 Kubernetes API,負責處理接受請求的工作,API 伺服器是 Kubernetes 控制平面的前端。

KubernetesOpenAPI: 外部第三方系統通過該接口可以與 Kubernetes 進行互動。

Aggregated APIServer: 是為了将原來的 APIServer 這個應用給拆分,為了友善使用者開發自己的 APIServer 內建進來,而不用直接修改 Kubernetes 官方倉庫的代碼,這樣一來也能将 APIServer 解耦,友善使用者使用實驗特性。

CustomResourceDefinition: 通過定制化的代碼給你的 Kubernetes API 伺服器增加資源對象,而無需編譯完整的定制 API 伺服器。

GVK/GVR: 當我們在一個特定的群組版本 (Group-Version) 中提到一個 Kind 時,我們會把它稱為 GroupVersionKind,簡稱 GVK。與 資源 (resources) 和 GVR 一樣,每個 GVK 對應 Golang 代碼中的 Go type。

PediaCluster:每個叢集對應一個 PediaCluster,具體指代該叢集的認證資訊以及需要同步緩存的資源資訊。

Clusterpedia APIServer: 以 Aggregated API 的方式注冊到 Kube APIServer,通過統一的入口來提供服務。

Cluster Synchro:每個叢集會對應一個同步資源對象,收集需要同步與緩存的資料資訊。

ClusterSynchro Manager: 在部署的控制面層進行 Cluster Synchro 執行個體的管理。

Karmada: 全稱 Kubernetes Armada,是一個 Kubernetes 管理系統,可讓您跨多個 Kubernetes 叢集和雲運作您的雲原生應用程式,而無需更改應用程式;通過使用 Kubernetes 原生 API 并提供進階排程功能,Karmada 可以實作真正的開放式多雲 Kubernetes。

02

能力介紹

1. 叢集接入,自動發現

0.4.0 後,Clusterpedia 提供了更加友好地接入多雲平台的方式。使用者通過建立 ClusterImportPolicy 來自動發現多雲平台中納管的叢集,并将這些叢集自動同步為 PediaCluster,使用者不需要根據納管的叢集來手動去維護 PediaCluster 了。

在下面業務模型介紹時候,會詳細介紹該功能。

2. 指定叢集檢索

Clusterpedia 不僅僅支援多叢集的聚合查詢,也可以指定某一個叢集進行查詢,如下圖所示,我們接入了 arm 和 x86 兩套 k8s 叢集。

可以指定 x86 叢集進行 po 的檢索。

Clusterpedia 使用心得
Clusterpedia 使用心得

3. 對資源進行更複雜的操作

原生 Kubernetes 目前隻支援對 metadata.name 和 metadata.namespace 的字段過濾,而且操作符隻支援 =,!=,==,能力非常有限。

Clusterpedia 在相容已有的 field selector 功能的基礎上,提供了更加強大的功能,支援和 label selector 相同的操作符,如下檢索:

Clusterpedia 使用心得

也可以支援直接拼接 sql 語句查詢:

kubectl get --raw="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments?whereSQL=(cluster='arm-cluster-example') OR (namespace IN ('kube-system','default'))"

Clusterpedia 使用心得

也支援查詢 pod 的建立時間區間。

Clusterpedia 使用心得
Clusterpedia 使用心得

4. 多叢集檢索

多個叢集資源一起搜尋也是可以的, 如下展示:

Clusterpedia 使用心得

5. 特性功能 FeatureGates

使用者在使用特性功能時,需要開啟相應的特性開關。

Clusterpedia APIServer 和 Clusterpedia ClusterSynchro Manager 分别具有不同的特性功能。

如下圖開啟特性所示:

Clusterpedia 使用心得

APIServer 支援:RemainingItemCount,AllowRawSQLQuery,預設都不開啟。

ClusterSynchro Manager 支援:PruneManagedFields(預設開啟),PruneLastAppliedConfiguration(預設開啟),AllowSyncCustomResources,AllowSyncAllResources。

5.1 RemainingItemCount

它是 Kubernetes 之上的一個增強資源分頁功能。在 Kubernetes 分頁的基礎上,Clusterpedia 複用 ListOptions.Limit 和 ListOptions.Continue 字段作為分頁的 size 和 offset,但為了避免 kubectl 進行對全量資料的分片拉取,Clusterepdia 不會在響應中攜帶 Continue 資訊。

在一些 UI 場景下,往往會需要擷取到目前檢索條件下的資源總量,是以打開 RemainingItemCount 功能即可獲得資源分頁時候的總數與剩餘數量,由于存儲層傳回剩餘資源數量會導緻額外的 COUNT 查詢,對性能有一定影響,是以該功能預設是關閉的。

5.2 AllowRawSQLQuery

該特性專屬于 Clusterpedia APIServer,可以在資源查詢時候直接使用原生的 sql 語句。

不同的使用者的需求可能是不同的,盡管 Clusterpedia 提供了很多簡便的檢索條件,例如指定一組命名空間或者資源名稱,也可以指定 owner 進行查詢,但是使用者依然可能會有更加複雜的查詢。

URL="/apis/clusterpedia.io/v1beta1/resources/apis/apps/v1/deployments"

kubectl get --raw="$URL?whereSQL=(cluster='global') OR (namespace IN ('kube-system','default'))"

示例中,我們傳遞一個用于 WHERE 查詢的 SQL 語句 ,(cluster=‘global’) OR (namespace IN (‘kube-system’,‘default’)),

這個語句會檢索 global 叢集内所有命名空間下以及其他叢集中 kube-system 和 default 命名空間下的 deployments。

5.3 PruneManagedFields/PruneLastAppliedConfiguration

資源的 Metadata 中有一些字段在實際搜尋中通常沒有太大用處,是以在同步時我們會預設裁剪這些字段。

我們使用該特性來分别控制這些字段是否在資源同步時被裁剪,這些特性專屬于 Clustersynchro Manager 元件,且預設開啟

5.4 AllowSyncAllCustomResources

自定義資源不同于 Kubernetes 的内置資源,Kubernetes 的内置資源通常不會經常性變動,而自定義資源的類型可能會被動态的建立和删除。

使用者如果想要根據被納管叢集中的 CRD 的變動來自動調節同步的資源類型,那麼使用者在 PediaCluster 中指定同步所有自定義資源。

Clusterpedia 使用心得

該功能可能會導緻大量的長連接配接,是以需要在 Clustersynchro Manager 中開啟該 feature。

5.5 AllowSyncAllResources

使用者可以通過全資源通配符來同步所有類型的資源,當被納管叢集中發生任意的資源類型變動(例如 Kubernetes 版本更新,group/version 被禁用,CRD 或者 APIService 變動)都會導緻同步的資源類型發生修改。

Clusterpedia 使用心得

該功能會建立大量的長連接配接,建議指定具體的資源類型,如果需要對自定義資源進行動态同步,可以使用同步所有的自定義資源(AllowSyncAllCustomResources)。

03

業務模型

1. PediaCluster

自定義資源類型 CRD,PediaCluster 有兩個作用: 配置叢集的認證資訊 , 配置同步的資源。

Clusterpedia 使用心得

通過上面的生成對象,可接入 APIServer 對應配置到 Clusterpedia 裡面進行資源檢索與同步。

有三個字段可以配置同步的資源:

spec.syncResources 配置該叢集需要同步的資源。

spec.syncAllCustomResources 同步所有的自定義資源。

spec.syncResourcesRefName 引用公共的叢集資源同步配置。

也可配合下面的 ClusterImportPolicy 生成 PediaClusterLifecycle,進行自動的叢集發現與管理。

2. ClusterSyncResources

自定義資源類型 CRD,提供了公共的叢集資源同步配置

Clusterpedia 使用心得

spec.syncResources 字段和 PediaCluster 的 spec.syncResources 配置方式相同,可參考 PediaCluster 使用方式。

當我們修改 ClusterSyncResources 時,所有引用它的 PediaCluster 内同步的資源都會發生相應的修改。

3. Storage

Clusterpedia 的預設存儲層支援 MySQL 和 PostgreSQL 兩種存儲元件。

Clusterpedia 使用心得

使用者在安裝 Clusterpedia 時,可以使用已存在的存儲元件,不過需要建立相應的預設存儲層配置 ConfigMap 和存儲元件密碼 Secret。

Clusterpedia 的安裝 yaml 會從 internalstroage-password 的 Secret 中擷取密碼。

将存儲元件的密碼配置到 Secret 中

Clusterpedia 使用心得

4. ClusterImportPolicy

Clusterpedia 使用心得

通過上圖,大概描述下,ClusterImportPolicy,PediaClusterLifecycle,PediaCluster , Cluster 的關系。

(1) 建立一個 ClusterImportPolicy 對象,可以通過 spec 裡面的 source/references 等關鍵字找到 Karmada 叢集

(2) Karmada 認證資訊打通後,并傳回給政策 ClusterImportPolicy

(3) 接下來會根據 ClusterImportPolicy 配置的 PediaClusterLifecycle 建立時機,當條件滿足時候,會建立 PediaClusterLifecycle,

(4) 一個 PediaClusterLifecycle 會對應一個 PediaCluster , 當某個叢集加入 Karmada 的控制面時候,會傳遞事件過來,PediaClusterLifecycle 監聽到後同步建立 PediaCluster

(5) 每個 PediaCluster 會對應具體的一個叢集, 會把裡面的具體配置的資源進行緩存同步,以便檢索時候快速搜尋。

下面,我們會舉一個例子,當我們通過該動态政策,接入已有的 Karmada 叢集。

如下是我提前準備的 karmada 叢集,接入了 member1 和 member2 叢集

Clusterpedia 使用心得
Clusterpedia 使用心得

下發測試資源進行驗證。

Clusterpedia 使用心得
Clusterpedia 使用心得

下面會在該 Karmada 叢集進行 Clusterpedia 的部署。

Clusterpedia 使用心得

部署成功, 下發資源 ClusterImportPolicy 前叢集狀态。

Clusterpedia 使用心得

下發資源後叢集狀态。

Clusterpedia 使用心得

測試下跨叢集的通路。

Clusterpedia 使用心得
Clusterpedia 使用心得

上面大概示範了下, 在 Karmada 平面內建 Clusterpedia 的情況,下面說明下各字段的具體含義,

spec.source 和 spec.references 分别定義 Source 資源和 References 資源。

什麼叫 Source 資源和 References 資源呢?因為該特性是為了可以動态接入叢集。Clusterpedia 需要接入叢集的話,要先定義 PediaCluster,配置每個叢集的認證資訊, 而通過該特性,現在可以定義一個 ClusterImportPolicy ,這個裡面包含的 Source 就是該多雲平台的來源認證資訊,而 References 資源是額外被引用的資源資訊,比如 Karmada 叢集接入,還需要 secrets 等資訊等,這時候該 secrets 資訊就可以放入 References 進行定義。

spec.nameTemplate 定義生成的 PediaClusterLifecycle 和 PediaCluster 的名稱,可以根據 Source 資源進行渲染。

spec.template 和 spec.creationCondition 定義資源模版建立,以及建立的條件。

當一個 Source 被建立後,ClusterImportPolicy Controller 會根據 ClusterImportPolicy 建立相應的 PediaClusterLifecycle 資源。

5. PediaClusterLifecycle

它是和 ClusterImportPolicy 相關的資源,通過上面介紹 ClusterImportPolicy 時候,我們可以知道該 CRD 的大概功能。

下面我們具體詳細的描述下該資源資訊:

Clusterpedia 使用心得

通過上面定義的 ClusterImportPolicy 進行内部轉化生成,PediaClusterLifecycle 資源的名字是通過 ClusterImportPolicy 的 spec.nameTemplate 字段來設定的。

首先需要在 ClusterImportPolicy 資源中定義監聽(想要轉換的)的資源類型,我們将被監聽的資源稱為 Source 資源。

PediaClusterLifecycle 會根據具體的 Source 資源的變動情況,來進行相應 PediaCluster 的建立/更新/删除等動作。

對于 ClusterImportPolicy 和 PediaClusterLifecycle 的調協由 Clusterpedia Controller Manager 内的 ClusterImportPolicy Controller 和 PediaClusterLifecycle Controller 負責。

04

原理分析

1. 整體架構

Clusterpedia 使用心得

如圖所示,Clusterpedia 主要有兩個元件:

ClusterSynchroManager :管理主叢集内的 PediaCluster 資源,通過 PediaCluster 配置認證資訊連接配接到指定叢集,并且實時同步相應的資源。

APIServer:同樣會監聽主叢集内的 PediaCluster 資源,并根據叢集同步的資源以相容 Kubernetes OpenAPI 的方式來提供對資源的複雜檢索,Clusterpedia APIServer 會以聚合式 API 的方式注冊到主叢集的 APIServer 中, 這樣我們通過和主叢集相同的入口便可通路 Clusterpedia。

在較新的版本中,引入了 ControllerManager 控制器,主要為了實作外部叢集的動态發現與注冊:包括了兩個 Controller ,分别對于 ClusterImportPolicy,PediaClusterLifecycle,PediaCluster 資源對象的調協作用。

2. 内部介紹

2.1 Clusterpedia-APIServer

Clusterpedia-APIServer 大概邏輯是以 Aggregated API 的方式注冊到 Kube APIServer,通過統一的入口來提供服務。

部署程式時候,會注冊 APIService,通過擴充 Aggregated APIServer 接口進行程式開發。

主要負責是接受外部通路請求,通過調用 Storage 接口,從資料庫傳回使用者需要的資料。

内部通過 RESTStorage 實作了 k8s.io/apiserver/pkg/registry/rest/rest.go 的 Lister 和 Getter 接口,在使用者通過 API 通路到該接口時候,通過内嵌的 Storage 的接口從資料庫擷取資料,加快了傳回與檢索速度

如下圖描述内部的邏輯流向:

Clusterpedia 使用心得

(1) cmd 啟動時候,初始化

(2) genericeServer 擴充接口的代理實作體

(3) 注冊 GenericeServer

(4) 綁定對應的資源/版本到 generice 實作接口裡面

2.2 ClustersynchroManager

ClustersynchroManager 大概邏輯如下:

Clusterpedia 使用心得

(1) 啟動入口,配置啟動相應的參數以及初始化 Storage 存儲接口

(2) 初始化 Kubernetes ClientSet 接口,ClusterSynchro Crd ClientSet 接口和對應的 Informer Factory,并啟動隊列進行事件的監聽與派發

(3) 啟動多個協程,進行隊列的邏輯處理

(4) 啟動 Informer 進行事件的捕獲與本地隊列存儲

(5) 通過 informer 機制,監聽叢集資源 PediaCluster CR 的增删改事件,并進入隊列進行 Reconcile 調和,通過 PediaCluster CR Spec 裡面定義的 syncResources 字段資訊,以及監聽到 PediaCluster 變化,加入事件隊列,緩存并更新到 DB 進行存儲

(6) 首先判斷該 PediaCluster 是否被打上了 delete 标記時候,如果是:會進行叢集的清理動作,包括停止該叢集的監聽與緩存程式,同時會清除 DB 資料庫表 Resource 存儲的該叢集 cluster 相關的記錄;然後判斷是否有 finalizer 字段,如果有的話則删除 PediaCluster 資源的 finalizer 字段;沒有被标記删除事件,會判斷該 PediaCluster 是否有 finalizer 字段,沒有的話要給該 PediaCluster 加上 finalizer 字段;通過 PediaCluster 存儲的叢集資訊,建立通路 Kubernetes 叢集的 config 對象。

(7) 這時候會分兩步進行判斷,先看全局緩存中,是否該 PediaCluster 已經在運作了,如果有了緩存并且配置檔案沒有變化,則使用緩存的對象 ;如果沒有緩存,或者配置檔案發生了變化,則删除緩存資料,重新建立一個 ClusterSynchro 并運作主 Run 方法。

(8) 通過 ClusterSynchro 的 SetResource 方法,設定具體需要同步的資源。

Clusterpedia 使用心得

(1) 初始化 ClusterSynchro,每一個 PediaCluster 對象,會生成一個對應的 ClusterSynchro,通過 Informer 緩存 PediaCluster 定義的 SyncResources 資源組,存儲進 DB 資料庫供外部通路使用。

(2) dynamicDiscoveryManager 會通過 startAggregatorResourceWatcher,startServerVersionWatcher 監控資源 GVR 和緩存的比對情況, 或者叢集是否更新,比如版本的更新等。如有變動,觸發事件 chan 通知 resetSyncResources 函數運作,讓資源再次開始同步動作。

(3) 分别啟動 crdController,apiServiceController 進行資源變動的監聽,負責通過 chan 事件進行資源的緩存與同步 DB 操作。

(4) 分别啟動 monitor 協程,通過定時器通路 Kubernetes 叢集的/readyz 或者/healthz 接口,檢測叢集是否健康,根據叢集目前的健康狀态,自動啟停資源收集;通過 monitor 健康檢測的結果,啟動和停止資源的收集與緩存功能。

(5) 叢集狀态更新,如果有更新事件,則會更新叢集的 status 狀态

(6) 觸發資源同步的 chan。

(7) 資源同步 chan,等待信号量,收到時候,即進入 setSyncResources()處理緩存的同步。

(8) 緩存變更邏輯時候,會通過 ResourceNegotiator 判斷是否需要更新資源情況,根據以前緩存的資訊與目前叢集資訊進行比對,判斷是否更新 DB 資料。

(9) 通過 PediaCluster 定義的需要緩存的 GVR 等資訊,分類通過 ResourceSynchro 進行檢測以及更新,它會通過 Storage 接口通路 DB 層,把叢集的對應 GVR 資料與 DB 進行同步。

3. Clusterpedia-controller-manager

Clusterpedia-controller-managerr 大概邏輯如下:

Clusterpedia 使用心得

(1) 啟動入口,參數初始化,運作環境初始化;

(2) 内部運作函數,會進行一系列的初始化工作;

(3) 初始化 clusterimportpolicy controller;

(4) clusterimportpolicy controller 内部監聽的資源以及變動更新回調函數;

(5) 初始化 lifecycle controller;

(6) lifecycle controller 内部監聽的資源以及變動更新回調函數;

(7) 啟動 controller。

05

總結

目前多雲已經越來越流行,跨叢集檢索能力也受到了很高的重視,以前的單叢集 Informer 機制已經不能滿足檢索要求。

目前社群裡面有 Karmada 自身,在 1.2 版本引入的 karmada-search 元件進行資源檢索能力,通過送出 ResourceRegistry 資源對象在 Karmada-apiserver 控制平面注冊,便可使用 search API 進行檢索。

另一方面 ClusterPedia 社群也在蓬勃的發展中,ClusterPedia 在檢索上最大的優勢就是除了可以使用 Kubectl 操作,以及很多複雜條件(模糊搜尋,字段過濾,清單字段支援,根據父輩以及祖輩 Owner 查詢,分頁與排序等)以外,還能夠納管版本 1.10 到 1.24 的叢集,而且即使這些叢集内的資源版本不同,我們也可以使用統一的資源版本來檢索,目前 0.4 以後的版本,也增強了叢集接入能力,可以和 Karmada、Kubevela、Cluster-api 等其他多雲平台一起結合,自動轉換叢集資訊進入 ClusterPedia 控制面,使用者隻需要定義一個資源對象 ClusterImportPolicy。

本文作者

楊剛

現任「DaoCloud 道客」雲原生資深研發工程師

參考文檔:

https://clusterpedia.io/zh-cn/

https://github.com/clusterpedia-io/clusterpedia

繼續閱讀