基于ACK One Gitops使用Argo Rollouts实现金丝雀发布

ACK One整合了ArgoCD GitOps的能力,同时结合渐进式发布组件Argo Rollouts,通过Git Commit实现全自动的金丝雀发布。本文介绍如何通过ACK One GitOps结合Argo Rollouts组件快速构建应用的金丝雀发布能力。

前提条件

相关概念

展开查看GitOps相关概念

GitOps

GitOps是使用Git仓库来管理应用的部署模板,将Git仓库作为Kubernetes集群中部署应用的唯一来源,实现应用的持续部署。关于GitOps的更多介绍,请参见GitOps概述

image

展开查看Argo Rollouts相关概念

Argo Rollouts

Argo Rollouts是基于Kubernetes的一个标准扩展组件,可以提供高级的部署能力,例如蓝绿发布、金丝雀发布,以及Kubernetes渐进交付功能。关于Argo Rollouts的更多介绍,请参见Argo Rollouts官方文档

image

展开查看金丝雀(Canary)发布相关概念

金丝雀(Canary)发布

金丝雀(Canary)发布是一种发布策略,即灰度发布。金丝雀发布指的是在生产环境中分阶段逐步更新后端应用的版本(版本需要具备流量控制能力,例如可以通过Ingress控制器),在小范围内验证符合预期后,再推广至整个生产环境。

金丝雀发布的优势

金丝雀发布可以使用真实环境测试新版本,当新版本存在问题时,新版本最多只影响部分用户,且支持安全快速的回滚策略,即将路由到新版本上的流量切换到其他老版本上。

金丝雀发布流程

image

注意事项

  • 如果您选择GitHub仓库,则不推荐使用中国内地地域。如需在中国内地地域运行,您可以选择适合的Git服务提供商。

  • 本文舰队管理的Fleet实例和关联的ACK集群的地域均以中国香港地域为例介绍。

步骤一:在ACK集群中部署Argo Rollouts组件

执行以下命令,在ACK集群中部署Argo Rollouts组件。关于安装Argo Rollouts组件的更多信息,请参见Argo Rollouts官方文档

kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

步骤二:在ACK集群中部署ack-arms-prometheus组件

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

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > 组件管理

  3. 组件管理页面,单击日志与监控页签,找到ack-arms-prometheus组件。

    • 若在卡片右上方显示已安装,说明在创建集群时已安装ack-arms-prometheus组件,您无需处理。

    • 若在卡片右上方未显示信息,您需要单击卡片右下方的安装,在ACK集群中安装该组件。

步骤三:使用ACK One GitOps发布应用

通过GitOps发布应用支持以下两种方式。

  • 通过ArgoCD CLI的方式发布应用。下文以此方式为例,介绍如何使用GitOps发布应用。

  • 通过GitOps控制台发布应用。具体操作,请参见GitOps快速入门

  1. 执行以下命令,添加Git Repo。

    argocd repo add https://github.com/AliyunContainerService/gitops-demo.git --name gitops-demo

    预期输出:

    Repository 'https://github.com/AliyunContainerService/gitops-demo.git' added
  2. 执行以下命令,查看已添加的Git Repo列表。

    argocd repo list

    预期输出:

    TYPE  NAME         REPO                                                       INSECURE  OCI    LFS    CREDS  STATUS      MESSAGE  PROJECT
    git   gitops-demo  https://github.com/AliyunContainerService/gitops-demo.git  false     false  false  false  Successful
  3. 执行以下命令,查看Cluster列表。

    argocd cluster list

    预期输出:

    SERVER                          NAME                                                                 VERSION  STATUS      MESSAGE                                                  PROJECT
    https://192.168.XX.XX:6443      c76073b011afb4de2a8****-ack-gitops-demo-192-10-110-0-0-16  1.26+    Successful
    https://kubernetes.default.svc  in-cluster                                                                    Unknown     Cluster has no applications and is not being monitored.
  4. 执行以下命令,通过Application方式创建应用。

    argocd app create rollouts-demo --repo https://github.com/AliyunContainerService/gitops-demo.git --project default --sync-policy automated --revision rollouts --path  . --dest-namespace default --dest-server https://192.168.XX.XX:6443 
  5. 执行以下列表,查看应用列表。

    argocd app list

    预期输出:

    NAME           CLUSTER                     NAMESPACE  PROJECT  STATUS  HEALTH   SYNCPOLICY  CONDITIONS  REPO                                            PATH  TARGET
    rollouts-demo  https://192.168.XX.XX:6443  default    default  Synced  Healthy  Auto        <none>      https://github.com/AliyunContainerService/gitops-demo.git  .     rollouts
  6. 执行以下命令,查看Rollouts运行状态。

    kubectl argo rollouts get rollout rollouts-demo --watch

    预期输出:

    1234..png

