1. 程式人生 > 其它 >雲邊協同下的統一應用管理: 基於 OpenYurt 和 KubeVela 的解決方案

雲邊協同下的統一應用管理: 基於 OpenYurt 和 KubeVela 的解決方案

作者:喬中沛(伊靈)

背景

隨著萬物互聯場景的逐漸普及,邊緣裝置的算力也不斷增強,如何藉助雲端計算的優勢滿足複雜多樣化的邊緣應用場景,讓雲原生技術延伸到端和邊緣成為了新的技術挑戰,“雲邊協同”正在逐漸成為新的技術焦點。本文將圍繞 CNCF 的兩大開源專案 KubeVela 和 OpenYurt,以一個實際的 Helm 應用交付的場景,為大家介紹雲邊協同的解決方案。

OpenYurt 專注於以無侵入的方式將 Kubernetes 擴充套件到邊緣計算領域。OpenYurt 依託原生 Kubernetes 的容器編排、排程能力,將邊緣算力納入到 Kubernetes 基礎設施中統一管理,提供了諸如邊緣自治、高效運維通道、邊緣單元化管理、邊緣流量拓撲、安全容器、邊緣 Serverless/FaaS、異構資源支援等能力。簡而言之,OpenYurt 以 Kubernetes 原生的方式為雲邊協同構建了統一的基礎設施。

KubeVela 孵化於 OAM 模型,專注於幫助企業構建統一的應用交付和管理能力,為業務開發者遮蔽底層基礎設施複雜度,提供靈活的擴充套件能力,並提供開箱即用的微服務容器管理、雲資源管理、版本化和灰度釋出、擴縮容、可觀測性、資源依賴編排和資料傳遞、多叢集、CI 對接、GitOps 等特性。最大化的提升開發者自助式應用管理的研發效能,提升也滿足平臺長期演進的擴充套件性訴求。

OpenYurt 與 KubeVela 結合能解決什麼問題?

如上所述,OpenYurt 滿足了邊緣節點的接入,讓使用者可以通過操作原生 Kubernetes 的方式管理邊緣節點。邊緣節點通常用來表示距離使用者更近的計算資源,比如某個就近機房中的虛擬機器或物理伺服器等,通過 OpenYurt 加入後,這些邊緣節點會轉化為 Kubernetes 中可以使用的節點(Node)。OpenYurt 用節點池(NodePool)來描述同一地域的一組邊緣節點。在滿足了基本的資源管理後,針對應用如何編排部署到一個叢集中的不同節點池,我們通常會有如下核心需求:

1. 統一配置: 如果對每一份要下發的資源做手動修改,需要很多人工介入,非常容易出錯和遺漏。我們需要統一的方式來做引數配置,不僅可以方便地做批量管理操作,還可以對接安全和審計,滿足企業風險控制與合規需求。

2. 差異部署: 部署到不同節點池的工作負載有大部分屬性相同,然而總有個性化的配置差異。關鍵在於如何設定和節點選擇相關的引數,例如 NodeSelector 可以指示 Kubernetes 排程器將工作負載排程到不同的節點池。

3. 可擴充套件性: 雲原生生態繁榮,無論是工作負載種類還是不同的運維功能都在不斷增長,為了更靈活地滿足業務需求,我們需要整體的應用架構是可擴充套件的,能夠充分享受雲原生生態的紅利。

而 KubeVela 在應用層與 OpenYurt 可以很好的互補,滿足上述三個核心需求。接下來,我們結合實際的操作流程來展示這些功能點。

將應用部署到邊緣

我們將以Ingress控制器為例,展示如何使用KubeVela 將應用程式部署到邊緣。在這種情況下,我們希望將 Nginx Ingress 控制器部署到多個節點池中,以實現通過邊緣 Ingress 訪問指定節點池提供的服務,某個 Ingress 僅能由所在節點池的 Ingress 控制器處理。

