概述#

接續上一章 Deployment 內建的 Recreate 與 Rolling Update,這次我們把藍綠部署(Blue-Green Deployment)放上桌。Kubernetes 的優勢在於可以用 Service 或 Ingress 等資源自由地調度流量,所以即便沒有「藍綠」這種預設策略,我們仍能輕易把它的精神實作出來。本章用最直覺的 Service 做示範。

藍綠部署的特色#

藍綠部署是常見的零停機(Zero Downtime)策略:穩定、單純,且同一時間線上不會出現新舊版本並存的疑慮。代價是更新期間需要兩倍資源同時運作;只要資源能撐住,這通常是最划算的穩定性換時間方案。

落實步驟#

在 Kubernetes 中,藍綠部署的關鍵在於透過 Label 與 Selector 控制流量去向:

  1. 啟動 v1 版本,並用 Service 的 Label Selector 鎖定 v1 作為對外入口。
  2. 部署 v2 版本,待它完全就緒。此時新舊兩個版本同時存在。
  3. 把 Service 的 Selector 從 v1 切到 v2,瞬間完成版本切換。
  4. 確認穩定後,關閉舊的 v1 版本資源。

實戰練習#

1. 啟動 v1 版本與 Service#

# app-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
  labels:
    app: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: v1
  template:
    metadata:
      labels:
        app: my-app
        version: v1
    spec:
      containers:
        - name: foo
          image: mikehsu0618/foo
          ports:
            - containerPort: 8080
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: blue-green-service
spec:
  selector:
    app: my-app
    version: v1
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

Service 的 Selector 同時指定了 app: my-appversion: v1,所以對外只會看到 v1 版本。

部署並驗證:

kubectl apply -f app-v1.yaml -f service.yaml
kubectl get all
curl localhost:8080   # {"data":"Hello foo"}

2. 預先把 v2 啟動起來#

# app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: bar-deployment
  labels:
    app: bar
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: v2
  template:
    metadata:
      labels:
        app: my-app
        version: v2
    spec:
      containers:
        - name: bar
          image: mikehsu0618/bar
          ports:
            - containerPort: 8080
kubectl apply -f app-v2.yaml
kubectl get all

此時叢集裡 v1 與 v2 都在運作,但對外仍只有 v1 接收流量:

curl localhost:8080   # 仍然回傳 {"data":"Hello foo"}

3. 將 Service 的 Selector 切換到 v2#

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: blue-green-service
spec:
  selector:
    app: my-app
    version: v2 # 從 v1 改為 v2
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
kubectl apply -f service.yaml
kubectl describe service blue-green-service

切換後 Service 的 Endpoints 會立刻指向 v2 對應的 Pod,再次測試:

curl localhost:8080   # {"data":"Hello bar"}

4. 關閉舊的 v1 版本#

kubectl delete -f app-v1.yaml
kubectl get all

只剩下 v2 的 bar-deployment,藍綠部署正式完成切換。

小結#

只用 Deployment 與 Service 就能拼出一條完整的藍綠流水線。重點在於把 Label 設計好、用 Selector 當成「流量開關」,瞬間完成版本切換並保留隨時回滾的能力。再次印證:Kubernetes 的部署策略並沒有死板的形式,能穩穩落實精神就是好設計。

原文出處#

  • GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day14
  • iThome:https://ithelp.ithome.com.tw/articles/10290317