Kruise Rollout是基于Kubernetes的一个标准扩展组件,可以配合原生工作负载(Deployment、StatefulSet),实现灰度发布、A/B Testing发布和蓝绿发布等功能。本文介绍如何使用Kruise Rollout实现灰度发布。

前提条件

已创建Kubernetes集群,且集群版本不低于1.16。具体操作,请参见创建Kubernetes托管版集群

背景信息

Kruise Rollout是OpenKruise社区开源的渐进式交付框架。Kruise Rollout支持配合流量和实例灰度的灰度发布、蓝绿发布、A/B Testing发布,基于Prometheus Metrics指标可以实现发布过程的自动化分批与暂停,并提供旁路的无感对接、兼容已有的多种工作负载(Deployment、CloneSet、StatefulSet),更多信息,请参见Kruise Rollout
使用Kruise Rollout实现灰度发布架构如下图所示。gray

步骤一:安装Kruise Rollout组件

  1. 登录容器服务管理控制台,在左侧导航栏中选择集群
  2. 集群列表页面中,单击目标集群名称,然后在左侧导航栏中,选择运维管理 > 组件管理
  3. 组件管理页面,单击应用管理页签。在ack-kruise卡片右下方,单击安装
  4. 在弹出的对话框中,单击确定

步骤二:基于Kruise Rollout实现灰度发布

Kruise Rollout是一种旁路式的工作机制,您只要配置一份Rollout资源下发到K8s集群中,后续的业务发布、升级都不需要额外的操作,并且可以与Helm、PaaS平台低成本地无缝对接。