步骤四:开始金丝雀发布

Argo Rollouts金丝雀发布的过程中,您可以通过以下两种方式确认新版本的应用是否正常,进而决定是否进一步增加新版本的流量权重,直到全部流量都指向新版本。一种是人工确认;另一种是通过ARMS Prometheus监控采集到的新版本应用的业务指标状态,决定是否增加新版本流量权重。

人工确认方式

  1. 在rollout.yaml文件中,修改如下内容,然后保存并提交。

    apiVersion: argoproj.io/v1alpha1
    kind: Rollout
    metadata:
      name: rollouts-demo
    spec:
      replicas: 4
      strategy:
        canary:            # 无需添加analysis指标采集部分。
          canaryService: rollouts-demo-canary
          stableService: rollouts-demo-stable
          trafficRouting:
            nginx:
              stableIngress: rollouts-demo-stable
          steps:
            - setWeight: 20
            - pause: {}          # 该处为暂停,需要介入处理。
            - setWeight: 40
            - pause: {duration: 5m}
            - setWeight: 60
            - pause: {duration: 5m}
            - setWeight: 80
            - pause: {duration: 5m}
      revisionHistoryLimit: 2
      selector:
        matchLabels:
          app: rollouts-demo
      template:
        metadata:
          labels:
            app: rollouts-demo
        spec:
          containers:
          - name: rollouts-demo
            image: argoproj/rollouts-demo:yellow   # 修改镜像Tag。
            ports:
            - name: http
              containerPort: 8080
              protocol: TCP
            resources:
              requests:
                memory: 32Mi
                cpu: 5m        
  2. 执行以下命令,查看Rollouts运行状态。

    kubectl argo rollouts get rollout rollouts-demo --watch

    预期输出:

    123..png

    在rollout.yaml文件中,在第一个puase的位置,由于未设置暂停时间,因此金丝雀发布会一直暂停在该处,直到有resumed或promoted动作为止。

  3. 恢复金丝雀发布。

    1. 在rollout.yaml文件中,修改如下内容,然后保存并提交。

            steps:
              - setWeight: 20
              - pause: {duration: 10s}   # 此处增加一个较短的duration,使其快速进入下一步。
    2. 再次执行以下命令,恢复金丝雀发布。

      kubectl argo rollouts get rollout rollouts-demo --watch

      预期输出:3..png

    金丝雀发布完成后,效果如下图所示。

    4..png

