在 Kubernetes(K8s)集羣中部署應用時,最頭疼的就是版本更新——直接重啓服務會導致業務中斷,影響用户體驗。而 K8s 自帶的滾動更新(Rolling Update)功能完美解決了這個問題:它能逐步替換舊版本 Pod,在更新過程中保持部分實例可用,實現零停機部署;一旦更新出現問題,還能快速回滾到穩定版本,極大降低發佈風險。這篇就分享滾動更新與回滾的核心配置和實戰技巧,幫你安全高效地完成應用迭代。
一、核心認知:滾動更新的工作原理
滾動更新是 Deployment 控制器的默認更新策略,核心邏輯是“逐步替換、灰度發佈”:
- 按照配置的比例,先創建少量新版本 Pod;
- 等待新版本 Pod 就緒(Ready 狀態)後,銷燬同等數量的舊版本 Pod;
- 重複上述步驟,直到所有舊版本 Pod 被替換為新版本;
- 整個過程中,服務始終有可用實例,用户無感知。
關鍵參數(控制更新節奏):
maxSurge:更新過程中允許超出期望副本數的最大 Pod 數量(可設為整數或百分比,默認 25%);maxUnavailable:更新過程中允許不可用的最大 Pod 數量(可設為整數或百分比,默認 25%)。
簡單説,這兩個參數就像“更新閥門”:maxSurge 控制“最多多啓動多少新 Pod”,maxUnavailable 控制“最多允許多少舊 Pod 不可用”,合理配置能平衡更新速度和服務穩定性。
二、實戰:滾動更新配置與操作
以一個 Nginx 應用為例,演示如何配置滾動更新並執行版本升級。
1. 編寫 Deployment 配置(含滾動更新策略)
創建 nginx-deployment.yaml 文件,明確配置滾動更新參數:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 4 # 期望副本數(4 個實例,保證更新時高可用)
strategy:
type: RollingUpdate # 滾動更新策略(默認,可省略)
rollingUpdate:
maxSurge: 1 # 最多多啓動 1 個 Pod(避免資源佔用過高)
maxUnavailable: 0 # 不允許任何 Pod 不可用(優先保證服務穩定)
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21-alpine # 初始版本(舊版本)
ports:
- containerPort: 80
readinessProbe: # 就緒探針(關鍵!確保 Pod 真正可用才接收流量)
httpGet:
path: /
port: 80
initialDelaySeconds: 5 # 啓動後 5 秒開始探測
periodSeconds: 3 # 每 3 秒探測一次
2. 部署初始版本
# 創建 Deployment
kubectl apply -f nginx-deployment.yaml
# 查看部署狀態(確保 4 個 Pod 均為 Running)
kubectl get pods -l app=nginx
# 輸出示例:4 個 nginx:1.21-alpine 版本的 Pod 運行中
3. 執行滾動更新(升級版本)
通過修改鏡像版本觸發滾動更新,有兩種方式:
方式 1:編輯 Deployment 配置(推薦生產環境)
# 編輯配置,將鏡像改為 nginx:1.23-alpine(新版本)
kubectl edit deployment nginx-deploy
在編輯界面找到 image: nginx:1.21-alpine,改為 image: nginx:1.23-alpine,保存退出。
方式 2:用 set image 命令(快速測試)
# 直接指定新鏡像版本
kubectl set image deployment/nginx-deploy nginx=nginx:1.23-alpine
4. 觀察滾動更新過程
# 實時查看 Pod 狀態變化
kubectl get pods -l app=nginx -w
觀察輸出會發現:
- 先啓動 1 個
nginx:1.23-alpine新版本 Pod(符合maxSurge:1); - 新版本 Pod 就緒後,銷燬 1 箇舊版本 Pod;
- 重複步驟 1-2,直到 4 個 Pod 全部替換為新版本;
- 整個過程中,始終有 4 個 Pod 可用(
maxUnavailable:0生效)。
5. 驗證更新結果
# 查看 Deployment 狀態(確認更新完成)
kubectl rollout status deployment/nginx-deploy
# 輸出:deployment "nginx-deploy" successfully rolled out
# 驗證所有 Pod 均為新版本
kubectl get pods -l app=nginx -o jsonpath='{range .items[*]}{.spec.containers[0].image}{"\n"}{end}'
# 輸出均為 nginx:1.23-alpine
三、實戰:更新失敗後的快速回滾
如果新版本存在 Bug(如鏡像拉取失敗、服務異常),需要立即回滾到上一個穩定版本。
1. 模擬更新失敗
故意使用一個不存在的鏡像版本,觸發更新失敗:
kubectl set image deployment/nginx-deploy nginx=nginx:invalid-version
觀察 Pod 狀態,會發現新 Pod 處於 ImagePullBackOff 狀態,舊 Pod 被逐步銷燬但新 Pod 無法就緒,服務面臨不可用風險。
2. 查看更新歷史
# 查看 Deployment 滾動更新歷史
kubectl rollout history deployment/nginx-deploy
# 輸出示例:
# deployments "nginx-deploy"
# REVISION CHANGE-CAUSE
# 1 kubectl apply --filename=nginx-deployment.yaml
# 2 kubectl set image deployment/nginx-deploy nginx=nginx:1.23-alpine
# 3 kubectl set image deployment/nginx-deploy nginx=nginx:invalid-version
3. 回滾到上一個穩定版本(REVISION 2)
# 回滾到上一版本(快速回滾)
kubectl rollout undo deployment/nginx-deploy
# 或指定回滾到某個具體版本(如 REVISION 1)
# kubectl rollout undo deployment/nginx-deploy --to-revision=1
4. 驗證回滾結果
# 查看回滾狀態
kubectl rollout status deployment/nginx-deploy
# 驗證 Pod 鏡像已回滾到穩定版本
kubectl get pods -l app=nginx -o jsonpath='{range .items[*]}{.spec.containers[0].image}{"\n"}{end}'
# 輸出均為 nginx:1.23-alpine(穩定版本)
四、關鍵優化:零停機部署的核心技巧
1. 必須配置就緒探針(readinessProbe)
這是零停機的核心保障!如果沒有就緒探針,K8s 會認為 Pod 啓動後就可用,但此時服務可能還在初始化(如加載配置),直接接收流量會導致請求失敗。配置就緒探針後,只有探測成功的 Pod 才會被納入服務訪問列表。
2. 合理配置 maxSurge 和 maxUnavailable
- 追求穩定性(如核心服務):
maxSurge: 10%、maxUnavailable: 0,確保更新過程中無服務中斷; - 追求更新速度(如非核心服務):
maxSurge: 50%、maxUnavailable: 20%,加快更新節奏; - 資源緊張場景:降低
maxSurge(如 1),避免更新時佔用過多 CPU/內存。
3. 版本標籤化(避免使用 latest 鏡像)
永遠不要使用 nginx:latest 這類標籤,因為 latest 是動態的,更新後無法回滾到確切版本。建議使用固定版本標籤(如 nginx:1.23.1-alpine),確保更新和回滾的可追溯性。
4. 小步迭代,控制副本數
- 副本數建議 ≥3,更新時能保證足夠的可用實例;
- 重大版本更新可分階段進行:先更新 10% 副本觀察,再逐步擴大範圍。
五、避坑指南
1. 更新卡住(一直處於 Progressing 狀態)
- 原因:新 Pod 無法就緒(如就緒探針配置錯誤、鏡像拉取失敗);
- 解決:
- 查看 Pod 日誌:
kubectl logs <pod-name>; - 描述 Pod 排查問題:
kubectl describe pod <pod-name>; - 修復問題後重新觸發更新,或直接回滾。
2. 回滾後服務仍異常
- 原因:回滾時舊 Pod 未徹底銷燬,或配置殘留;
- 解決:
- 強制刪除異常 Pod:
kubectl delete pod <pod-name> --force; - 驗證 Deployment 配置:
kubectl get deployment nginx-deploy -o yaml,確保鏡像版本正確。
3. 資源不足導致更新失敗
- 原因:
maxSurge配置過大,更新時啓動的新 Pod 超出集羣資源上限; - 解決:降低
maxSurge數值,或擴容集羣資源。
總結
K8s 滾動更新與回滾是實現零停機部署的核心能力,核心要點可概括為:
- 配置就緒探針,確保 Pod 真正可用;
- 合理設置
maxSurge和maxUnavailable,平衡穩定性和更新速度; - 使用固定版本鏡像,保證更新和回滾的可追溯性;
- 出現問題時,通過
kubectl rollout undo快速回滾,降低風險。
這套方案適用於絕大多數微服務的版本迭代,無論是小版本 bug 修復,還是重大功能升級,都能在不影響用户體驗的前提下完成部署。掌握這些技巧後,你可以放心地進行頻繁的版本發佈,真正實現 DevOps 所倡導的“持續部署”理念。