全部產品
Search
文件中心

Microservices Engine:結合Kruise Rollouts實現基於MSE的全鏈路灰階

更新時間:Jul 30, 2025

作為Kubernetes應用部署工具,Kruise Rollouts提供金絲雀發布、藍綠髮布等多種灰階發布策略,並通過與MSE微服務治理的結合,實現對新版本應用在服務調用鏈路上的平滑灰階升級,確保新版本的穩定性。

全鏈路灰階介紹

在微服務架構情境下,傳統的灰階發布模式往往不能滿足交付的複雜需求,全鏈路灰階發布的情境也就應運而生,此時每個微服務都會有灰階環境或分組來接受灰階流量。開發人員希望進入上遊灰階環境的流量也能進入下遊灰階環境中,確保一個請求始終在灰階環境中傳遞,從而形成流量泳道。在泳道內的流量鏈路中,即使這個調用鏈路上有一些微服務應用不存在灰階環境,那麼這些微服務應用在請求下遊的時候依然能夠重新回到灰階環境中。此時可以根據服務的實際情況,控制多個服務同時進行發布變更,從而保證整個系統的穩定性,效果如下圖所示:

image.png

Kruise Rollouts介紹

Kruise Rollouts是OpenKruise社區開源的漸進式交付架構。Kruise Rollouts支援配合流量和執行個體灰階的灰階發布、藍綠髮布和A/B Testing發布。基於Prometheus Metrics指標,Kruise Rollouts還可以實現發布過程的自動化分批與暫停,並提供旁路的無感對接,相容已有的多種工作負載(Deployment、CloneSet、StatefulSet),更多資訊,請參見Kruise Rollouts

Kruise Rollouts是一種旁路式的工作機制。您只需配置一份Rollouts資源並將其下發到K8s叢集中,後續的業務發布和升級均無需額外操作,並且可以與Helm和PaaS平台低成本無縫對接。使用Kruise Rollouts實現灰階發布架構圖如下:image.png

前提條件

步驟一:準備工作

  1. 安裝Kruise Rollouts組件。

    1. 登入Container Service管理主控台,在左側導覽列選擇叢集列表

    2. 叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,單擊組件管理

    3. 組件管理頁面,單擊應用管理頁簽。

    4. ack-kruise卡片右下方,單擊安裝

    5. 在彈出的對話方塊中,單擊確認

  2. 安裝MSE Ingress組件。建立MseIngressConfig和IngressClass,具體操作,請參見通過MSE Ingress訪問Container Service

  3. 為應用開啟微服務治理。具體操作,請參見ACK和ACS微服務應用接入MSE治理中心(Java版)

