ASM集成Argo Rollouts实现金丝雀发布

Argo Rollouts是Kubernetes控制器和CRD集合,ASM集成Argo Rollouts提供更强大的金丝雀部署能力。当您需要在Kubernetes环境中更新应用并降低发布风险时,可以在ASM中使用Argo Rollouts实现金丝雀发布。通过逐步分批次地向用户推送新版本并实时观测其性能表现,有效控制风险,确保服务稳定性和用户体验,从而实现在保证业务连续性的前提下顺利完成版本迭代。

前提条件

准备工作

安装Argo Rollout

安装Argo Rollout的操作步骤如下,更多信息,请参见Argo Rollouts

  1. 执行以下命令,安装Argo Rollout服务端。

    kubectl create namespace argo-rollouts
    kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
  2. 执行以下命令,安装Kubectl Argo Rollout插件。

    安装Kubectl Argo Rollout插件,方便您通过kubectl进行管理。

    brew install argoproj/tap/kubectl-argo-rollouts

启用ASM的数据面KubeAPI访问能力

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择网格实例 > 基本信息

  3. 启用数据面KubeAPI访问右侧,单击启用启用数据面KubeAPI访问

  4. 在弹出框中,单击确认

金丝雀发布

本文以创建稳定版本和金丝雀版本为例,逐步将流量切换为金丝雀版本,实现基于流量比例的发布策略。关于金丝雀发布的更多信息,请参见金丝雀发布

步骤一:创建Rollout和Service应用

  1. 创建Rollout。

    1. 使用以下内容,创建rollout.yaml文件。

      展开查看rollout.yaml

      apiVersion: argoproj.io/v1alpha1
      kind: Rollout
      metadata:
        name: istio-rollout
      spec:
        revisionHistoryLimit: 2
        selector:
          matchLabels:
            app: istio-rollout
        template:
          metadata:
            annotations:
              sidecar.istio.io/inject: "true"
            labels:
              app: istio-rollout
          spec:
            containers:
            - name: istio-rollout
              image: argoproj/rollouts-demo:blue
              ports:
              - name: http
                containerPort: 8080
                protocol: TCP
              resources:
                requests:
                  memory: 32Mi
                  cpu: 5m
        strategy:
          canary:
            canaryService: istio-rollout-canary
            stableService: istio-rollout-stable
            trafficRouting:
              istio:
                virtualService:
                  name: istio-rollout-vsvc
                  routes:
                  - primary
            steps:
            - setWeight: 10
            - pause: {}         #手工卡点。
            - setWeight: 20
            - pause: {duration: 20s}
            - setWeight: 30
            - pause: {duration: 20s}
            - setWeight: 40
            - pause: {duration: 20s}
            - setWeight: 50
            - pause: {duration: 20s}
            - setWeight: 60
            - pause: {duration: 20s}
            - setWeight: 70
            - pause: {duration: 20s}
            - setWeight: 80
            - pause: {duration: 20s}
            - setWeight: 90
            - pause: {duration: 20s}

      strategy字段定义发布策略,部分参数说明如下:

      • setWeight:设置流量的权重。

      • pause:若未配置duration,表示需要手动更新;配置duration,表示等待duration时间进行自动更新。

    2. 执行以下命令,将Rollout部署到集群。

      kubectl apply -f rollout.yaml
  2. 创建Service。

    1. 使用以下内容,创建service.yaml文件。

      apiVersion: v1
      kind: Service
      metadata:
        name: istio-rollout-canary
      spec:
        ports:
        - port: 80
          targetPort: http
          protocol: TCP
          name: http
        selector:
          app: istio-rollout
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: istio-rollout-stable
      spec:
        ports:
        - port: 80
          targetPort: http
          protocol: TCP
          name: http
        selector:
          app: istio-rollout
    2. 执行以下命令,将Service部署到集群。

      kubectl apply -f service.yaml

步骤二:创建Istio相关资源

  1. 创建虚拟服务VirtualService。

    由于启用了ASM的数据面KubeAPI访问能力,您可以通过数据面的KubeConfig访问ASM中的VirtualService、Gateway、DestinationRule等Istio资源,也可以通过ASM控制台或者ASM KubeConfig创建Istio资源。

    1. 使用以下内容,创建istio-rollout-vsvc.yaml文件。

      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: istio-rollout-vsvc
      spec:
        gateways:
          - istio-rollout-gateway
        hosts:
          - '*'
        http:
          - match:
              - uri:
                  prefix: /
            name: primary
            route:
              - destination:
                  host: istio-rollout-stable
                weight: 100
              - destination:
                  host: istio-rollout-canary
    2. 执行以下命令,部署istio-rollout-vsvc。

      kubectl apply -f istio-rollout-vsvc.yaml
  2. 创建网关规则Gateway。

    1. 使用以下内容,创建istio-rollout-gateway.yaml文件。

      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: istio-rollout-gateway
      spec:
        selector:
          istio: ingressgateway
        servers:
          - hosts:
              - '*'
            port:
              name: http
              number: 80
              protocol: HTTP
                                      
    2. 执行以下命令,部署istio-rollout-gateway。

      kubectl apply -f istio-rollout-gateway.yaml

