全部產品
Search
文件中心

Alibaba Cloud Service Mesh:基於Argo CD實現應用服務的全鏈路灰階

更新時間:Jun 30, 2024

Argo CD主要用於監聽Git倉庫中應用編排的變化,與叢集中應用真實運行狀態進行對比,自動或手動同步拉取應用編排的變更到部署叢集中。當您面臨微服務應用新版本上線的風險挑戰,期望平穩過渡、逐步驗證新功能時,可以藉助Argo CD實現應用服務的全鏈路灰階發布,以精細化流量調度和版本管理手段,確保新舊版本無縫切換,最大限度地減少對線上服務的影響,同時提升系統的穩定性和可靠性。

前提條件

背景資訊

Argo CD支援以GitOps的方式對應用服務進行方便快捷地部署與發布。開發人員提交YAML編寫的應用程式定義資源(Deployment、Service)和流量管理規則資源(VirtualService、Gateway、DestinationRule)等到Git倉庫。Argo CD監控叢集中各類資源的狀態,與Git倉庫中的資源期望編排進行比較,以Git倉庫中的內容為基準,當Git倉庫發生變更時,支援自動或手動同步資源。

Service MeshASM支援通過流量泳道將應用的相關版本(或者其他特徵)隔離成一個獨立的運行環境,以滿足應用服務的全鏈路灰階發布情境。ASM自1.20.6.27版本起,支援通過ASMSwimLaneGroup和ASMSwimLane兩種YAML編寫的自訂資源來定義流量泳道,支援使用Argo CD管理這兩種自訂資源,實現全鏈路灰階發布。更多資訊,請參見流量泳道概述

步驟一:使用Argo CD部署應用服務和流量泳道規則

  1. 建立mock應用全鏈路灰階樣本。

    1. 在Argo CD管理介面,單擊NEW APP,進行如下配置。

      image

      配置項

      說明

      Application Name

      應用程式名稱,本樣本中填寫mock

      SYNC POLICY

      應用同步策略,本樣本中填寫Automatically,即Git倉庫中有變更後,自動從Git倉庫中同步資源定義的最新版本。選中PRUNE RESOURCES,表示當資源定義在Git倉庫中不再存在時刪除、同步會刪除該資源。

      Repository URL

      作為同步來源的Git倉庫URL,本樣本中填寫樣本倉庫的URL https://github.com/AliyunContainerService/asm-labs.git。如果您希望在樣本的基礎上進行修改,可以Fork此倉庫,並填寫Fork後的Github倉庫地址。

      Revision

      作為同步來源的Git Tag或分支名,本樣本中填寫樣本倉庫的分支argocd-asm

      Path

      作為同步來源的Git倉庫中的代碼路徑,本樣本中填寫樣本所用的資源所在路徑argo-cd/swimlane

      Cluster URL

      作為同步目的地的叢集API Server地址,本樣本中填寫Argo CD部署的Kubernetes叢集API Server地址https://kubernetes.default.svc

  2. 配置完成後,單擊頁面上方的CREATE

    在Argo CD的Applications頁面,可以查看剛建立的mock應用的狀態。

    image

  3. 單擊mock應用,查看資源的同步狀態。

    image

    可以看到Git倉庫中除了定義應用的Deployment和Service資源外,還有流量管理規則資源VirtualService、Gateway,以及ASM流量泳道規則資源ASMSwimLaneGroup、ASMSwimLane。

步驟二:驗證流量泳道全鏈路灰階效果

在本樣本中,通過ASMSwimLaneGroup和ASMSwimLane資源實現了v1和v2版本應用服務環境的隔離。通過VirtualService資源定義,使ASM網關以1:1的比例向兩個版本的應用服務轉寄流量。您可以通過不斷訪問ASM網關驗證全鏈路灰階的效果。

  1. 通過ASM控制台擷取網關的公網IP。具體操作,請參見擷取ASM網關地址

  2. 執行以下命令,設定環境變數。

    xxx.xxx.xxx.xxx為上一步擷取的IP地址。

    export ASM_GATEWAY_IP=xxx.xxx.xxx.xxx
  3. 執行以下命令,不斷訪問ASM網關。

    for i in {1..100}; do curl http://${ASM_GATEWAY_IP}/mock; echo ''; sleep 1; done;

    預期輸出:

    -> mocka(version: v2, ip: 10.0.239.73)-> mockb(version: v2, ip: 10.0.239.136)-> mockc(version: v2, ip: 10.0.239.139)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v2, ip: 10.0.239.73)-> mockb(version: v2, ip: 10.0.239.136)-> mockc(version: v2, ip: 10.0.239.139)
    -> mocka(version: v2, ip: 10.0.239.73)-> mockb(version: v2, ip: 10.0.239.136)-> mockc(version: v2, ip: 10.0.239.139)
    -> mocka(version: v2, ip: 10.0.239.73)-> mockb(version: v2, ip: 10.0.239.136)-> mockc(version: v2, ip: 10.0.239.139)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    -> mocka(version: v2, ip: 10.0.239.73)-> mockb(version: v2, ip: 10.0.239.136)-> mockc(version: v2, ip: 10.0.239.139)
    -> mocka(version: v1, ip: 10.0.239.75)-> mockb(version: v1, ip: 10.0.239.138)-> mockc(version: v1, ip: 10.0.239.137)
    ...

    可以看到樣本的應用程式套件含三個服務mocka、mockb、mockc,服務調用鏈路為mocka→mockb→mockc,每個服務包含v1和v2兩個版本。請求以接近1:1的比例發送到樣本應用的v1和v2版本,同時,每個版本的服務調用鏈路彼此隔離,實現了全鏈路灰階的效果。

