溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

發(fā)布時(shí)間:2021-11-23 21:59:20 來(lái)源:億速云 閱讀:154 作者:柒染 欄目:云計(jì)算

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

原理介紹

我們通常使用 Deployment、StatefulSet 等 Kubernetes 自帶的工作負(fù)載來(lái)部署業(yè)務(wù),每個(gè)工作負(fù)載都管理一組 Pod,以 Deployment 為例:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

通常還會(huì)為每個(gè)工作負(fù)載創(chuàng)建對(duì)應(yīng)的 Service,Service 通過(guò) selector 來(lái)匹配后端 Pod,其它服務(wù)或者外部通過(guò)訪問(wèn) Service 即可訪問(wèn)到后端 Pod 提供的服務(wù)。要對(duì)外暴露可以直接將 Service 類(lèi)型設(shè)置為 LoadBalancer,LB 插件會(huì)自動(dòng)為其創(chuàng)建 CLB (騰訊云負(fù)載均衡器) 作為流量入口。

如何實(shí)現(xiàn)藍(lán)綠發(fā)布?以 Deployment 為例,集群中部署兩個(gè)不同版本的 Deployment,它們的 Pod 擁有共同的 label,但有一個(gè) label 的值不同,用于區(qū)分不同的版本,Service 使用 selector 選中了其中一個(gè)版本的 Deployment 的 Pod,通過(guò)修改 Service 的 selector 中決定 服務(wù)版本的 label 的值來(lái)改變 Service 后端對(duì)應(yīng)的 Deployment,實(shí)現(xiàn)讓服務(wù)從一個(gè)版本直接切換到另一個(gè)版本,即藍(lán)綠發(fā)布:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

如何實(shí)現(xiàn)灰度發(fā)布?雖然我們通常會(huì)為每個(gè)工作負(fù)載都創(chuàng)建一個(gè) Service,但 Kubernetes 并沒(méi)有限制 Service 一定要與工作負(fù)載一一對(duì)應(yīng),因?yàn)?Service 是通過(guò) selector 來(lái)匹配后端 Pod 的,只要不同工作負(fù)載的 Pod 都能被相同 selector 選中,就可以實(shí)現(xiàn)一個(gè) Service 對(duì)應(yīng)多個(gè)版本的工作負(fù)載的效果,調(diào)整不同版本工作負(fù)載的副本數(shù)就相當(dāng)于調(diào)整不同版本服務(wù)的權(quán)重,實(shí)現(xiàn)灰度發(fā)布:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

使用 YAML 創(chuàng)建資源

本文的示例將使用 yaml 的方式部署工作負(fù)載和創(chuàng)建 Service,有兩種操作方式。

方式一:在 TKE 或 EKS 控制臺(tái)右上角點(diǎn)擊 YAML 創(chuàng)建資源,然后將本文示例的 yaml 粘貼進(jìn)去:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

方式二:將示例的 yaml 保存成文件,然后使用 kubectl 指定 yaml 文件來(lái)創(chuàng)建,如: kubectl apply -f xx.yaml 。

部署多版本工作負(fù)載

要實(shí)現(xiàn)藍(lán)綠發(fā)布或灰度發(fā)布,首先我們需要在集群中部署多個(gè)版本的工作負(fù)載,這里以簡(jiǎn)單的 nginx 為例,部署第一個(gè)版本:

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")
                ';
            }
        }
    }

再部署第二個(gè)版本:

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")
                ';
            }
        }
    }

可以在控制臺(tái)看到部署的情況:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

實(shí)現(xiàn)藍(lán)綠發(fā)布

為我們部署的 Deployment 創(chuàng)建 LoadBalancer 類(lèi)型的 Service 對(duì)外暴露服務(wù),指定使用 v1 版本的服務(wù):

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

測(cè)試訪問(wèn):

$ 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 版本的響應(yīng),現(xiàn)在我們切到 v2 版本,修改 Service 的 selector,讓它選中 v2 版本的服務(wù),如果在控制臺(tái)改,先找到對(duì)應(yīng) Service,點(diǎn)擊 編輯YAML:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

修改 selector 部分:

  selector:
    app: nginx
    version: v2

或者也可以直接用 kubectl 修改:

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

再次測(cè)試訪問(wèn):

$ 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 版本的響應(yīng),成功實(shí)現(xiàn)了藍(lán)綠發(fā)布。

實(shí)現(xiàn)灰度發(fā)布

相比藍(lán)綠發(fā)布,我們?yōu)椴唤o Service 指定使用 v1 版本的服務(wù),從 selector 中刪除 version 標(biāo)簽,讓 Service 同時(shí)選中兩個(gè)版本的 Deployment 的 Pod:

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

測(cè)試訪問(wèn):

$ 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 版本的響應(yīng),另一半是 v2 版本的響應(yīng)?,F(xiàn)在我們來(lái)調(diào)節(jié) v1 和 v2 版本的 Deployment 的副本,將 v1 版本調(diào)至 1 個(gè)副本,v2 版本調(diào)至 4 個(gè)副本。

可以通過(guò)控制臺(tái)操作:

如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布

也可以通過(guò) kubectl 操作:

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

然后再次進(jìn)行訪問(wèn)測(cè)試:

$ 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 次訪問(wèn)中只有 2 次返回了 v1 版本,v1 與 v2 的響應(yīng)比例與其副本數(shù)比例一致,為 1:4,通過(guò)控制不同版本服務(wù)的副本數(shù)就實(shí)現(xiàn)了灰度發(fā)布。

關(guān)于如何在TKE集群中實(shí)現(xiàn)簡(jiǎn)單的藍(lán)綠發(fā)布和灰度發(fā)布問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

tke
AI