步骤三:创建ASM网关

创建端口为80的ASM网关,作为测试访问的入口。

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 入口网关

  3. 入口网关页面,单击创建。设置网关的基本信息,然后单击创建

    部分配置项说明如下,关于配置项的更多信息,请参见创建入口网关

    配置项

    说明

    名称

    本文以ingressgateway为例。

    网关类型

    选择南北向-入口网关类型。

    端口映射

    单击添加端口,在新增端口行中,配置协议HTTP服务端口80

步骤四:查看Rollout状态

执行以下命令,查看Rollout的状态。

kubectl argo rollouts get rollout istio-rollout

预期输出:

kubectl argo rollouts get rollout istio-rollout
Name:            istio-rollout
Namespace:       default
Status:          ✔ Healthy
Strategy:        Canary
  Step:          18/18
  SetWeight:     100
  ActualWeight:  100
Images:          argoproj/rollouts-demo:blue (stable)
Replicas:
  Desired:       1
  Current:       1
  Updated:       1
  Ready:         1
  Available:     1

NAME                                       KIND        STATUS     AGE  INFO
⟳ istio-rollout                            Rollout     ✔ Healthy  52s
└──# revision:1
   └──⧉ istio-rollout-7f96d86486           ReplicaSet  ✔ Healthy  52s  stable
      └──□ istio-rollout-7f96d86486-vpqvb  Pod         ✔ Running  52s  ready:2/2

步骤五:测试Rollout初始状态

  1. 获取ASM网关的IP地址。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 入口网关

    3. 获取目标网关的服务地址

  2. 在浏览器访问http://{ASM网关IP}/

    访问效果如下所示,此界面会并发调用http://{ASM网关IP}/color,将获取到颜色信息填充到方格中。在Rollout istio-rollout中,指定的颜色为blue,并且未进行金丝雀发布,因此显示颜色为蓝色。蓝色效果

步骤六:滚动更新

本文以黄色代表金丝雀版本,将http://{ASM网关IP}/网页中的方格颜色从蓝色逐渐变为黄色,实现金丝雀发布。

  1. 更新镜像版本。

    1. 执行以下命令,更新镜像版本。

      kubectl argo rollouts set image istio-rollout "*=argoproj/istio-rollout:yellow"
    2. 查看容器的镜像版本。

      1. 登录容器服务管理控制台,在左侧导航栏单击集群

      2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 容器组

      3. 名称列下,查看目标容器的镜像版本。

        如下图所示,Yellow版本(金丝雀版本)的Pod已被创建,但Blue版本(稳定版)的Pod依然存在。

        镜像版本

  2. 在浏览器访问http://{ASM网关IP}/

    访问效果如下所示,有10%的方格被变成了黄色。黄色与蓝色效果服务网格ASM中,由于配置的虚拟服务VirtualService的权重发生了变化,Stable(蓝色)的权重从100变为90,Sanary(黄色,即金丝雀版本),权重从0变为10。虚拟服务VirtualService的权重由Rollout控制,开始创建Rollout的第一个Step的setWeight中设置了金丝雀版本的权重为10,在开始滚动时,Argo Rollout的控制器会修改Rollout中配置的VirtualService的权重。pause设置为空,表示需要人工卡点确认,才进到下一阶段。

  3. 继续金丝雀发布。

    1. 执行以下命令,继续金丝雀发布。

      kubectl argo rollouts promote istio-rollout
    2. 在浏览器访问http://{ASM网关IP}/

      访问效果如下所示,VirtualService中的权重会根据Rollout中的配置继续调整。由于步骤1中设置了pause时间,会等待一段时间后自动调整。继续发布

  4. 金丝雀发布成功。

    1. 等待一段时间后,在浏览器访问http://{ASM网关IP}/,查看页面效果。

      访问效果如下所示,所有的颜色块都变为了黄色。黄色效果

    2. 执行以下命令,查看Rollout状态。

      kubectl argo rollouts get rollout istio-rollout --watch

      预期输出:

      Name:            istio-rollout
      Namespace:       default
      Status:          ✔ Healthy
      Strategy:        Canary
        Step:          18/18
        SetWeight:     100
        ActualWeight:  100
      Images:          argoproj/rollouts-demo:yellow (stable)
      Replicas:
        Desired:       1
        Current:       1
        Updated:       1
        Ready:         1
        Available:     1
      
      NAME                                       KIND        STATUS        AGE  INFO
      ⟳ istio-rollout                            Rollout     ✔ Healthy     48m
      ├──# revision:4
      │  └──⧉ istio-rollout-5fcf5864c4           ReplicaSet  ✔ Healthy     27m  stable
      │     └──□ istio-rollout-5fcf5864c4-vw6kh  Pod         ✔ Running     26m  ready:2/2
      ├──# revision:3
      │  └──⧉ istio-rollout-897cb5b6d            ReplicaSet  • ScaledDown  27m
      └──# revision:1
         └──⧉ istio-rollout-7f96d86486           ReplicaSet  • ScaledDown  48m

      由预期输出得到,Stabel的Image更新为yellow

