部分借鉴地址: https://support.huaweicloud.com/intl/zh-cn/bestpractice-cce/cce_bestpractice_10002.html
1.原理介绍

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

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Deployment

通常还会为每个工作负载创建对应的Service,Service使用selector来匹配后端Pod,其他服务或者集群外部通过访问Service即可访问到后端Pod提供的服务.

2.灰度发布原理

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

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Deployment_02

3.蓝绿发布原理

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

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Deployment_03

4.灰度发布yaml配置
cat> ./k8s-grayscale-all.yaml >> EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        version: v1
        app: nginx
    spec:
      containers:
      - name: nginx
        image: docker.io/nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: docker.io/nginx:latest
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
  - name: nginx-port
    protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_04

查看ep 资源对象和部署服务名称

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_05

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_nginx_06

5.测试验证-灰度发布

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_nginx_07

6.蓝绿发布YAMl配置
cat> ./k8s-blue-green-all.yaml >> EOF
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        version: v1
        app: nginx
    spec:
      containers:
      - name: nginx
        image: docker.io/nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: docker.io/nginx:latest
        ports:
        - containerPort: 80

--- 
#应用流量转发至 nginnx-v1 应用
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  selector:
    app: nginx
    version: v1
  ports:
  - name: nginx-port
    protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer
EOF
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
7.测试验证-绿色版本应用 v1

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_08

8.测试验证-蓝色版本应用 v2
#切换至蓝色v2 版本应用命令

[root@rocklinux-k8s-master]# kubectl patch service nginx-svc -p '{"spec":{"selector":{"version":"v2"}}}' -n demo
service/nginx-svc patched
  • 1.
  • 2.
  • 3.
  • 4.

v2切换

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_09

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_nginx_10

切换v1 和 v2 结果对比

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_11

9.发布蓝绿切换命令
#切换至v1 版本
kubectl patch service nginx-svc -p '{"spec":{"selector":{"version":"v1"}}}' -n demo
service/nginx-svc patched

#切换至v2 版本
kubectl patch service nginx-svc -p '{"spec":{"selector":{"version":"v2"}}}' -n demo
service/nginx-svc patched
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
10.补充自建集群SVC LoadBalancer

细心的博友会发现自建集群中无法直接使用 LoadBalancer 但是开源社区中

metallb 项目可以提供 负载均衡的类型的svc 具体部署如下

集群版本: v1.28.2    

操作系统: Rocky Linux release 9.4 (Blue Onyx)

内核版本: 5.14.0-427.13.1.el9_4.x86_64

metallb 版本: v0.14.8 

# metallb-native.yaml 部署yaml 文件
kubectl apply -f  https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
kubectl apply -f  https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-frr.yaml
  • 1.
  • 2.
  • 3.

修改网络配置文件

cat> IPAddressPool.yaml >> EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.0.200-192.168.0.250
EOF

cat > L2Advertisement.yaml >> EOF
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-lb-example
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool
EOF

kubectl create -f L2Advertisement.yaml
kubectl create -f IPAddressPool.yaml
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布_Pod_12