Clusternet v0.5.0 重磅釋出: 全面解決多叢集應用分發的差異化配置難題

騰訊雲原生發表於2021-10-21

作者

徐迪,騰訊雲容器技術專家。
汝英哲,騰訊雲高階產品經理。

摘要

在做多叢集應用分發的時候,經常會遇到以下的差異化問題,比如:

  1. 在分發的資源上全部打上統一的標籤,比如 apps.my.company/deployed-by: my-platform
  2. 在分發到子叢集的資源上標記叢集的資訊,比如 apps.my.company/running-in: cluster-01
  3. 調整應用在每個叢集中的副本數目、映象名稱等等,比如有一個名為 my-nginx (宣告的副本數為 3)的 Deployment 應用要分發到叢集 cluster-01,叢集 cluster-02,叢集 cluster-03 中,我希望在這三個叢集的副本數目分別為 3,5,7;
  4. 在分發到叢集 cluster-01 之前,調整應用在該叢集中的一些配置,比如注入一個 Sidecar 容器等;
  5. 遇到某些特殊場景時,例如大促,動態擴容,應用灰度升級時,希望可以針對某個叢集進行操作,變更範圍小,不影響到其他叢集,同時出現問題的時候,可以及時回滾,恢復到變更前的狀態;
  6. 如果定義了多個差異化配置,相互之間出現衝突時,該如何解決;

開源 Clusternet 專案簡介

Clusternet ( Cluster Internet ) 是騰訊雲開源的兼具多叢集管理和跨叢集應用編排的雲原生管控專案,讓使用多叢集就像上網一樣簡單。無論你的 Kubernetes 叢集是執行在公有云、私有云、混合雲還是邊緣雲上,都擁有一致的管理/訪問體驗,利用 K8s API 集中部署和協調多叢集的應用程式和服務。

Clusternet 採用 Addon 外掛的方式,方便使用者一鍵安裝、運維及整合,輕鬆地管理數以百萬計的 Kubernetes 叢集,讓雲端計算像 Internet 一樣無所不在,自由便捷。

Clusternet 支援向不同叢集分發和管理各種應用資源,包括原生 Kubernetes 各類資源(Deployment/StatefulSet/ConfigMap/Secret 等)、各類 CRD 資源,以及 HelmChart 應用等等。

Clusternet 如何解決這些差異化配置難題

Clusternet 在設計應用分發模型的時候,就充分考慮到了上述的那些場景,不希望引入過多的複雜設計,儘量減少使用者的重複定義,做到精簡化、方便配置、可擴充套件性強、便於變更回滾等等。

如果我們將上述的差異化問題進行歸納,大致可以歸納為以下兩類:

  1. 通用化配置或者全域性化配置,比如對於某些資源進行無差異化的打標籤,預配置等等;

  2. 專屬於某個叢集的配置,比如更改 Deployment 在某叢集對應的副本數,升級映象,增加 Sidecar 容器等等;

下圖是 Clusternet 的多叢集應用分發模型,其中綠色的模組是需要使用者去建立的,紫色的模組是 Clusternet 內部做流轉的資源物件。Clusternet 提供了 kubectl 外掛,可以通過 “kubectl clusternet apply” 命令來建立資源。歡迎閱讀 Clusternet - 新一代開源多叢集管理與應用治理專案,瞭解圖中的相關概念。

Clusternet 資源分發模型採用鬆耦合的設計,使用者無須更改或重新編寫已有的資源物件,僅需要額外定義分發策略 (Subscription)和差異化配置(Localization/Globalization)即可實現多叢集的應用分發。

Localization 與 Globalization

在 Clusternet 中,每個註冊的叢集,都會擁有一個專屬的 namespace (名稱空間),因此我們分別定義了 LocalizationGlobalization 這兩個 CRD 用於宣告差異化配置。其中 Localization 描述 namespace-scoped (名稱空間作用域)的差異化配置策略,可用於對單個叢集進行配置,比如 Deployment 在這個叢集中的副本數目等。而 Globalization 描述 cluster-scoped (叢集作用域) 的差異化配置策略,比如修改某個 HelmChart 的通用配置等。

