Deployment Strategies - Recreate Strategy and Rolling Update Strategy
在上一篇中,有多種 Deployment 的更新策略,其中兩個常見的方式為 Recreate Strategy 與 Rolling Update Strategy。 以下是這兩種的實作範例:
Recreate Strategy
Recreate Strategy 是 Kubernetes 的一種部署策略,會先停止所有舊版本的 Pod,確保它們完全移除後再啟動新版本的 Pod。 這種方式適合應用程式的舊版本與新版本之間不兼容的情境,或需要進行重大架構調整的場景。 雖然實現簡單,但會造成短暫停機,需謹慎使用。
實作 Recreate Strategy
- 首先我們先建立一個 deployment,他是部屬 v1 的 image,部屬 replicas 數量為 3,我們經部屬策略改成
Recreate
,並且我們在 label 地方增加 version v1。
recreate/app-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
labels:
app: demo
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
version: v1
spec:
containers:
- name: demo-container
image: hello-world:v1.0.0
ports:
- containerPort: 8080
- 接著我們撰寫 v2 版本的 deployment,我們將 image 改成 v2 版本的,並且將 label 中的 version 改成 v2。
recreate/app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
labels:
app: demo
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
version: v2
spec:
containers:
- name: demo-container
image: hello-world:v2.0.0
ports:
- containerPort: 8080
- 透過 kubectl 使令來將 app-v1 運行起來,也能查看他是否建立三個 pod,並且都達到 Running 狀態。
kubectl.exe apply -f recreate/app-v1.yaml
---
deployment.apps/demo-deployment created
kubectl.exe get pods
---
NAME READY STATUS RESTARTS AGE
demo-deployment-75b4bd45c5-85pth 1/1 Running 0 91s
demo-deployment-75b4bd45c5-w29q5 1/1 Running 0 91s
demo-deployment-75b4bd45c5-w7pg5 1/1 Running 0 91s
- 接著我們透過-w (--watch) 來觀察版本更新時他會如何變化。
kubectl.exe get pods -w
- 我們使用 kubectl 來更新到 v2 版本的 image。
kubectl.exe apply -f recreate/app-v2.yaml
---
deployment.apps/demo-deployment configured
- 從結果來看,我們可以發現他將 v1 的 3 個 pod 全部都 termiated 之後,才開始創立 v2 版本的 pod,這中間存在著停機時間。
kubectl.exe get pods -w
---
NAME READY STATUS RESTARTS AGE
demo-deployment-75b4bd45c5-85pth 1/1 Running 0 2m52s
demo-deployment-75b4bd45c5-w29q5 1/1 Running 0 2m52s
demo-deployment-75b4bd45c5-w7pg5 1/1 Running 0 2m52s
demo-deployment-75b4bd45c5-85pth 1/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w29q5 1/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w7pg5 1/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w7pg5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-85pth 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w29q5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w29q5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-85pth 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w7pg5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-85pth 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-85pth 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w7pg5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w7pg5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w29q5 0/1 Terminating 0 4m22s
demo-deployment-75b4bd45c5-w29q5 0/1 Terminating 0 4m22s
demo-deployment-6c5d69f4dc-m2k56 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-hvfm4 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-b2lp4 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-m2k56 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-hvfm4 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-b2lp4 0/1 Pending 0 1s
demo-deployment-6c5d69f4dc-m2k56 0/1 ContainerCreating 0 1s
demo-deployment-6c5d69f4dc-b2lp4 0/1 ContainerCreating 0 1s
demo-deployment-6c5d69f4dc-hvfm4 0/1 ContainerCreating 0 1s
demo-deployment-6c5d69f4dc-m2k56 1/1 Running 0 1s
demo-deployment-6c5d69f4dc-hvfm4 1/1 Running 0 1s
demo-deployment-6c5d69f4dc-b2lp4 1/1 Running 0 1s
Rolling Update Strategy
Rolling Update Strategy 是 Kubernetes 中預設的部署策略,允許舊版本的 Pod 和新版本的 Pod 在部署過程中共存。 系統會逐步啟動新版本的 Pod,同時逐步關閉 舊版本的 Pod,確保服務始終可用。 此策略能實現零停機時間,是更新需要穩定性和用戶體驗的最佳選擇,但需考量新舊版本的兼容性。
參數詳細說明
minReadySeconds
- 用途:確保新 Pod 在完全啟動且能夠正常處理流量後,才被 Kubernetes 認定為準備就緒(Ready)。
- 重要性:
- 如果應用程式啟動時間較長,例如需要載入大量配置或進行初始化,未設定
minReadySeconds
可能會導致 Kubernetes 過早將其視為就緒並繼續升級,從而導致服務中斷。 - Kubernetes 會等待每個新 Pod 達到
minReadySeconds
後,再進行下一步的升級操作,因此可以更精確控制升級節奏。
- 如果應用程式啟動時間較長,例如需要載入大量配置或進行初始化,未設定
- 適用場景:
- 啟動時間較長的應用程式(例如,微服務架構中的資料庫或機器學習模型服務)。
- 嚴格需要穩定提供服務的場景,避免新 Pod 在未準備好時處理流量。
maxSurge
- 用途:定義升級過程中可以額外啟動的 Pod 數量,幫助確保升級期間能維持服務的可用性。
- 運作原理:
maxSurge
設定為一個固定值時,表示最多能多出固定數量的 Pod。- 設定為百分比時,會根據
replicas
的數量動態計算多出的 Pod 數量。例如,replicas: 10
,maxSurge: 25%
表示最多可以多啟動 2.5(向上取整為 3)個 Pod。
- 適用場景:
- 需要在升級過程中增加系統容量以應對瞬時負載的情況。
- 高流量應用程式,在升級過程中需要確保額外的可用性。
maxUnavailable
- 用途:定義升級過程中允許處於不可用狀態的最大 Pod 數量。
- 運作原理:
maxUnavailable
設定為固定值時,表示升級期間最多允許固定數量的 Pod 不可用。- 設定為百分比時,則按比例動態計算。例如,
replicas: 10
,maxUnavailable: 20%
表示最多允許 2 個 Pod 不可用。
- 適用場景:
- 應用程式的 Pod 為無狀態(Stateless)服務,且短暫的不可用性不會對用戶體驗造成重大影響。
- 資源受限的情況下,控制新舊 Pod 的替換過程以減少資源壓力。
常見配置
maxSurge | maxUnavailable | 適用場景 | 影響 |
---|---|---|---|
1 | 0 | 高可用性應用,需要升級期間 100% 可用 | 確保服務無中斷,但升級速度較慢,每次只能新增 1 個 Pod 並刪除 1 個舊 Pod。 |
1 | 1 | 平衡升級速度與穩定性 | 升級速度比前者快,可同時新增 1 個 Pod 並允許 1 個 Pod 不可用,適合能容忍短暫影響的應用。 |
0 | 1 | 資源有限,不能新增額外 Pod 的小型部署 | 不增加 Pod 數量,升級過程中允許最多 1 個 Pod 不可用,適合資源緊張但對穩定性要求不高的應用。 |
25% | 25% | 大型部署,需快速升級並容忍部分短暫影響 | 升級效率高,允許部分 Pod 不可用,適合容忍部分服務影響但追求升級效率的場景,例如非關鍵業務的後端服務。 |
50% | 0 | 需要快速升級且資源充足的高可用場景 | 升級速度極快,可同時新增大量 Pod(如 replicas=10 時最多新增 5 個),但要求所有 Pod 在升級期間保持完全可用。 |
實作 Rolling Update Strategy
- 首先一樣建立一個 deployment,並且將 strategy 設定為 RollingUpdate,然後 maxSurge 設定為 1、maxUnavailable 設定為 0、minReadySeconds 設定為 5 秒,這樣就能設定平穩的更新策略。
rolling-update/app-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
labels:
app: demo
spec:
replicas: 3
strategy:
type: RollingUpdate # 部署策略為滾動更新(RollingUpdate),逐步替換舊 Pod
rollingUpdate:
maxSurge: 1 # 升級期間允許額外增加的 Pod 數量(這裡是 1 個)
maxUnavailable: 0 # 升級期間允許不可用的 Pod 數量(這裡是 0,確保服務不中斷)
minReadySeconds: 5 # 新 Pod 啟動後需等待 5 秒,確保其準備就緒後才繼續下一步
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
version: v1
spec:
containers:
- name: demo-container
image: hello-world:v1.0.0
ports:
- containerPort: 8080
- 建立 image 為 v2 版本的 deployment,將 label 和 image 改為 v2 版本。
rolling-update/app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
labels:
app: demo
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
minReadySeconds: 5
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
version: v2
spec:
containers:
- name: demo-container
image: hello-world:v2.0.0
ports:
- containerPort: 8080
- 透過 kubectl 指令來執行 v1 的 deployment。
kubectl.exe apply -f rolling-update/app-v1.yaml
---
deployment.apps/demo-deployment created
- 透過-w (--watch) 來觀察 pod 如何被更新的順序。
kubectl.exe get pods -w
- 利用 kubectl 來執行升版,將版本升級到 v2 版本。
kubectl.exe apply -f rolling-update/app-v2.yaml
---
deployment.apps/demo-deployment configured
- 透過觀察 pods,我們可以發現因為 maxSurge 設為 1、maxUnavailable 設為 0 的關係,首先會先創立一個 pod,直到他 Running 後,才會把原本的其中一個 pod 關閉,往後依序這樣創立再刪除,將三個 pod 完全升版。
kubectl.exe get pods -w
---
NAME READY STATUS RESTARTS AGE
demo-deployment-75b4bd45c5-b9s9s 1/1 Running 0 55s
demo-deployment-75b4bd45c5-r2hzj 1/1 Running 0 55s
demo-deployment-75b4bd45c5-sbfv7 1/1 Running 0 55s
demo-deployment-6c5d69f4dc-zrj87 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-zrj87 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-zrj87 0/1 ContainerCreating 0 0s
demo-deployment-6c5d69f4dc-zrj87 1/1 Running 0 1s
demo-deployment-75b4bd45c5-sbfv7 1/1 Terminating 0 119s
demo-deployment-6c5d69f4dc-lfxc4 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-lfxc4 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-lfxc4 0/1 ContainerCreating 0 0s
demo-deployment-75b4bd45c5-sbfv7 0/1 Terminating 0 119s
demo-deployment-75b4bd45c5-sbfv7 0/1 Terminating 0 2m
demo-deployment-75b4bd45c5-sbfv7 0/1 Terminating 0 2m
demo-deployment-75b4bd45c5-sbfv7 0/1 Terminating 0 2m
demo-deployment-6c5d69f4dc-lfxc4 1/1 Running 0 1s
demo-deployment-75b4bd45c5-b9s9s 1/1 Terminating 0 2m5s
demo-deployment-6c5d69f4dc-wljfm 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-wljfm 0/1 Pending 0 0s
demo-deployment-6c5d69f4dc-wljfm 0/1 ContainerCreating 0 0s
demo-deployment-75b4bd45c5-b9s9s 0/1 Terminating 0 2m5s
demo-deployment-75b4bd45c5-b9s9s 0/1 Terminating 0 2m6s
demo-deployment-6c5d69f4dc-wljfm 1/1 Running 0 1s
demo-deployment-75b4bd45c5-b9s9s 0/1 Terminating 0 2m6s
demo-deployment-75b4bd45c5-b9s9s 0/1 Terminating 0 2m6s
demo-deployment-75b4bd45c5-r2hzj 1/1 Terminating 0 2m11s
demo-deployment-75b4bd45c5-r2hzj 0/1 Terminating 0 2m12s
demo-deployment-75b4bd45c5-r2hzj 0/1 Terminating 0 2m12s
demo-deployment-75b4bd45c5-r2hzj 0/1 Terminating 0 2m12s
demo-deployment-75b4bd45c5-r2hzj 0/1 Terminating 0 2m12s