示意圖的叢集中有兩個節點池:北京和上海,他們之間的網路不互通。我們希望再其中每個節點池都部署一個 Nginx Ingress Controller,並作為各自節點池的網路流量入口。一個靠近北京的客戶端,可以通過訪問北京節點池的 Ingress Controller,訪問北京節點池內提供的服務,且不會訪問到上海節點池提供的服務。

Demo 的基礎環境

我們將使用 Kubernetes 叢集模擬邊緣場景。群集有 3 個節點,它們的角色分別是:

  • 節點 1:master 節點,雲端節點
  • 節點 2:worker 節點,邊緣節點,在節點池 beijing 中
  • 節點 3:worker 節點,邊緣節點,在節點池 shanghai 中

準備工作

1. 安裝 YurtAppManager

YurtAppManager 是 OpenYurt 的核心元件。它提供節點池 CRD 和控制器。OpenYurt 中還有其他元件,但在本教程中我們只需要 YurtAppManager.

git clone https://github.com/openyurtio/yurt-app-managercd yurt-app-manager && helm install yurt-app-manager -n kube-system ./charts/yurt-app-manager/

2.安裝KubeVela,啟用 FluxCD 外掛。

安裝 Vela 命令列工具,並在叢集中安裝 KubeVela。

curl -fsSl https://kubevela.net/script/install.sh | bash
vela install

在本案例中,為了複用社群提供的成熟的 Helm Chart,我們用 Helm 型別的元件來安裝 Nginx Ingress Controller。在微核心設計的 KubeVela 中,Helm 型別的元件是由 FluxCD 外掛提供的,下面啟用 FluxCD 外掛 [ 1]

vela addon enable fluxcd

3. 準備節點池

建立兩個節點池:北京節點池和上海節點池。在實際的邊緣場景中,以地域劃分節點池是常見的模式。不同分組的節點間往往存在網路不互通、資源不共享、資源異構、應用獨立等明顯的隔離屬性。這也是節點池概念的由來。在 OpenYurt 中,通過節點池、服務拓撲等功能幫助使用者處理上述問題。今天的例子中我們將使用節點池來描述和管理節點。

kubectl apply -f - <<EOF
apiVersion: apps.openyurt.io/v1beta1
kind: NodePool
metadata:
  name: beijing
spec:
  type: Edge
  annotations:
    apps.openyurt.io/example: test-beijing
  taints:
    - key: apps.openyurt.io/example
      value: beijing
      effect: NoSchedule
---
apiVersion: apps.openyurt.io/v1beta1
kind: NodePool
metadata:
  name: shanghai
spec:
  type: Edge
  annotations:
    apps.openyurt.io/example: test-shanghai
  taints:
    - key: apps.openyurt.io/example
      value: shanghai
      effect: NoSchedule
EOF

將邊緣節點加入到各自的節點池,邊緣節點的加入方式可以參考 OpenYurt 節點加入的方式。

kubectl label node <node1> apps.openyurt.io/desired-nodepool=beijing
kubectl label node <node2> apps.openyurt.io/desired-nodepool=shanghai
kubectl get nodepool

預期輸出

NAME       TYPE   READYNODES   NOTREADYNODES   AGE
beijing    Edge   1            0               6m2s
shanghai   Edge   1            0               6m1s

批量部署邊緣應用

在我們深入細節之前,讓我們看看 KubeVela 是如何描述部署到邊緣的應用的。通過下面這個應用,我們可以將 Nginx Ingress Controller 部署多份到各自的邊緣節點池。使用同一個應用來統一配置 Nginx Ingress 可以消除重複,降低管理負擔,也方便後續對叢集內的元件統一進行釋出運維等常見操作。

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: edge-ingress
spec:
  components:
    - name: ingress-nginx
      type: helm
      properties:
        chart: ingress-nginx
        url: https://kubernetes.github.io/ingress-nginx
        repoType: helm
        version: 4.3.0
        values:
          controller:
            service:
              type: NodePort
            admissionWebhooks:
              enabled: false
      traits:
        - type: edge-nginx
  policies:
    - name: replication
      type: replication
      properties:
        selector: [ "ingress-nginx" ]
        keys: [ "beijing","shanghai" ]
  workflow:
    steps:
      - name: deploy
        type: deploy
        properties:
          policies: ["replication"]