步驟二:部署Demo應用

  1. 部署業務應用(Deployment、Service和Ingress)。

    1. 使用如下內容,建立mse-demo.yaml檔案。

      展開查看mse-demo.yaml檔案

      # a service
      apiVersion: v1
      kind: Service
      metadata:
        name: spring-cloud-a
      spec:
        ports:
          - name: http
            port: 20001
            protocol: TCP
            targetPort: 20001
        selector:
          app: spring-cloud-a
      # a application
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-a
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: spring-cloud-a
        template:
          metadata:
            annotations:
              msePilotCreateAppName: spring-cloud-a
            labels:
              app: spring-cloud-a
          spec:
            containers:
              - env:
                  - name: JAVA_HOME
                    value: /usr/lib/jvm/java-1.8-openjdk/jre
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.0
                imagePullPolicy: Always
                name: spring-cloud-a
                ports:
                  - containerPort: 20001
      # b application
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-b
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: spring-cloud-b
        template:
          metadata:
            annotations:
              msePilotCreateAppName: spring-cloud-b
            labels:
              app: spring-cloud-b
          spec:
            containers:
              - env:
                  - name: JAVA_HOME
                    value: /usr/lib/jvm/java-1.8-openjdk/jre
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-b:mse-2.0.0
                imagePullPolicy: Always
                name: spring-cloud-b
      # c application
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-c
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: spring-cloud-c
        template:
          metadata:
            annotations:
              msePilotCreateAppName: spring-cloud-c
            labels:
              app: spring-cloud-c
          spec:
            containers:
              - env:
                  - name: JAVA_HOME
                    value: /usr/lib/jvm/java-1.8-openjdk/jre
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0
                imagePullPolicy: Always
                name: spring-cloud-c
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nacos-server
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nacos-server
        template:
          metadata:
            labels:
              app: nacos-server
          spec:
            containers:
            - env:
              - name: MODE
                value: standalone
              image: registry.cn-hangzhou.aliyuncs.com/mse-governance-demo/nacos-server:v2.1.2
              imagePullPolicy: Always
              name: nacos-server
            dnsPolicy: ClusterFirst
            restartPolicy: Always
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: nacos-server
      spec:
        type: ClusterIP
        ports:
          - name: nacos-server-8848-8848
            port: 8848
            protocol: TCP
            targetPort: 8848
          - name: nacos-server-9848-9848
            port: 9848
            protocol: TCP
            targetPort: 9848
        selector:
          app: nacos-server
      ---
      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: demo-mysql
        name: demo-mysql
      spec:
        ports:
          - port: 3306
            targetPort: 3306
        selector:
          app: demo-mysql
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: demo-mysql
      spec:
        selector:
          matchLabels:
            app: demo-mysql
        replicas: 1
        strategy:
          type: Recreate
        template:
          metadata:
            labels:
              app: demo-mysql
          spec:
            containers:
              - args:
                  - --character-set-server=utf8mb4
                  - --collation-server=utf8mb4_unicode_ci
                env:
                  - name: MYSQL_ROOT_PASSWORD
                    value: root
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo-mysql:3.0.1
                name: demo-mysql
                ports:
                  - containerPort: 3306
    2. 執行如下命令,部署業務應用。

      kubectl apply -f mse-demo.yaml
    3. 使用如下內容,建立mse-ingress.yaml檔案。

      展開查看mse-ingress.yaml檔案

      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        annotations:
          mse.ingress.kubernetes.io/service-subset: ""
        name: spring-cloud-a
      spec:
        ingressClassName: mse
        rules:
          - http:
              paths:
                - backend:
                    service:
                      name: spring-cloud-a
                      port:
                        number: 20001
                  path: /
                  pathType: Prefix
    4. 執行如下命令,建立Ingress規則。

      kubectl apply -f mse-ingress.yaml
    5. 執行如下命令,擷取外部IP。

      kubectl get ingress

      預期輸出如下所示:

      NAME         CLASS    HOSTS   ADDRESS        PORTS   AGE
      spring-cloud-a   <none>   *       EXTERNAL_IP     80     12m
    6. 執行如下命令,查看路由訪問情況。替換以下<EXTERNAL_IP>為您上一步擷取的外部IP。

      curl http://<EXTERNAL_IP>/a

      預期輸出如下所示:

      A[192.168.0.26][config=base] -> B[192.168.100.45] -> C[192.168.0.34]

