Chuyển đến nội dung chính

第3課: Rolling Updates 與 Rollbacks

Deployment 更新策略: RollingUpdate vs Recreate。maxUnavailable 和 maxSurge 的配置。 kubectl rollout 指令: status、history、undo。版本紀錄管理。

Rolling Updates 與 Rollbacks — maxUnavailable、maxSurge 視覺化

1. 更新策略

策略行為停機時間使用場景
RollingUpdate(預設)逐步替換舊 Pod零停機大部分生產環境
Recreate先刪除所有舊 Pod,再建立新 Pod有停機不能多版本並存的應用
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1     # 更新期間最多有 1 個 Pod 不可用
      maxSurge: 1           # 更新期間最多額外建立 1 個 Pod

# replicas=10 + maxUnavailable=1 + maxSurge=1 的情況:
# 最少可用: 10 - 1 = 9 個 Pod
# 最多存在: 10 + 1 = 11 個 Pod
RollingUpdate 過程(replicas=4, maxUnavailable=1, maxSurge=1):

起始:   [v1] [v1] [v1] [v1]         ← 4 個 v1 Pods
步驟1:  [v1] [v1] [v1] [--] [v2]   ← 終止 1 個 v1,啟動 1 個 v2
步驟2:  [v1] [v1] [--] [v2] [v2]   ← 繼續替換
步驟3:  [v1] [--] [v2] [v2] [v2]   
完成:   [v2] [v2] [v2] [v2]         ← 全部更新為 v2

考試重點: maxUnavailable 和 maxSurge 可以設定為絕對數字或百分比。maxUnavailable: 25% 和 maxSurge: 25% 是預設值。計算題:replicas=10, maxSurge=2 → 更新期間最多存在 12 個 Pod。

2. kubectl rollout 指令

# 查看 rollout 狀態
kubectl rollout status deployment/myapp

# 查看修訂版本歷史
kubectl rollout history deployment/myapp
kubectl rollout history deployment/myapp --revision=2

# 回滾到上一個版本
kubectl rollout undo deployment/myapp

# 回滾到特定版本
kubectl rollout undo deployment/myapp --to-revision=3

# 暫停和恢復 rollout(多次變更後一次套用)
kubectl rollout pause deployment/myapp
# ... 進行多次 kubectl set image / kubectl patch ...
kubectl rollout resume deployment/myapp

# 重啟(觸發 rolling restart)
kubectl rollout restart deployment/myapp

3. 觸發更新

# 方法 1: 直接設定 image
kubectl set image deployment/myapp app=nginx:1.25 --record

# 方法 2: kubectl edit
kubectl edit deployment myapp

# 方法 3: kubectl patch
kubectl patch deployment myapp -p '{"spec":{"template":{"spec":{"containers":[{"name":"app","image":"nginx:1.25"}]}}}}'

# 方法 4: 修改 YAML 檔案並 apply
kubectl apply -f deployment.yaml

4. 版本紀錄管理

spec:
  revisionHistoryLimit: 10   # 保留的 ReplicaSet 數量(預設 10)

# 使用 --record 記錄變更原因(已棄用但仍可用)
kubectl set image deployment/myapp app=nginx:1.25 --record

# 使用 annotation 替代 --record(推薦方式)
kubectl annotate deployment/myapp kubernetes.io/change-cause="upgrade to 1.25"

# 查看各版本的變更記錄
kubectl rollout history deployment/myapp
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy.yaml
2         upgrade to 1.25
3         upgrade to 1.26

5. 速查表

任務指令
更新映像檔kubectl set image deploy/app c=img:tag
回滾kubectl rollout undo deploy/app
回滾到指定版本kubectl rollout undo deploy/app --to-revision=N
查看 rollout 進度kubectl rollout status deploy/app
查看歷史版本kubectl rollout history deploy/app
暫停 rolloutkubectl rollout pause deploy/app

6. 練習題

Q1: 一個 Deployment 有 replicas=10, maxSurge=3, maxUnavailable=0。Rolling update 期間最多同時存在多少個 Pod?

  • A) 10
  • B) 13 ✓
  • C) 7
  • D) 3

解析: maxSurge=3 允許超出 desired 數量最多 3 個 Pod → 10 + 3 = 13。maxUnavailable=0 表示任何時候都必須至少有 10 個 Pod 可用。此設定確保零停機更新,但消耗更多資源。

Q2: 您剛部署了新版本的映像檔,發現有 bug。最快回滾到上一個版本的指令是什麼?

  • A) kubectl rollout restart deployment/myapp
  • B) kubectl rollout undo deployment/myapp ✓
  • C) kubectl delete deployment myapp && kubectl apply -f old.yaml
  • D) kubectl set image deployment/myapp app=previous-image

解析: kubectl rollout undo 立即回滾到上一個版本(revision N-1)。不需要記住舊映像檔名稱或保留舊 YAML 檔案。也可以用 --to-revision=N 回滾到特定版本。

Q3: Deployment 使用 Recreate 策略。更新觸發時會發生什麼?

  • A) 逐步替換 Pod,保持服務可用
  • B) 先刪除所有舊 Pod,然後建立新 Pod(有停機) ✓
  • C) 建立新的 ReplicaSet,在流量切換前驗證
  • D) 同時運行舊版和新版 Pod

解析: Recreate 策略先終止所有現有 Pod,等全部停止後再建立新版本的 Pod。這會導致停機時間,但避免多版本同時運行的問題(如資料庫 schema 不相容的情況)。