文档首页/ 云容器引擎 CCE/ 最佳实践/ 发布/ 使用Service实现简单的灰度发布和蓝绿发布
更新时间:2024-05-31 GMT+08:00

使用Service实现简单的灰度发布和蓝绿发布

CCE实现灰度发布通常需要向集群额外部署其他开源工具,例如Nginx Ingress,或将业务部署至服务网格,利用服务网格的能力实现。这些方案均有一些难度,如果您的灰度发布需求比较简单,且不希望引入过多的插件或复杂的用法,则可以参考本文利用Kubernetes原生的特性实现简单的灰度发布和蓝绿发布。

原理介绍

用户通常使用无状态负载 Deployment、有状态负载 StatefulSet等Kubernetes对象来部署业务,每个工作负载管理一组Pod。以Deployment为例,示意图如下:

通常还会为每个工作负载创建对应的Service,Service使用selector来匹配后端Pod,其他服务或者集群外部通过访问Service即可访问到后端Pod提供的服务。如需对外暴露可直接设置Service类型为LoadBalancer,弹性负载均衡ELB将作为流量入口。

  • 灰度发布原理

    以Deployment为例,用户通常会为每个Deployment创建一个Service,但Kubernetes并未限制Service需与Deployment一一对应。Service通过selector匹配后端Pod,若不同Deployment的Pod被同一selector选中,即可实现一个Service对应多个版本Deployment。调整不同版本Deployment的副本数,即可调整不同版本服务的权重,实现灰度发布。示意图如下:

  • 蓝绿发布原理

    以Deployment为例,集群中已部署两个不同版本的Deployment,其Pod拥有共同的label。但有一个label值不同,用于区分不同的版本。Service使用selector选中了其中一个版本的Deployment的Pod,此时通过修改Service的selector中决定服务版本的label的值来改变Service后端对应的Pod,即可实现让服务从一个版本直接切换到另一个版本。示意图如下:

前提条件

已上传Nginx镜像至容器镜像服务。为方便观测流量切分效果,Nginx镜像包含v1和v2两个版本,欢迎页分别为“Nginx-v1”“Nginx-v2”

资源创建方式

本文提供以下两种方式使用YAML部署Deployment和Service:

  • 方式1:在创建无状态工作负载向导页面,单击右侧“YAML创建”,再将本文示例的YAML文件内容输入编辑窗中。
  • 方式2:将本文的示例YAML保存为文件,再使用kubectl指定YAML文件进行创建。例如:kubectl create -f xxx.yaml

步骤1:部署两个版本的服务

在集群中部署两个版本的Nginx服务,通过ELB对外提供访问。

  1. 创建第一个版本的Deployment,本文以nginx-v1为例。YAML示例如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-v1
    spec:
      replicas: 2               # Deployment的副本数,即Pod的数量
      selector:                 # Label Selector(标签选择器)
        matchLabels:
          app: nginx
          version: v1
      template:
        metadata:
          labels:               # Pod的标签
            app: nginx
            version: v1
        spec:
          containers:
          - image: {your_repository}/nginx:v1 # 容器使用的镜像为:nginx:v1
            name: container-0
            resources:
              limits:
                cpu: 100m
                memory: 200Mi
              requests:
                cpu: 100m
                memory: 200Mi
          imagePullSecrets:
          - name: default-secret

  2. 创建第二个版本的Deployment,本文以nginx-v2为例。YAML示例如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-v2
    spec:
      replicas: 2               # Deployment的副本数,即Pod的数量
      selector:                 # Label Selector(标签选择器)
        matchLabels:
          app: nginx
          version: v2
      template:
        metadata:
          labels:               # Pod的标签
            app: nginx
            version: v2
        spec:
          containers:
          - image: {your_repository}/nginx:v2   # 容器使用的镜像为:nginx:v2
            name: container-0
            resources:
              limits:
                cpu: 100m
                memory: 200Mi
              requests:
                cpu: 100m
                memory: 200Mi
          imagePullSecrets:
          - name: default-secret

    您可以登录云容器引擎控制台查看部署情况。

步骤2:实现灰度发布

  1. 为部署的Deployment创建LoadBalancer类型的Service对外暴露服务,selector中不指定版本,让Service同时选中两个版本的Deployment的Pod。YAML示例如下:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        kubernetes.io/elb.id: 586c97da-a47c-467c-a615-bd25a20de39c    # ELB实例的ID,请替换为实际取值
      name: nginx
    spec: 
      ports:
      - name: service0
        port: 80
        protocol: TCP
        targetPort: 80
      selector:             # selector中不包含version信息
        app: nginx
      type: LoadBalancer    # 类型为LoadBalancer

  2. 执行以下命令,测试访问。

    for i in {1..10}; do curl <EXTERNAL_IP>; done;

    其中,<EXTERNAL_IP>为ELB实例的IP地址。

    返回结果如下,一半为v1版本的响应,一半为v2版本的响应。

    Nginx-v2
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v2
    Nginx-v1
    Nginx-v2
    Nginx-v1
    Nginx-v2
    Nginx-v2

  3. 通过控制台或kubectl方式调整Deployment的副本数,将v1版本调至4个副本,v2版本调至1个副本。

    kubectl scale deployment/nginx-v1 --replicas=4

    kubectl scale deployment/nginx-v2 --replicas=1

  4. 执行以下命令,再次测试访问。

    for i in {1..10}; do curl <EXTERNAL_IP>; done;

    其中,<EXTERNAL_IP>为ELB实例的IP地址。

    返回结果如下,可以看到10次访问中仅2次为v2版本的响应,v1与v2版本的响应比例与其副本数比例一致,为4:1。通过控制不同版本服务的副本数就实现了灰度发布。

    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v2
    Nginx-v1
    Nginx-v2
    Nginx-v1
    Nginx-v1
    Nginx-v1

    如果10次访问中v1和v2版本比例并非4:1,可以将访问次数调整至更大,比如20。理论上来说,次数越多,v1与v2版本的响应比例将越接近于4:1。

步骤3:实现蓝绿发布

  1. 为部署的Deployment创建LoadBalancer类型的Service对外暴露服务,指定使用v1版本的服务。YAML示例如下:

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        kubernetes.io/elb.id: 586c97da-a47c-467c-a615-bd25a20de39c    # ELB实例的ID,请替换为实际取值
      name: nginx
    spec:
      ports:
      - name: service0
        port: 80
        protocol: TCP
        targetPort: 80
      selector:             # selector中指定version为v1
        app: nginx
        version: v1
      type: LoadBalancer    # 类型为LoadBalancer 

  2. 执行以下命令,测试访问。

    for i in {1..10}; do curl <EXTERNAL_IP>; done;

    其中,<EXTERNAL_IP>为ELB实例的IP地址。

    返回结果如下,均为v1版本的响应。

    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1
    Nginx-v1

  3. 通过控制台或kubectl方式修改Service的selector,使其选中v2版本的服务。

    kubectl patch service nginx -p '{"spec":{"selector":{"version":"v2"}}}'

  4. 执行以下命令,再次测试访问。

    for i in {1..10}; do curl <EXTERNAL_IP>; done;

    其中,<EXTERNAL_IP>为ELB实例的IP地址。

    返回结果如下,均为v2版本的响应,成功实现了蓝绿发布。

    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2
    Nginx-v2