一個 KubeVela Application 有 3 個部分:

  1. 一個 helm 型別元件。它描述了我們想要安裝到叢集的 Helm 包版本。此外,我們給這個元件附加了一個運維特徵(trait) edge-nginx 。我們稍後將展示這個運維特徵的具體情況,現在你可以將其視為一個包含不同節點池的屬性的補丁。

  2. 一個 replication(元件分裂)策略。它描述瞭如何將元件複製到不同的節點池。該 selector 欄位用於選擇需要複製的元件。它的 keys 欄位將把一個元件轉換為具有不同 key 的兩個元件。(“beijing”和“shanghai”)

3. deploy 工作流步驟。它描述瞭如何部署應用程式。它指定 replication 策略執行復制工作的策略。

注意:

  1. 如果你希望此應用程式正常工作,請先在叢集下發在下文介紹的 edge-ingress 特性。
  2. deploy 是一個 KubeVela 內建的工作流程步驟。它還可以在多叢集場景 [2 ] 中與overridetopology 策略一起使用 。

現在,我們可以將應用下發到叢集。

vela up -f app.yaml

檢查應用狀態和 KubeVela 建立的資源。

vela status edge-ingress --tree --detail

預期輸出

CLUSTER       NAMESPACE     RESOURCE                           STATUS    APPLY_TIME          DETAIL
local  ─── default─┬─ HelmRelease/ingress-nginx-beijing  updated   2022-11-02 12:00:24 Ready: True  Status: Release reconciliation succeeded  Age: 153m
                   ├─ HelmRelease/ingress-nginx-shanghai updated   2022-11-02 12:00:24 Ready: True  Status: Release reconciliation succeeded  Age: 153m
                   └─ HelmRepository/ingress-nginx       updated   2022-11-02 12:00:24 URL: https://kubernetes.github.io/ingress-nginx  Age: 153m
                                                                                         Ready: True
                                                                                         Status: stored artifact for revision '7bce426c58aee962d479ca84e5c
                                                                                         fc6931c19c8995e31638668cb958d4a3486c2'

Vela CLI 不僅可以站在較高層次統一彙集展示應用健康狀態,當需要的時候,Vela CLI 也可以幫助你穿透應用,直達底層工作負載,並提供豐富的觀測和 Debug 能力,例如,你可以通過 vela logs 把列印應用的日誌;可以通過 vela port-forward 把部署應用的埠轉發到本地;可以通過 vela exec 命令,深入到邊緣的容器中執行 Shell 命令排查問題。

如果你想更直觀地瞭解應用去情況,KubeVela 官方還提供了 Web 控制檯外掛 VelaUX。啟用 VelaUX 外掛 [3 ] ,你可以檢視更詳細的資源拓撲。

vela addon enable velaux

訪問 VelaUX 的資源拓撲頁面。

正如你所看到的,KubeVela 建立了兩個 HelmRelease 資源,把 Nginx Ingress Controller 的 Helm Chart 交付到兩個節點池。 HelmRelease 資源被上述 FluxCD 外掛處理並在叢集兩個節點池中分別安裝了 Nginx Ingress。通過以下命令,檢查是否在北京節點池中建立了 Ingress Controller 的 Pod,上海節點池同理。

$ kubectl get node -l  apps.openyurt.io/nodepool=beijing                               
NAME                      STATUS   ROLES    AGE   VERSION
iz0xi0r2pe51he3z8pz1ekz   Ready    <none>   23h   v1.24.7+k3s1

$ kubectl get pod ingress-nginx-beijing-controller-c4c7cbf64-xthlp -oyaml|grep iz0xi0r2pe51he3z8pz1ekz
  nodeName: iz0xi0r2pe51he3z8pz1ekz

差異化部署