本文示例的业务配置基于Deployment部署一个echoserver服务,并通过Nginx Ingress对外暴露服务。

  1. 部署业务应用(Deployment、Service、Ingress)。
    1. 使用以下内容,创建echoserver.yaml文件。
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echoserver
        labels:
          app: echoserver
      spec:
        replicas: 5
        selector:
          matchLabels:
            app: echoserver
        template:
          metadata:
            labels:
              app: echoserver
          spec:
            containers:
            - name: echoserver
               # Mac M1选择的镜像要支持ARM64系统,比如:e2eteam/echoserver:2.2-linux-arm64。
              image: cilium/echoserver:1.10.2
              imagePullPolicy: IfNotPresent
              ports:
              - containerPort: 8080
              env:
              - name: PORT
                value: '8080'
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: echoserver
        labels:
          app: echoserver
      spec:
        ports:
        - port: 80
          targetPort: 8080
          protocol: TCP
          name: http
        selector:
          app: echoserver
      ---
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: echoserver
        annotations:
          kubernetes.io/ingress.class: nginx
      spec:
        rules:
        - host: www.example.com
          http:
            paths:
            - backend:
                service:
                  name: echoserver
                  port:
                    number: 80
              path: /apis/echo
              pathType: Exact
    2. 执行以下命令,部署业务应用。
      kubectl apply -f echoserver.yaml
    3. 执行以下命令,获取外部IP。
      kubectl get ingress
    4. 执行以下命令,查看路由访问情况。
      替换<EXTERNAL_IP>为您上一步获取的外部IP。
      curl -H "Host: www.example.com"  http://<EXTERNAL_IP>/apis/echo

      预期输出:

      Hostname: echoserver-84845cb968-27rvv
      
      Pod Information:
          node name:    version2
          pod name:    echoserver-84845cb968-27rvv
          pod namespace:    default
          pod IP:    10.244.1.99
      
      Server values:
          server_version=nginx: 1.13.3 - lua: 10008
  2. 定义Kruise Rollout发布规则。
    1. 使用以下内容,创建rollout.yaml文件。
      apiVersion: rollouts.kruise.io/v1alpha1
      kind: Rollout
      metadata:
        name: rollouts-demo
        # 创建的Rollout规则需要和相应的工作负载(Deployment和CloneSet)在同一命名空间下。
        # default命名空间。
      spec:
        objectRef:
          # 支持滚动更新的工作负载目前支持Deployment和CloneSet。
          workloadRef:
            apiVersion: apps/v1
            kind: Deployment
            name: echoserver
        strategy:
          canary:
            steps:
            # 导入5%流量到新版本。
            - weight: 5
            # 手动确认剩余Pods的发布。
              pause: {}
            # 可选,发布Pod副本的第一步。如果未设置,默认配置使用weight的值,如上为5%。
              replicas: 20%
            trafficRoutings:
              # echoserver service name
            - service: echoserver
              # nginx ingress
              type: nginx
              # echoserver ingress name
              ingress:
                name: echoserver

      Rollout是Kruise Rollout扩展的渐进式发布资源,以上定义的规则描述了灰度发布的规则:第一批发布20%*5=1个Pod,发布成功后导入5%流量到新版本,人工确认此次发布正常后,再进行后续发布。

    2. 执行以下命令,将该Rollout资源下发到K8s集群。
      kubectl apply -f rollout.yaml
    3. 执行以下命令,查看Rollout资源状态。
      kubectl get rollout -n default rollouts-demo

      预期输出:

      NAME            STATUS    CANARY_STEP   CANARY_STATE   MESSAGE              AGE
      rollouts-demo   Healthy                                rollout is healthy   32s

      STATUS=Healthy:表示Rollout资源正常工作。

  3. 应用版本升级。
    1. 执行以下命令,修改echoserver.yaml文件。
      kubectl edit echoserver.yaml
    2. 将Deployment的镜像版本由1.10.2升级到1.10.3。
      # echoserver.yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echoserver
      ...
      spec:
        ...
        containers:
        - name: echoserver
          # Arm架构的可以选择e2eteam/echoserver:2.2-linux-arm镜像。
          image: cilium/echoserver:1.10.3
          imagePullPolicy: IfNotPresent
    3. 执行以下命令,重新部署业务。
      kubectl apply -f echoserver.yaml
      说明 Kruise Rollout是一个常态化的配置,只需要下发到集群中即可。后面业务版本发布只需要调整Deployment配置,不需要再对Kruise Rollout进行操作。
    4. 执行以下命令,查看Rollout资源状态。
      kubectl get rollouts rollouts-demo -n default

      预期输出:

      NAME            STATUS        CANARY_STEP   CANARY_STATE   MESSAGE                                                                         AGE
      rollouts-demo   Progressing   1             StepPaused     Rollout is in step(1/1), and you need manually confirm to enter the next step   41m
      • STATUS=Progressing:表示Rollout资源已经处于灰度发布过程中。
      • CANARY_STATE=StepPaused:表示本批发布完成。
  4. 确认灰度发布的新版本发布正常后,可继续后续发布。
    1. 执行以下命令,继续后续发布。
      kubectl-kruise rollout approve rollouts/rollouts-demo

      预期输出:

      rollout.rollouts.kruise.io/rollouts-demo approved
      之后将进行后续实例发布,直至完成。
    2. 执行以下命令,查看Rollout资源状态。
      kubectl get rollouts rollouts-demo -n default

      预期输出:

      NAME            STATUS    CANARY_STEP   CANARY_STATE   MESSAGE                                   AGE
      rollouts-demo   Healthy   1             Completed      Rollout has been completed, and succeed   54m
  5. 可选:若新版本服务异常,可进行业务回滚。
    1. 执行以下命令,修改echoserver.yaml文件。
      kubectl edit echoserver.yaml
    2. 将Deployment的镜像版本由1.10.3回滚到1.10.2。
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echoserver
      ...
      spec:
        ...
        containers:
        - name: echoserver
          # Mac M1可以选择e2eteam/echoserver:2.2-linux-arm镜像版本。
          image: cilium/echoserver:1.10.2
          imagePullPolicy: IfNotPresent
    3. 执行以下命令,重新部署业务。
      kubectl apply -f echoserver.yaml
    4. 执行以下命令,查看Rollout资源状态。
      kubectl get rollouts

      预期输出:

      NAME            STATUS    CANARY_STEP   CANARY_STATE   MESSAGE                                                                       AGE
      rollouts-demo   Healthy   1             StepPaused     The workload has been rolled back and the rollout process will be cancelled   5m23s
    5. 执行以下命令,查看应用状态。
      kubectl get deployment

      预期输出:

      NAME         READY   UP-TO-DATE   AVAILABLE   AGE
      echoserver   5/5     5            5           5m21s