天天看點

更靈活的邊緣雲原生運維:OpenYurt 單元化部署新增 Patch 特性背景新的需求特性示範總結

更靈活的邊緣雲原生運維:OpenYurt 單元化部署新增 Patch 特性背景新的需求特性示範總結

作者 | 張傑(冰羽)

來源 |

阿裡巴巴雲原生公衆号

背景

在正文開始之前,我們先回顧一下單元化部署的概念和設計理念。在邊緣計算場景下,計算節點具有很明顯的地域分布屬性,相同的應用可能需要部署在不同地域下的計算節點上。以 Deployment 為例,如下圖所示,傳統的做法是先将相同地域的計算節點設定成相同的标簽,然後建立多個 Deployment,不同 Deployment 通過 NodeSelectors 標明不同的标簽,進而實作将相同的應用部署到不同地域的需求。

更靈活的邊緣雲原生運維:OpenYurt 單元化部署新增 Patch 特性背景新的需求特性示範總結

但是随着地域分布越來越多,使得運維變得越來越複雜,具體表現在以下幾個方面:

  • 當鏡像版本更新,需要修改大量相關的 Deployment 的鏡像版本配置。
  • 需要自定義 Deployment 的命名規範來表明相同的應用。
  • 缺少一個更高的視角對這些 Deployment 進行統一管理和運維。運維的複雜性随着應用和地域分布增多出現線性增長。

基于以上需求和問題,openyurt 的 yurt-app-manager 元件提供的單元化部署(UnitedDeployment)通過更上層次的抽象,對這些子的 Deployment 進行統一管理:自動建立/更新/删除,進而大幅簡化了運維複雜度的問題。

yurt-app-manager 元件: 

https://github.com/openyurtio/yurt-app-manager

如下圖所示:

更靈活的邊緣雲原生運維:OpenYurt 單元化部署新增 Patch 特性背景新的需求特性示範總結

單元化部署(UnitedDeployment)對這些 Workload 進行了更高層次的抽象,UnitedDeployment 包含兩個主要配置:WorkloadTemplate 和 Pools。workloadTemplate 格式可以是Deployment 也可以是Statefulset。Pools 是一個清單,每個清單都有一個 Pool 的配置,每個 Pool 都有它的 name、replicas 和 nodeSelector 配置。通過 nodeSelector 可以選擇一組機器, 是以在邊緣場景下 Pool 我們可以簡單的認為它代表了某個地域下的一組機器。使用WorkloadTemplate + Pools 的定義,我們可以很容易的将一個 Deployment 或者 Statefulset 應用分發到不同的地域中去。

下面是一個具體的 UnitedDeployment 例子:

apiVersion: apps.openyurt.io/v1alpha1
kind: UnitedDeployment
metadata:
  name: test
  namespace: default
spec:
  selector:
    matchLabels:
      app: test
  workloadTemplate:
    deploymentTemplate:
      metadata:
        labels:
          app: test
      spec:
        selector:
          matchLabels:
            app: test
        template:
          metadata:
            labels:
              app: test
          spec:
            containers:
            - image: nginx:1.18.0
              imagePullPolicy: Always
              name: nginx
  topology:
    pools:
    - name: beijing
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - beijing
      replicas: 1
    - name: hangzhou
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - hangzhou
      replicas: 2           

UnitedDeployment 控制器的具體邏輯如下:

使用者定義了一個 UnitedDeployment CR , CR 裡定義了一個 DeploymentTemplate 和兩個 Pool。

  • 其中 DeploymentTemplate 格式為一個 Deployment 格式定義,本例子中使用的 Image 為 nginx:1.18.0。
  • Pool1 的 name 為 beijing, replicas=1,nodeSelector 為 apps.openyurt.io/nodepool=beijing。代表 UnitedDeployment 控制器将要建立一個子的 Deployment,replicas 為 1,nodeSelector 為 apps.openyurt.io/nodepool=beijing,其他的配置繼承自 DeploymentTemplate 配置。
  • Pool2 的 name 為 hangzhou,replicas=2, nodeSelector 為 apps.openyurt.io/nodepool=hangzhou,代表 UnitedDeployment 控制器将要建立一個子的 Deployment,replicas 為 2,nodeSelector 為 apps.openyurt.io/nodepool=hangzhou,其他的配置繼承自 DeploymentTemplate 配置。

UnitedDeployment 控制器檢測到 name 為 test 的 UnitedDeployment CR 執行個體被建立後,會首先根據 DeploymentTemplate 裡的配置生成一個 Deployment 的模闆對象,根據 Pool1 和 Pool2 的配置和 Deployment 的模闆對象,分别生成 name 字首為 test-hangzhou- 和 test-beijing- 的兩個 deployment 資源對象,這兩個 Deployment 資源對象有自己的 nodeselector 和 replica 配置。這樣通過使用 workloadTemplate+Pools 的形式,可以将 workload 分發到不同的地域,而無需使用者維護大量的 Deployment 資源。

UnitedDeployment 所解決的問題

UnitedDeployment 通過一個單元化部署執行個體就可以自動維護多個 Deployment 或者 Statefulset 資源,每個 Deployment 或者 Statefulset 資源都遵循統一的命名規範。同時還能實作 Name、NodeSelectors 和 Replicas 等的差異化配置。能極大地簡化使用者在邊緣場景下的運維複雜度。

新的需求