通过ARMS Prometheus监控指标自动确认

  1. 在rollout.yaml文件中,修改如下内容,然后保存并提交。

      strategy:
        canary:
          analysis:        # 指标分析配置。
            templates:     # 指标分析模板。
            - templateName: success-rate
            startingStep: 2 #delay starting analysis run until setWeight: 40%
            args:
              - name: service-name
                value: rollouts-demo-stable
          canaryService: rollouts-demo-canary
          stableService: rollouts-demo-stable
          trafficRouting:
            nginx:
              stableIngress: rollouts-demo-stable
          steps:
            - setWeight: 20
            - pause: {duration: 5m}
            - setWeight: 40
            - pause: {duration: 5m}
            - setWeight: 60
            - pause: {duration: 5m}
            - setWeight: 80
            - pause: {duration: 5m}
      revisionHistoryLimit: 2
      selector:
        matchLabels:
          app: rollouts-demo
      template:
        metadata:
          labels:
            app: rollouts-demo
        spec:
          containers:
          - name: rollouts-demo
            image: argoproj/rollouts-demo:blue  # 设置新的镜像Tag。        
  2. 获取ARMS Prometheus的服务地址address。

    该服务地址为标准的Kubernetes Service地址格式{ServiceName}.{Namespace}.svc.{ClusterDomain}:{ServicePort},例如,本文ARMS Prometheus的Service部署在arms-prom命名空间下,暴露的服务名称为arms-prom-server,并且集群默认的ClusterDomain为cluster.local,服务端口为9090,所以ARMS Prometheus的服务地址为http://arms-prom-server.arms-prom.svc.cluster.local:9090

  3. 在analysis.yaml文件中,增加如下关于ARMS Prometheus业务指标的配置内容。

    以下ARMS Prometheus的服务地址address为上一步获取的服务地址adress。例如下方示例代码中金丝雀发布成功的条件为当在采集周期内请求灰度应用成功的比例达到95%时,金丝雀发布将会自动进入下一流程。关于更多采集指标的配置,请参见指标采集官方文档

    apiVersion: argoproj.io/v1alpha1
    kind: AnalysisTemplate
    metadata:
      name: success-rate
    spec:
      args:
      - name: service-name
      metrics:
      - name: success-rate
        interval: 5m
        successCondition: result[0] >= 0.95   # 指标判断条件。
        failureLimit: 10
        provider:
          prometheus:   # 指标采集服务地址。
            address: http://arms-prom-server.arms-prom.svc.cluster.local:9090  # ARMS Prometheus服务地址,为上一步获取的服务地址address。
            query: |
              sum(
                irate(nginx_ingress_controller_requests{status=~"(1|2).*", canary!="" ,service="{{args.service-name}}"}[5m]))
                /
                sum(irate(nginx_ingress_controller_requests{canary!="",service="{{args.service-name}}"}[5m])
              )
  4. 确保Arms Prometheus有持续的指标数据。

    1. 执行以下命令,持续访问应用的Ingress入口,获取ACK集群的Ingress信息。

      kubectl get ingress

      预期输出:

      NAME                                        CLASS   HOSTS                 ADDRESS         PORTS   AGE
      rollouts-demo-rollouts-demo-stable-canary   nginx   rollouts-demo.local   8.217.XX.XX   80      9h
      rollouts-demo-stable                        nginx   rollouts-demo.local   8.217.XX.XX   80      9h
    2. 修改本地Hosts文件,新增如下配置。

      8.217.XX.XX  rollouts-demo.local
    3. 在新的窗口中,执行以下命令,持续为应用增加访问流量。

       while true; do curl -s "http://rollouts-demo.local/" | grep -o "<title>.*</title>" ;sleep 200ms;done
  5. 执行以下命令,查看Rollouts运行状态。

    kubectl argo rollouts get rollout rollouts-demo --watch

    预期输出:

    自动..png

  6. 查看ARMS Prometheus监控指标。

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

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择运维管理 > Prometheus 监控

    3. Prometheus 监控页面,单击网络监控页签,然后单击集群Ingress流量监控

      查看ARMS监控指标如下图所示。

      arms..png

    金丝雀发布完成后,效果如下图所示。

    自动发布完成..png

(可选)步骤五:金丝雀发布回滚

在金丝雀发布过程中,如果您发现应用异常,可以通过修改rollout.yaml文件进行回滚。具体操作如下。

在rollout.yaml文件中,修改如下内容,然后保存并提交。

    spec:
      containers:
      - name: rollouts-demo
        image: argoproj/rollouts-demo:yellow  # 仅需把该处调整为稳定版本的Tag,保存并提交Git仓库。

预期输出:

回滚..png

相关文档