KubeVela 應用交付過程中如何實現了同一個元件的差異化部署?讓我們繼續深入瞭解支撐應用的 Trait(運維特徵)和 Policy(應用策略)。上文提到我們在工作流中使用了 KubeVela 內建的元件分裂(replication) Policy,給 ingress-nginx 元件附加了一個自定義的  edge-nginx Trait 。

  • 元件分裂 Policy 將元件拆為兩個元件,帶有不同的  context.replicaKey 。

  • edge-nginx Trait 使用不同的  context.replicaKey,將帶有不同配置值的 Helm Chart 交付到叢集中。讓兩個 Nginx Ingress Controller 執行在不同的節點池,監聽具有不同 ingressClass 的 Ingress 資源。具體的方式是 Patch 了 Helm Chart 的 Values 配置,修改了和節點選擇親和性以及 ingressClass 相關的欄位。

  • 在 Patch 不同欄位時,使用了不同的 Patch 策略 [4 ] (PatchStrategy),例如使用 retainKeys 策略能夠覆蓋原本的值,使用 jsonMergePatch 策略則會和原本的值合併。

"edge-nginx": {
  type: "trait"
  annotations: {}
  attributes: {
    podDisruptive: true
    appliesToWorkloads: ["helm"]
  }
}
template: {
  patch: {
    // +patchStrategy=retainKeys
    metadata: {
      name: "(context.name)-(context.replicaKey)"
    }
    // +patchStrategy=jsonMergePatch
    spec: values: {
      ingressClassByName: true
      controller: {
        ingressClassResource: {
          name:            "nginx-" + context.replicaKey
          controllerValue: "openyurt.io/" + context.replicaKey
        }
        _selector
      }
      defaultBackend: {
        _selector
      }
    }
  }
  _selector: {
    tolerations: [
      {
        key:      "apps.openyurt.io/example"
        operator: "Equal"
        value:    context.replicaKey
      },
    ]
    nodeSelector: {
      "apps.openyurt.io/nodepool": context.replicaKey
    }
  }
  parameter: null
}

讓更多型別的應用走向邊緣

可以看到,為了將 Nginx Ingress 部署到不同節點池,我們僅自定義了一個四十餘行的 Trait 並充分利用了 KubeVela 內建的能力。在雲原生生態愈加繁榮和雲邊協同的趨勢下,更多的應用都可能走向邊緣部署。當新場景中需要一個新的應用部署在邊緣節點池時,也無需煩惱,因為在 KubeVela 的幫助下,仿照該模式擴展出一個新的邊緣應用部署 Trait 也很容易,無需編寫程式碼

例如,我們希望將 K8s 社群近期的演進熱點 Gateway API [5 ] 的實現也部署到邊緣,通過 Gateway API 增強邊緣節點池暴露服務的表達能力、擴充套件性,在邊緣節點使用基於角色的網路 API 等。對於這種場景,我們也可以基於上述擴充套件方式輕鬆完成部署任務,只需要定義如下的一個新 Trait。

"gateway-nginx": {
  type: "trait"
  annotations: {}
  attributes: {
    podDisruptive: true
    appliesToWorkloads: ["helm"]
  }
}

template: {
  patch: {
    // +patchStrategy=retainKeys
    metadata: {
      name: "(context.name)-(context.replicaKey)"
    }
    // +patchStrategy=jsonMergePatch
    spec: values: {
      _selector
      fullnameOverride: "nginx-gateway-nginx-" + context.replicaKey
      gatewayClass: {
        name:           "nginx" + context.replicaKey
        controllerName: "k8s-gateway-nginx.nginx.org/nginx-gateway-nginx-controller-" + context.replicaKey
      }
    }
  }
  _selector: {
    tolerations: [
      {
        key:      "apps.openyurt.io/example"
        operator: "Equal"
        value:    context.replicaKey
      },
    ]
    nodeSelector: {
      "apps.openyurt.io/nodepool": context.replicaKey
    }
  }
  parameter: null
}

