乐趣区

关于腾讯云:手把手教你在-TKE-集群中实现简单的蓝绿发布和灰度发布

概述

如何在腾讯云 Kubernetes 集群实现蓝绿公布和灰度公布?通常要向集群额定部署其它开源工具来实现,比方 Nginx Ingress,Traefik 等,或者让业务上 Service Mesh(服务网格),利用服务网格的能力来实现。这些计划多多少少都是须要一点点门槛的,如果蓝绿公布或灰度公布的需要不简单,同时不心愿让集群引入更多的组件或简单的用法,能够思考应用本文的简略计划,利用 Kubernetes 原生的个性以及腾讯云 TKE/EKS 集群自带的 LB 插件实现简略的蓝绿公布和灰度公布。

: 本文实用产品范畴: TKE 集群、EKS 集群 (弹性集群)

原理介绍

咱们通常应用 Deployment、StatefulSet 等 Kubernetes 自带的工作负载来部署业务,每个工作负载都治理一组 Pod,以 Deployment 为例:

通常还会为每个工作负载创立对应的 Service,Service 通过 selector 来匹配后端 Pod,其它服务或者内部通过拜访 Service 即可拜访到后端 Pod 提供的服务。要对外裸露能够间接将 Service 类型设置为 LoadBalancer,LB 插件会主动为其创立 CLB (腾讯云负载均衡器) 作为流量入口。

如何实现蓝绿公布?以 Deployment 为例,集群中部署两个不同版本的 Deployment,它们的 Pod 领有独特的 label,但有一个 label 的值不同,用于辨别不同的版本,Service 应用 selector 选中了其中一个版本的 Deployment 的 Pod,通过批改 Service 的 selector 中决定 服务版本的 label 的值来扭转 Service 后端对应的 Deployment,实现让服务从一个版本间接切换到另一个版本,即蓝绿公布:

如何实现灰度公布?尽管咱们通常会为每个工作负载都创立一个 Service,但 Kubernetes 并没有限度 Service 肯定要与工作负载一一对应,因为 Service 是通过 selector 来匹配后端 Pod 的,只有不同工作负载的 Pod 都能被雷同 selector 选中,就能够实现一个 Service 对应多个版本的工作负载的成果,调整不同版本工作负载的正本数就相当于调整不同版本服务的权重,实现灰度公布:

应用 YAML 创立资源

本文的示例将应用 yaml 的形式部署工作负载和创立 Service,有两种操作形式。

形式一:在 TKE 或 EKS 控制台右上角点击 YAML 创立资源 ,而后将本文示例的 yaml 粘贴进去:

形式二:将示例的 yaml 保留成文件,而后应用 kubectl 指定 yaml 文件来创立,如: kubectl apply -f xx.yaml

部署多版本工作负载

要实现蓝绿公布或灰度公布,首先咱们须要在集群中部署多个版本的工作负载,这里以简略的 nginx 为例,部署第一个版本:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: "openresty/openresty:centos"
        ports:
        - name: http
          protocol: TCP
          containerPort: 80
        volumeMounts:
        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf
          name: config
          subPath: nginx.conf
      volumes:
      - name: config
        configMap:
          name: nginx-v1
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: nginx
    version: v1
  name: nginx-v1
data:
  nginx.conf: |-
    worker_processes  1;
    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }
    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {access_by_lua 'local header_str = ngx.say("nginx-v1")';
            }
        }
    }

再部署第二个版本:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
      version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: "openresty/openresty:centos"
        ports:
        - name: http
          protocol: TCP
          containerPort: 80
        volumeMounts:
        - mountPath: /usr/local/openresty/nginx/conf/nginx.conf
          name: config
          subPath: nginx.conf
      volumes:
      - name: config
        configMap:
          name: nginx-v2
---
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: nginx
    version: v2
  name: nginx-v2
data:
  nginx.conf: |-
    worker_processes  1;
    events {
        accept_mutex on;
        multi_accept on;
        use epoll;
        worker_connections  1024;
    }
    http {
        ignore_invalid_headers off;
        server {
            listen 80;
            location / {access_by_lua 'local header_str = ngx.say("nginx-v2")';
            }
        }
    }

能够在控制台看到部署的状况:

实现蓝绿公布

为咱们部署的 Deployment 创立 LoadBalancer 类型的 Service 对外裸露服务,指定应用 v1 版本的服务:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
    protocol: TCP
    name: http
  selector:
    app: nginx
    version: v1

测试拜访:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1
nginx-v1

全是 v1 版本的响应,当初咱们切到 v2 版本,批改 Service 的 selector,让它选中 v2 版本的服务,如果在控制台改,先找到对应 Service,点击 编辑 YAML:

批改 selector 局部:

  selector:
    app: nginx
    version: v2

或者也能够间接用 kubectl 批改:

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

再次测试拜访:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v2

全是 v2 版本的响应,胜利实现了蓝绿公布。

实现灰度公布

相比蓝绿公布,咱们为不给 Service 指定应用 v1 版本的服务,从 selector 中删除 version 标签,让 Service 同时选中两个版本的 Deployment 的 Pod:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer
  ports:
  - port: 80
    protocol: TCP
    name: http
  selector:
    app: nginx

测试拜访:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v1
nginx-v1
nginx-v2
nginx-v2
nginx-v2
nginx-v1
nginx-v1
nginx-v1
nginx-v2
nginx-v2

能够看到,一半是 v1 版本的响应,另一半是 v2 版本的响应。当初咱们来调节 v1 和 v2 版本的 Deployment 的正本,将 v1 版本调至 1 个正本,v2 版本调至 4 个正本。

能够通过控制台操作:

也能够通过 kubectl 操作:

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

而后再次进行拜访测试:

$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址 nginx-v2nginx-v1nginx-v2nginx-v2nginx-v2nginx-v2nginx-v1nginx-v2nginx-v2nginx-v2$ for i in {1..10}; do curl EXTERNAL-IP; done; # 替换 EXTERNAL-IP 为 Service 的 CLB IP 地址
nginx-v2
nginx-v1
nginx-v2
nginx-v2
nginx-v2
nginx-v2
nginx-v1
nginx-v2
nginx-v2
nginx-v2

能够看到,10 次访问中只有 2 次返回了 v1 版本,v1 与 v2 的响应比例与其正本数比例统一,为 1:4,通过管制不同版本服务的正本数就实现了灰度公布。

总结

本文咱们介绍了如何在无限的条件下在 Kubernetes 集群中实现简略的蓝绿公布与灰度公布,对于一些简略的公布需要场景能够思考应用这种计划。

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

退出移动版