步驟三:通過Kruise Rollouts實現自動化的全鏈路灰階發布

  1. 定義Kruise Rollouts的灰階發布規則。

    說明

    以下Rollout資源將定義灰階發布規則,發布分為三批:

    1. A/B Testing發布,具有header[User-Agent]=xiaoming的流量將匯入到新版本,其它則為老版本。

    2. 按照流量比例進行灰階,此批次將灰階50%的執行個體及流量。

    3. 將灰階完成所有的執行個體。

    1. 使用如下內容,建立rollout.yaml檔案。

      展開查看rollout.yaml檔案

      # 用於圈定全鏈路的應用
      # a rollout configuration
      apiVersion: rollouts.kruise.io/v1alpha1
      kind: Rollout
      metadata:
        # 其它微服務應用類似配置,例如:rollout-b, rollout-c
        name: rollout-a
        annotations:
          rollouts.kruise.io/trafficrouting: mse-traffic
      spec:
        objectRef:
          workloadRef:
            apiVersion: apps/v1
            kind: Deployment
            name: spring-cloud-a
        strategy:
          canary:
            steps:
            - pause: {}
              replicas: 1
            patchPodTemplateMetadata:
              labels:
                alicloud.service.tag: gray
                opensergo.io/canary-gray: gray
      ---
      # b rollout configuration
      apiVersion: rollouts.kruise.io/v1alpha1
      kind: Rollout
      metadata:
        name: rollout-b
        annotations:
          rollouts.kruise.io/trafficrouting: mse-traffic
      spec:
        objectRef:
          workloadRef:
            apiVersion: apps/v1
            kind: Deployment
            name: spring-cloud-b
        strategy:
          canary:
            steps:
              - pause: {}
                replicas: 1
            patchPodTemplateMetadata:
              labels:
                alicloud.service.tag: gray
                opensergo.io/canary-gray: gray
      ---
      # c rollout configuration
      apiVersion: rollouts.kruise.io/v1alpha1
      kind: Rollout
      metadata:
        name: rollout-c
        annotations:
          rollouts.kruise.io/trafficrouting: mse-traffic
      spec:
        objectRef:
          workloadRef:
            apiVersion: apps/v1
            kind: Deployment
            name: spring-cloud-c
        strategy:
          canary:
            steps:
              - pause: {}
                replicas: 1
            patchPodTemplateMetadata:
              labels:
                alicloud.service.tag: gray
                opensergo.io/canary-gray: gray
      ---
      # 全鏈路泳道配置
      apiVersion: rollouts.kruise.io/v1alpha1
      kind: TrafficRouting
      metadata:
        name: mse-traffic
      spec:
        objectRef:
        - service: spring-cloud-a
          ingress:
            classType: mse
            name: spring-cloud-a
        strategy:
          matches:
          # A/B Testing發布,基於header的流量灰階方式。
          - headers:
            - type: Exact
              name: User-Agent
              value: xiaoming
              # 此批次灰階的流量比例50%。
          #weight: 30 , 灰階30%流量
          requestHeaderModifier:
            set:
            - name: x-mse-tag
              value: gray

    2. 執行如下命令,將該Rollout資源下發到K8s叢集。

      kubectl apply -f rollout.yaml
    3. 執行如下命令,查看Rollout資源的狀態。

      kubectl get rollout

      預期輸出STATUS=Healthy,表明Rollout資源正常工作。

  2. 升級應用版本。

    Kruise Rollouts是一個常態化的配置,將其下發到叢集後,後續業務版本發布只需調整Deployment配置,無需再對Kruise Rollouts進行額外操作。例如,業務將spring-cloud-a服務跟spring-cloud-c鏡像版本升級到mse-2.0.1,然後通過執行kubectl apply -f mse-demo.yaml命令將Deployment部署到叢集。將Deployment配置下發到K8s叢集時,除kubectl方式外,也可以使用Helm或Vela等方式。

    • 修改mse-demo.yaml檔案,將spring-cloud-a服務跟spring-cloud-c鏡像版本升級到mse-2.0.1。

      展開查看YAML檔案

      # a application
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-a
        ...
            containers:
              - env:
                  - name: JAVA_HOME
                    value: /usr/lib/jvm/java-1.8-openjdk/jre
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.1
                imagePullPolicy: Always
                name: spring-cloud-a
                ports:
                  - containerPort: 20001
      ...
      # c application
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: spring-cloud-c
      spec:
        ...
                image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.1
    • 執行如下命令,查看Rollout資源的狀態。

      kubectl get rollouts rollout-a -n default
      kubectl get rollouts rollout-c -n default

      預期輸出:

      NAME            STATUS        CANARY_STEP   CANARY_STATE   MESSAGE                                                                         AGE
      rollouts-a   Progressing   1             StepPaused     Rollout is in step(1/1), and you need manually confirm to enter the next step   41m
      rollouts-c   Progressing   1             StepPaused     Rollout is in step(1/1), and you need manually confirm to enter the next step   41m

      通過預期輸出的STATUSCANARY,可以觀察Rollout的過程以及步驟:

      • 若預期輸出STATUS=Progressing:表明已經在灰階發布過程中。

      • 若預期輸出CANARY_STATE=StepPaused:表明當前批次已經完成,是否需要繼續,可通過人工確認。

  3. 確認灰階發布的新版本發布正常後,繼續後續發布。

    前面的步驟僅發布部分執行個體以及部分的金絲雀流量灰階,通過一些業務日誌或監控確認新版本發布正常後,可通過rollout.rollouts.kruise.io/<rollouts-demo> approved命令繼續後續發布,其中<rollouts-demo>表示Rollout資源的名稱。

  4. (可選)若新版本服務異常,可進行業務復原。

    如果在Rollout過程中,發現新版本服務異常,可以通過Deployment配置恢複到之前版本。然後通過kubectl apply -f mse-demo.yaml命令進行部署,無需對Rollout資源做任何改動。

在微服務治理架構中,全鏈路灰階功能提供流量分流,極大地方便了測試和發布時的快速驗證,結合Kruise Rollouts能夠大幅度協助DevOps提升線上穩定性。