Argo Rollouts是Kubernetes控制器和CRD集合,阿里云服务网格ASM集成Argo Rollouts,提供更强大的金丝雀部署能力。本文介绍如何通过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文件。
      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。具体操作,请参见集成ARMS 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(黄色)。
      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. 自动回滚到稳定版
    自动回滚到稳定版