Override 策略

Clusternet 還提供了兩種 Overide 策略:ApplyLater(預設的策略)和 ApplyNowApplyLater 意味著該 Localization/Globalization 的差異化配置不會立即應用到資源上,只會在隨後新建立出來的 Description 物件或者 HelmChart/Subscription/Description 等各個資源物件更新的時候才生效。而 ApplyNow 意味著會建立後即時生效,Clusternet 會將定義的差異化配置應用到所有匹配的物件中,即時下發到對應的子叢集中。

Priority 優先順序

此外,兩者均支援按照 Priority(優先順序)進行管理和配置,優先順序的高低通過 0-1000 的數值來定義,值越小,優先順序越低,預設是500。在進行差異化渲染的時候,Clusternet 會按照 Globalization (低優先順序) -> Globalization (高優先順序) -> Localization (低優先順序) -> Localization (高優先順序) 的次序,依次將宣告的 Override 進行 apply。

正是藉助於這種兩階段基於優先順序two-stage priority based)的差異化配置能力,Clusternet 可以很方便地支援面向多叢集的藍綠髮布、金絲雀釋出、版本升級等場景。在使用過程中, 你可以定義多個 GlobalizationLocalization 物件,並設定不同的優先順序策略。

支援 Patch 操作

Clusternet 支援兩種格式的 Override,JSON Patch (RFC 6902) 和 JSON Merge Patch (RFC 7396)。有關 JSON patch 和 JSON 合併 patch 的比較,大家可以檢視 JSON Patch 和 JSON Merge Patch,也可以參照如下的典型示例。

典型示例

下面我們來看幾個典型的差異化配置場景。在如下的例子中,我們通過 Localization 物件來統一展示。這裡使用 Globalization 也是可以的,這兩者的 Spec 定義都是一樣的,唯一的區別這兩者的作用域和優先順序差別。大家在實際使用的時候,可以根據需要進行改寫。

增加/更新標籤

如果我們想給某個物件增加或者更新標籤,可以這麼定義如下的 Localization 物件。在使用的時候,請將 metadata.namespace 的值替換為真實的註冊叢集的專屬 namespace。

apiVersion: apps.clusternet.io/v1alpha1
kind: Localization
metadata:
  name: nginx-local-overrides-demo-label
  namespace: clusternet-5l82l # 請更新這個值為對應叢集的 namespace
spec:
  overridePolicy: ApplyLater
  # 優先順序反映著該物件的重要性,數值範圍從 0 到 1000,值越小表示優先順序越低
  # 預設的值為 500.
  priority: 300
  feed: # 這裡表示要 override 的物件
    apiVersion: apps/v1
    kind: Deployment
    name: my-nginx
    namespace: foo
  overrides: # 這裡可以定義著多個 override
    - name: add-update-labels
      type: MergePatch # 這裡需要指定 override 的型別
      # value 可以是 yaml 格式,也可以是 json 格式。
      # 如下是 json 格式的例子
      value: '{"metadata":{"labels":{"deployed-in-cluster":"clusternet-5l82l"}}}'

可以在一個 Localization 物件中定義多個 overrides,在上面的例子中,我們只定義了一個名為 add-update-labels 的 override,其值為 json 格式的字串,目的是增加或者更新一個標籤 deployed-in-cluster: clusternet-5l82lspec.feed 所定義的物件中。

這裡 override 的值也可以 yaml 格式,見如下的例子。

apiVersion: apps.clusternet.io/v1alpha1
kind: Localization
metadata:
  name: nginx-local-overrides-demo-label
  namespace: clusternet-5l82l # 請更新這個值為對應叢集的 namespace
spec:
  overridePolicy: ApplyLater
  # 優先順序反映著該物件的重要性,數值範圍從 0 到 1000,值越小表示優先順序越低
  # 預設的值為 500.
  priority: 300
  feed: # 這裡表示要 override 的物件
    apiVersion: apps/v1
    kind: Deployment
    name: my-nginx
    namespace: foo
  overrides: # 這裡定義著 override value
    - name: add-update-labels
      type: MergePatch
      # value 可以是 yaml 格式,也可以是 json 格式。
      # 如下是 yaml 格式的例子
      value: |-
        metadata:
          labels:
            deployed-in-cluster: clusternet-5l82l