使用Prometheus实现自动回滚

在金丝雀过程中可以手动执行kubectl argo rollouts abort istio-rollout命令进行回滚,回退到Stable版本。您还可以使用Prometheus监控系统,对金丝雀中的应用健康状态进行监控,当监控指标异常时,自动回滚到Stable版本,并标记为降级。

  1. 在ASM中启用Prometheus。具体操作,请参见集成可观测监控Prometheus版实现网格监控集成自建Prometheus实现网格监控

  2. 配置Argo AnalysisTemplate。

    1. 使用以下YAML内容,创建istio-success-rate.yaml文件。

      配置AnalysisTemplate的address为ASM的Prometheus地址。

      apiVersion: argoproj.io/v1alpha1
      kind: AnalysisTemplate
      metadata:
        name: istio-success-rate
      spec:
        args:
        - name: service
        - name: namespace
        metrics:
        - name: success-rate
          initialDelay: 60s
          interval: 20s
          successCondition: result[0] > 0.90
          provider:
            prometheus:
              address: http://xxx.aliyuncs.com:9090/api/v1/prometheus/
              query: >+
                sum(irate(istio_requests_total{
                  reporter="source",
                  destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local",
                  response_code!~"5.*"}[40s])
                )
                /
                sum(irate(istio_requests_total{
                  reporter="source",
                  destination_service=~"{{args.service}}.{{args.namespace}}.svc.cluster.local"}[40s])
                )
    2. 执行以下命令,部署Argo AnalysisTemplate。

      kubectl apply -f istio-success-rate.yaml
  3. 为Rollout关联Analysis。

    1. 使用以下YAML内容,创建rollout.yaml文件。

      strategy中配置analysis,从第二步开启使用Analysis进行监控,自动回滚。初始Image为Yellow(黄色)。

      展开查看rollout.yaml

      apiVersion: argoproj.io/v1alpha1
      kind: Rollout
      metadata:
        name: istio-rollout
      spec:
        revisionHistoryLimit: 2
        selector:
          matchLabels:
            app: istio-rollout
        template:
          metadata:
            annotations:
              sidecar.istio.io/inject: "true"
            labels:
              app: istio-rollout
          spec:
            containers:
            - name: istio-rollout
              image: argoproj/rollouts-demo:yellow
              ports:
              - name: http
                containerPort: 8080
                protocol: TCP
              resources:
                requests:
                  memory: 32Mi
                  cpu: 5m
        strategy:
          canary:
            canaryService: istio-rollout-canary
            stableService: istio-rollout-stable
            analysis:
              startingStep: 1
              templates:
              - templateName: istio-success-rate
              args:
              - name: service
                value: canary
              - name: namespace
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
            trafficRouting:
              istio:
                virtualService:
                  name: istio-rollout-vsvc
                  routes:
                  - primary
            steps:
            - setWeight: 10
            - pause: {}         #手工卡点。
            - setWeight: 20
            - pause: {duration: 20s}
            - setWeight: 30
            - pause: {duration: 20s}
            - setWeight: 40
            - pause: {duration: 20s}
            - setWeight: 50
            - pause: {duration: 20s}
            - setWeight: 60
            - pause: {duration: 20s}
            - setWeight: 70
            - pause: {duration: 20s}
            - setWeight: 80
            - pause: {duration: 20s}
            - setWeight: 90
            - pause: {duration: 20s}
    2. 执行以下命令,更新Rollout。

      kubectl apply -f rollout.yaml
  4. 执行以下命令,更新镜像版本。

    kubectl argo rollouts set image istio-rollout "*=argoproj/rollouts-demo:orange"

    在浏览器访问http://{ASM网关IP}/,访问效果如下所示:橙色效果

  5. 人工卡点确认。

    1. 执行以下命令,继续金丝雀发布。

      执行命令后,将进入到后续的自动金丝雀状态,并且从第二步开始,会结合Prometheus监控,如果金丝雀版本错误率高于90%,则触发回滚。

      kubectl argo rollouts promote istio-rollout
    2. 执行以下命令,查看监控服务状态。

      kubectl argo rollouts get rollout istio-rollout --watch

      预期输出:监控服务状态

  6. 设置Error。

    在后续渐进式发布中,您可以手动设置Error,调整金丝雀版本的错误率。移动Error至100%后,所有的金丝雀版本(橙色)都有一个红框,表示错误。等待片刻后,将自动切换回只有黄色的版本(稳定版)。

    图 1. 金丝雀中金丝雀中

    图 2. 自动回滚到稳定版自动回滚到稳定版