這個 Trait 和前文提到的部署 Nginx Ingress 使用的 Trait 非常相似,其中,我們也同樣對 Nginx Gateway Chart 的 Values 做了一些相似的 Patch,包括節點選擇、親和性、資源名稱。和前文 Trait 的區別是該 Trait 指定了 gatewayClass 而非 IngressClass。該案例的 Trait 和應用檔案詳見 GitHub 倉庫 [6 ] 。通過自定義這樣一個 Trait,我們就給叢集擴充套件了部署一種新應用到邊緣的能力。

如果我們無法預知未來邊緣計算的發展帶來的更多應用部署需求,至少我們可以通過這種更容易擴充套件的方式不斷適應新的場景。

KubeVela 如何解決了邊緣部署難題

回顧 KubeVela 是如何解決文章開始提出的關鍵問題的。

1. 統一配置: 我們使用一個元件來描述要部署的 ingress-nginx Helm Chart 的通用的屬性例如 Helm 倉庫、Chart 名稱、版本等統一配置。

2. 屬性差異: KubeVela 使用了一個使用者自定義的運維特徵定義,它描述下發到不同的節點池的 Helm 配置差異。該運維特徵可以重複用於部署相同的 Helm Chart。

3. 可擴充套件性: KubeVela 可以為常見的工作負載(如 Deployment/StatefulSet)或其他打包方式(如 Helm/Kustomize/...)以可程式設計的方式進行擴充套件,只需若干行的程式碼,即可將一種新應用推向邊緣場景。

這些得益於 KubeVela 在應用交付和管理領域提供的強大功能,KubeVela 除了能在單個叢集內部解決應用的定義、交付、運維和可觀測問題,還原生支援了多叢集模式的應用釋出和管理。目前適合邊緣計算場景的 Kubernetes 部署模式並無定式,無論單叢集+邊緣節點池的架構,還是多邊緣叢集架構,KubeVela 都能勝任其中的應用管理任務。

在 OpenYurt 和 KubeVela 的配合下,雲邊應用以統一方式部署,共享相同的抽象、運維、可觀測能力,避免了在不同場景中割裂的體驗。並且雲端應用和邊端應用都得以使用 KubeVela 以外掛形式不斷整合的雲原生生態的優秀實踐。未來 KubeVela 社群還將不斷豐富開箱即用的系統外掛,持續交付更好用、更易用的應用交付和管理能力。

如果想了解更多應用部署、管理的能力,可以閱讀 KubeVela 官方文件 [7 ] ,想要了解 KubeVela 社群的最新動態,歡迎來到 KubeVela 社群 [8 ] (釘釘群 23310022)參與討論!若你對 OpenYurt 感興趣,也歡迎來到 OpenYurt 社群(釘釘群 31993519)參與討論。

您也可以通過如下材料瞭解更多關於 KubeVela 以及 OAM 專案的細節:

  • 專案程式碼庫:https://github.com/kubevela/kubevela 歡迎 Star/Watch/Fork!
  • 專案官方主頁與文件:kubevela.io ,從 1.1 版本開始,已提供中文、英文文件,更多語言文件歡迎開發者進行翻譯。
  • 專案釘釘群:23310022;Slack:CNCF #kubevela Channel
  • 加入微信群:請先新增以下 maintainer 微訊號,表明進入 KubeVela 使用者群:

此處 :檢視 KubeVela 專案官網!!

相關連結

[1] FluxCD 外掛

https://kubevela.net/zh/docs/reference/addons/fluxcd

[2] 多叢集場景

https://kubevela.net/docs/case-studies/multi-cluster

[3] 啟用 VelaUX 外掛

https://kubevela.net/zh/docs/reference/addons/velaux

[4] Patch 策略

https://kubevela.net/zh/docs/platform-engineers/traits/patch-trait#patch-strategy

[5] Gateway API

https://gateway-api.sigs.k8s.io/

[6] GitHub 倉庫

https://github.com/chivalryq/yurt-vela-example/tree/main/gateway-nginx

[7] KubeVela 官方文件

https://kubevela.net/

[8] KubeVela 社群

https://github.com/kubevela/community