相關操作

發布應用服務的新版本

在本樣本中使用的樣本Git倉庫檔案結構如下:

image.png

檔案

說明

mock-v1.yaml

mock-v2.yaml

mocka、mockb、mockc三個服務的v1和v2版本部署定義。

swimlanegroup.yaml

泳道組定義。一個泳道組與一個或多個泳道相關聯,泳道組中主要定義多條流量泳道需要共用的資訊,包括services(指定應該為哪些K8s服務建立泳道隔離環境)、ingress(指定通過哪個網關規則對泳道組內的服務進行訪問)等。

swimlanes.yaml

泳道定義,其中定義了v1和v2兩個ASMSwimLane資源。泳道主要通過labelSelector定義區分服務不同版本的標籤選取器。

mock-route.yaml

定義了作用於ASM入口網關的網關規則(Gateway)和虛擬服務(VirtualService)資源。這些流量管理規則資源負責控制ASM網關如何向泳道中的服務轉寄請求。

要發布應用服務的新版本,您可以Fork樣本Git倉庫https://github.com/AliyunContainerService/asm-labs.gitargocd-asm分支,並修改argo-cd/swimlane路徑下的上述YAML資源,修改後向遠程Git倉庫進行提交。推送提交後,Argo CD將會自動同步您在Git倉庫中的變更(步驟一中的Repository URL要對應填寫Fork後的Git倉庫地址)。

以mocka、mockb、mockc三個服務發布新的v3版本為例,您需要對Git倉庫中的YAML資源進行以下修改:

  1. 增加argo-cd/swimlane/mock-v3.yaml檔案。

    YAML檔案提供mocka、mockb、mockc三個服務的v3版本的部署定義。

    展開查看YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: mocka-v3
     labels:
     app: mocka
     version: v3
    spec:
     replicas: 1
     selector:
     matchLabels:
     app: mocka
     version: v3
     ASM_TRAFFIC_TAG: v3
     template:
     metadata:
     labels:
     app: mocka
     version: v3
     ASM_TRAFFIC_TAG: v3
     spec:
     containers:
     - name: default
     image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0
     imagePullPolicy: IfNotPresent
     env:
     - name: version
     value: v3
     - name: app
     value: mocka
     - name: upstream_url
     value: "http://mockb:8000/"
     ports:
     - containerPort: 8000
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: mockb-v3
     labels:
     app: mockb
     version: v3
    spec:
     replicas: 1
     selector:
     matchLabels:
     app: mockb
     version: v3
     ASM_TRAFFIC_TAG: v3
     template:
     metadata:
     labels:
     app: mockb
     version: v3
     ASM_TRAFFIC_TAG: v3
     spec:
     containers:
     - name: default
     image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0
     imagePullPolicy: IfNotPresent
     env:
     - name: version
     value: v3
     - name: app
     value: mockb
     - name: upstream_url
     value: "http://mockc:8000/"
     ports:
     - containerPort: 8000
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: mockc-v3
     labels:
     app: mockc
     version: v3
    spec:
     replicas: 1
     selector:
     matchLabels:
     app: mockc
     version: v3
     ASM_TRAFFIC_TAG: v3
     template:
     metadata:
     labels:
     app: mockc
     version: v3
     ASM_TRAFFIC_TAG: v3
     spec:
     containers:
     - name: default
     image: registry.cn-beijing.aliyuncs.com/aliacs-app-catalog/go-http-sample:1.0
     imagePullPolicy: IfNotPresent
     env:
     - name: version
     value: v3
     - name: app
     value: mockc
     ports:
     - containerPort: 8000
  2. 修改argo-cd/swimlane/swimlanes.yaml檔案為以下內容。

    本樣本在檔案中增加了名為v3的流量泳道(ASMSwimLane)資源。該資源關聯名為mock的泳道組(ASMSwimLaneGroup)資源,並指定帶有version:v3標籤的Pod為v3版本的服務。

    展開查看YAML

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMSwimLane
    metadata:
     labels:
     swimlane-group: mock
     name: v1
    spec:
     labelSelector:
     version: v1
    ---
    apiVersion: istio.alibabacloud.com/v1
    kind: ASMSwimLane
    metadata:
     labels:
     swimlane-group: mock
     name: v2
    spec:
     labelSelector:
     version: v2
    ---
    apiVersion: istio.alibabacloud.com/v1
    kind: ASMSwimLane
    metadata:
     labels:
     swimlane-group: mock
     name: v3
    spec:
     labelSelector:
     version: v3
  3. 修改argo-cd/swimlane/mock-route.yaml檔案為以下內容。

    本樣本修改了檔案中名為mock的虛擬服務(VirtualService),在路由目標中增加v3版本的mocka服務,其中subset欄位對應流量泳道(ASMSwimLane)的名稱。同時,修改虛擬服務中的weight欄位,將v1、v2、v3三個版本的流量灰階比例調整為6:3:1。

    展開查看YAML

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
     name: ingressgateway
     namespace: istio-system
    spec:
     selector:
     istio: ingressgateway
     servers:
     - port:
     number: 80
     name: http
     protocol: HTTP
     hosts:
     - '*'
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
     name: mock
     namespace: istio-system
    spec:
     gateways:
     - ingressgateway
     hosts:
     - '*'
     http:
     - match:
     - uri:
     exact: /mock
     route:
     - destination:
     host: mocka.default.svc.cluster.local
     subset: v1
     weight: 60
     - destination:
     host: mocka.default.svc.cluster.local
     subset: v2
     weight: 30
     - destination:
     host: mocka.default.svc.cluster.local
     subset: v3
     weight: 10