替換映象及副本數目

Override 的型別也可以指定為 JSONPatch。在實際使用的時候,可以根據需要選擇一個合適的 override 型別即可。

通過如下的例子,可以將 Deployment foo/my-nginxclusternet-5l82l 子叢集中的副本數更改為 3,替換容器的映象為 nginx:1.14.0-alpine,並增加一個新的註釋 foo: bar

apiVersion: apps.clusternet.io/v1alpha1
kind: Localization
metadata:
  name: nginx-local-overrides-demo-image-replicas
  namespace: clusternet-5l82l # 請更新這個值為對應叢集的 namespace
spec:
  overridePolicy: ApplyLater
  # 優先順序反映著該物件的重要性,數值範圍從 0 到 1000,值越小表示優先順序越低
  # 預設的值為 500.
  priority: 400
  feed: # 這裡表示要 override 的物件
    apiVersion: apps/v1
    kind: Deployment
    name: my-nginx
    namespace: foo
  overrides: # 這裡定義著 override value
    - name: scale-and-add-annotations
      type: JSONPatch
      # value 可以是 yaml 格式,也可以是 json 格式。
      value: |-
        - path: /spec/replicas
          value: 3
          op: replace
        - path: "/spec/template/spec/containers/0/image"
          value: "nginx:1.14.0-alpine"
          op: replace
        - path: /metadata/annotations
          value:
            foo: bar
          op: add

注入 Sidecar 容器

我們還可以通過 Localization 來為 Deployment foo/my-nginxclusternet-5l82l 子叢集下的例項注入 Sidecar 容器,見如下的示例,

apiVersion: apps.clusternet.io/v1alpha1
kind: Localization
metadata:
  name: nginx-local-overrides-demo-sidecar
  namespace: clusternet-5l82l # 請更新這個值為對應叢集的 namespace
spec:
  overridePolicy: ApplyLater
  # 優先順序反映著該物件的重要性,數值範圍從 0 到 1000,值越小表示優先順序越低
  # 預設的值為 500.
  priority: 600
  feed: # 這裡表示要 override 的物件
    apiVersion: apps/v1
    kind: Deployment
    name: my-nginx
    namespace: foo
  overrides: # 這裡定義著 override value
    - name: inject-new-container
      type: JSONPatch
      # value 可以是 yaml 格式,也可以是 json 格式。
      value: |-
        - op: add
          path: "/spec/template/spec/containers/1"
          value:
            name: "redis-container"
            image: "redis:6.2.5"

通過 LocalizationGlobalization 不僅僅可以做如上的差異化配置,還有更多的場景等待著大家去發掘。

為了方便大家上手體驗一番,Clusternet 提供了例子,大家可以參照 README 中的步驟來實踐一下多叢集的應用分發。

加入我們

Clusternet 專案開源進行時,請關注 https://github.com/clusternet/clusternet 點贊支援,歡迎加入我們一起貢獻更多的功能。

相關連結

[1] https://github.com/clusternet/clusternet

[2] https://github.com/clusternet/kubectl-clusternet

[3] https://krew.sigs.k8s.io/plugins/

關於我們

更多關於雲原生的案例和知識,可關注同名【騰訊雲原生】公眾號~

福利:

①公眾號後臺回覆【手冊】,可獲得《騰訊雲原生路線圖手冊》&《騰訊雲原生最佳實踐》~

②公眾號後臺回覆【系列】,可獲得《15個系列100+篇超實用雲原生原創乾貨合集》,包含Kubernetes 降本增效、K8s 效能優化實踐、最佳實踐等系列。

【騰訊雲原生】雲說新品、雲研新術、雲遊新活、雲賞資訊,掃碼關注同名公眾號,及時獲取更多幹貨!!

相關文章