Kubernetes Deployment - 應用程式部署與更新
Deployment 是 Kubernetes 中部署無狀態 (Stateless) 應用程式的標準方式。 它比 ReplicaSet 更高階,提供了 宣告式更新 (Declarative Updates) 的能力,讓我們能輕鬆進行版本升級、回滾與擴展。
Deployment, ReplicaSet 與 Pod 的關係
層級關係如下:
- Deployment 管理 ReplicaSet。
- ReplicaSet 管理 Pod。
當你更新 Deployment (例如換 image tag),Deployment 會建立一個 新的 ReplicaSet,並逐漸將 Pod 從 舊的 ReplicaSet 遷移過去,這個過程稱為 滾動更新 (Rolling Update)。
定義 Deployment
建立 nginx-deployment.yaml:
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3 # 期望的副本數,這裡我們希望有 3 個 Pod 同時運行
selector:
matchLabels:
app: nginx # 用來選擇要管理的 Pod,必須與 template.metadata.labels 匹配
strategy:
type: RollingUpdate # 更新策略,預設為 RollingUpdate (滾動更新)
rollingUpdate:
maxUnavailable: 1 # 更新過程中,最多允許幾個 Pod 無法服務 (可以是數字或是百分比)
maxSurge: 1 # 更新過程中,最多允許比期望值 (replicas) 多出幾個 Pod
template: # Pod 的模板,Deployment 會根據這個模板建立 Pod
metadata:
labels:
app: nginx # Pod 的標籤
spec:
containers:
- name: nginx
image: nginx:1.14.2 # 容器映像檔,這裡故意先用舊版 1.14.2 作為示範
ports:
- containerPort: 80 # 容器暴露的端口
操作 Deployment
建立 Deployment
kubectl apply -f nginx-deployment.yaml
加上 --record 參數可以記錄指令歷程(便於回滾查看),但在新版 kubectl 已棄用,建議使用 GitOps 或註解管理。
查看狀態:
kubectl get deploy
kubectl get rs
你會看到一個由 Deployment 產生、名稱帶有 hash 的 ReplicaSet。
觸發滾動更新 (Rolling Update)
假設我們要將 Nginx 版本從 1.14.2 升級到 1.21.6。
可以直接修改 YAML 檔案並 apply,或者使用指令:
kubectl set image deployment/nginx-deploy nginx=nginx:1.21.6
觀察更新過程:
kubectl get rs
你會看到:
- 新的 RS 正在增加副本數 (0 -> 1 -> 2 -> 3)
- 舊的 RS 正在減少副本數 (3 -> 2 -> 1 -> 0)
透過 kubectl rollout status 可以監控進度:
kubectl rollout status deployment/nginx-deploy
版本回滾 (Rollback)
如果新版本有 Bug,需要緊急切回上一版:
kubectl rollout undo deployment/nginx-deploy
查看歷史版本:
kubectl rollout history deployment/nginx-deploy
擴展與縮減 (Scaling)
當流量增加時,我們可以快速擴展 Pod 的數量:
kubectl scale deployment nginx-deploy --replicas=5
當流量減少時,再縮減回來:
kubectl scale deployment nginx-deploy --replicas=3
重新啟動 (Restart)
當你更新了 ConfigMap 或 Secret,但沒有修改 Deployment 的 image tag 時,Pod 不會自動更新。這時可以使用 rollout restart 來觸發滾動更新,讓 Pod 重新讀取最新的設定配置:
kubectl rollout restart deployment/nginx-deploy
這會像一般的滾動更新一樣,逐個替換 Pod,不會造成服務中斷。
暫停與恢復 (Pause & Resume)
在更新過程中,你可以隨時暫停更新,例如為了檢查新版本的 Pod 是否正常運作(類似金絲雀發佈的手動版):
# 暫停更新
kubectl rollout pause deployment/nginx-deploy
確認沒問題後,再恢復繼續更新:
# 恢復更新
kubectl rollout resume deployment/nginx-deploy
常見更新策略
1. RollingUpdate (滾動更新 - 預設)
這是最常用的策略,透過邊殺邊建的方式,確保服務不中斷。
你可以透過 maxSurge 與 maxUnavailable 控制更新的速度與風險(如上方的 YAML 範例)。
2. Recreate (重建)
先殺光所有舊的 Pod,再建立新的 Pod。這會導致服務中斷 (Downtime),但適用於 不支援多版本同時運行 的應用程式(例如資料庫 schema 變更不相容時)。
設定方式:
spec:
strategy:
type: Recreate
結論
Deployment 是 K8s 中最核心的資源之一。掌握它,你就掌握了應用程式的部署與生命週期管理。 不過,Deployment 適用於 無狀態 (Stateless) 應用(如 Web Server)。 如果你的應用程式需要固定的網路 ID 或持久化儲存順序(如資料庫),那麼你需要的是 StatefulSet。