概述#

上一章介紹完六種常見的部署策略,本章一次練習其中兩種:Rolling Update 與 Recreate。它們之所以最容易實作,是因為它們本來就是 Deployment 內建可選的兩種 Pod 汰換策略,只要在 spec.strategy 切換型別就能切換行為。

1. 重建部署(Recreate)#

Recreate 是 Deployment 最簡單的策略,只需要把 spec.strategy.type 設為 Recreate。設定後,Deployment 會先把所有舊版本 Pod 終止,再以新版本重新建立。意味著服務的停機時間會等於應用關閉與啟動的時間,因此並不建議用於生產環境。

建立 v1 版本#

# app-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
  labels:
    app: foo
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
        version: v1
    spec:
      containers:
        - name: foo
          image: mikehsu0618/foo
          ports:
            - containerPort: 8080

部署:

kubectl apply -f app-v1.yaml

另一個終端開 watch 觀察:

kubectl get pods --watch

升級到 v2#

v2 設定僅將 template.metadata.labels.versionv1 改為 v2(其餘欄位保持不變):

# app-v2.yaml(僅顯示差異)
spec:
  template:
    metadata:
      labels:
        app: foo
        version: v2 # 由 v1 改成 v2
kubectl apply -f app-v2.yaml

回頭看 watch 視窗,可以清楚觀察到所有舊 Pod 同時進入 Terminating,等全部終止後才開始建立新版本的 Pod:

foo-deployment-8555547446-ld8fs   1/1     Running             0   8s
foo-deployment-8555547446-nbt2k   1/1     Terminating         0   21s
foo-deployment-8555547446-ld8fs   1/1     Terminating         0   22s
foo-deployment-8555547446-w6m5q   1/1     Terminating         0   22s
foo-deployment-6cbc7db745-vgmmq   0/1     Pending             0   0s
foo-deployment-6cbc7db745-8n6c7   0/1     ContainerCreating   0   0s
foo-deployment-6cbc7db745-5t7p6   1/1     Running             0   8s

Recreate 過程中所有舊 Pod 會同時下線,務必確認應用允許短暫停機再使用。

2. 滾動部署(Rolling Update,Ramped)#

Rolling Update 是 Deployment 的預設策略;不特別宣告時,Pod 會以小步快跑、細水長流的方式緩緩替換。如果想顯式指定,把 spec.strategy.type 設為 RollingUpdate,並透過 spec.strategy.rollingUpdate.{maxSurge,maxUnavailable} 控制速率。

建立 v1 版本#

# app-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo-deployment
  labels:
    app: foo
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: foo
  template:
    metadata:
      labels:
        app: foo
        version: v1
    spec:
      containers:
        - name: foo
          image: mikehsu0618/foo
          ports:
            - containerPort: 8080

兩個重要旋鈕:

  • maxSurge:一次最多可以多開幾個 Pod。
  • maxUnavailable:滾動過程中可以容忍幾個 Pod 不可用。

部署:

kubectl apply -f app-v1.yaml
kubectl get pods --watch

升級到 v2#

同樣只改 template.metadata.labels.versionv2

# app-v2.yaml(僅顯示差異)
spec:
  template:
    metadata:
      labels:
        app: foo
        version: v2 # 由 v1 改成 v2
kubectl apply -f app-v2.yaml

watch 視窗會看到新 Pod 與舊 Pod 交錯啟動/終止,依照 maxSurge=1、maxUnavailable=0 的設定逐一替換:

foo-deployment-6cbc7db745-vh8tn   0/1     Pending             0   0s
foo-deployment-6cbc7db745-vh8tn   1/1     Running             0   7s
foo-deployment-8555547446-vwtp4   1/1     Terminating         0   104s
foo-deployment-6cbc7db745-crhgt   1/1     Running             0   6s
foo-deployment-8555547446-kg5f7   1/1     Terminating         0   110s
foo-deployment-6cbc7db745-5q5tf   1/1     Running             0   5s
foo-deployment-8555547446-mrmb8   1/1     Terminating         0   115s

如此一來新版本始終維持至少 3 個 Pod 可服務,舊版本則陸續被替換掉,達到不中斷的滾動更新。

小結#

Recreate 與 Rolling Update 是 Deployment 內建的兩種策略,最容易上手也最常被使用。值得提醒:部署策略並不是互斥技術,後續章節會看到把 Rolling Update 與 Service / Ingress 的流量切換組合起來,就能拼出 Blue-Green、Canary 等更進階的玩法。

原文出處#

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