UnitedDeployment 能滿足使用者的大部分需求,但是在我們進行推廣和客戶落地以及在與社群同學讨論的過程中,逐漸發現在一些特殊場景下,UnitedDeployment 提供的功能還顯得有點不足,例如如下場景:

  • 應用鏡像更新時候,使用者計劃先在在某個節點池中做驗證,如果驗證成功,再在所有節點池中全量更新釋出。
  • 為了加快鏡像拉取速度,使用者可能在不同節點池中搭建自己的私有鏡像倉庫,是以同一個應用在每個節點池下的鏡像名會不一樣。
  • 不同的節點池下伺服器數量,規格,以及業務通路壓力不一緻,是以同一個應用在不同節點池下 pod 的 cpu,記憶體等配置會不一樣。
  • 同一個應用在不同節點池下可能會使用不同的 configmap 資源。

這些需求促使了 UnitedDeployment 需要提供針對每個 Pool 做一些個性化配置的功能,允許使用者根據不同節點池下的實際情況做一些個性化的配置,比如鏡像、pod 的 request 和 limit 等等。為了最大化的提供靈活性,經過讨論我們決定在 Pool 裡增加 Patch 的字段,允許使用者自定義 Patch 内容,但是需要遵循Kubernetes 的 strategic merge patch規範,其行為與我們常用的 kubectl patch 有點類似。

pool 裡新增 patch,示例如下:

pools:
    - name: beijing
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - beijing
      replicas: 1          
      patch:
        spec:
          template:
            spec:
              containers:
              - image: nginx:1.19.3
                name: nginx           

patch 裡定義的内容,需要遵循Kubernetes 的 strategic merge patch 規範, 如果用過 kubectl patch 的同學就很容易的知道 patch 内容如何書寫,具體可以參照使用 kubectl patch 更新 Kubernetest api 對象。

接下來我們示範一下 UnitedDeployment patch 的使用。

特性示範

1. 環境準備

  • 提供一個 K8s 叢集或者 OpenYurt 叢集,叢集裡至少 2 台節點。一台節點 label 為:apps.openyurt.io/nodepool=beiing, 另一台節點 label 為:apps.openyurt.io/nodepool=hangzhou。
  • 叢集裡需要安裝 yurt-app-manager 元件。

2. 建立 UnitedDeployment 執行個體

cat <<EOF | kubectl apply -f -

apiVersion: apps.openyurt.io/v1alpha1
kind: UnitedDeployment
metadata:
  name: test
  namespace: default
spec:
  selector:
    matchLabels:
      app: test
  workloadTemplate:
    deploymentTemplate:
      metadata:
        labels:
          app: test
      spec:
        selector:
          matchLabels:
            app: test
        template:
          metadata:
            labels:
              app: test
          spec:
            containers:
            - image: nginx:1.18.0
              imagePullPolicy: Always
              name: nginx
  topology:
    pools:
    - name: beijing
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - beijing
      replicas: 1
    - name: hangzhou
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - hangzhou
      replicas: 2              
EOF           

執行個體中 workloadTemplate 使用了 Deployment 模闆, 其中 name 為 nginx 的鏡像為 nginx:1.18.0。同時拓撲裡定義了兩個 pool:beijing 和 hangzhou,replicas 數目分别為 1 和 2。

3. 檢視 UnitedDeployment 建立的 Deployment

# kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
test-beijing-rk8g8    1/1     1            1           6m4s
test-hangzhou-kfhvj   2/2     2            2           6m4s           

可以看到 yurt-app-manager 控制器建立了兩個 Deployment,分布對應 beijing 和 hangzhou 的 pool,Deployment 的命名規範以 {UnitedDeployment name}-{pool name} 為字首。檢視這兩個 Deployment 配置我們可以發現,Replicas 和 Nodeselector 繼承了對應的每個 Pool 的配置,而其他的配置則繼承了 workloadTemplate 模闆的配置。

4. 檢視對應建立的 Pod

# kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
test-beijing-rk8g8-5df688fbc5-ssffj    1/1     Running   0          3m36s
test-hangzhou-kfhvj-86d7c64899-2fqdj   1/1     Running   0          3m36s
test-hangzhou-kfhvj-86d7c64899-8vxqk   1/1     Running   0          3m36s           

可以看到建立了 1 個 name 字首為 test-beijing 的 pod,2 個 name 字首為 test-hangzhou 的 pod。

5. 使用 patch 能力做差異化配置

使用 kubectl edit ud test  指令為 beijing 的 pool 增加 patch 字段,patch 裡的内容是修改 name 為 nginx 的 container 鏡像版本為:nginx:1.19.3。

格式如下:

- name: beijing
      nodeSelectorTerm:
        matchExpressions:
        - key: apps.openyurt.io/nodepool
          operator: In
          values:
          - beijing
      replicas: 1
      patch:
        spec:
          template:
            spec:
              containers:
              - image: nginx:1.19.3
                name: nginx           

6. 檢視 Deploy 執行個體配置

重新檢視字首為 test-beijing 的 Deployment,可以看到 container 的鏡像配置已經變成了 1.19.3。

kubectl get deployments  test-beijing-rk8g8 -o yaml           

總結

通過 UnitedDeployment 的 workloadTemplate + Pools 的形式,可以将 workload 通過繼承的模闆的方式快速分發到不同的地域。在加上 Pool 的 patch 能力,在繼承模闆的配置的同時還能提供更靈活的差異化配置,基本上已經可以滿足大部分客戶在邊緣場景下特殊的需求。

如果您對于 OpenYurt 有任何疑問,歡迎使用釘釘搜尋群号(31993519)加入釘釘交流群。

繼續閱讀