跳至主要内容

Deployment Strategies - Recreate Strategy and Rolling Update Strategy

在上一篇中,有多種 Deployment 的更新策略,其中兩個常見的方式為 Recreate StrategyRolling Update Strategy。 以下是這兩種的實作範例:


Recreate Strategy

Recreate Strategy 是 Kubernetes 的一種部署策略,會先停止所有舊版本的 Pod,確保它們完全移除後再啟動新版本的 Pod。 這種方式適合應用程式的舊版本與新版本之間不兼容的情境,或需要進行重大架構調整的場景。 雖然實現簡單,但會造成短暫停機,需謹慎使用。

實作 Recreate Strategy

  1. 首先我們先建立一個 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
  1. 接著我們撰寫 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
  1. 透過 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
  1. 接著我們透過-w (--watch) 來觀察版本更新時他會如何變化。
kubectl.exe get pods -w
  1. 我們使用 kubectl 來更新到 v2 版本的 image。
kubectl.exe apply -f recreate/app-v2.yaml
---

deployment.apps/demo-deployment configured
  1. 從結果來看,我們可以發現他將 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: 10maxSurge: 25% 表示最多可以多啟動 2.5(向上取整為 3)個 Pod。
  • 適用場景
    • 需要在升級過程中增加系統容量以應對瞬時負載的情況。
    • 高流量應用程式,在升級過程中需要確保額外的可用性。

maxUnavailable

  • 用途:定義升級過程中允許處於不可用狀態的最大 Pod 數量。
  • 運作原理
    • maxUnavailable 設定為固定值時,表示升級期間最多允許固定數量的 Pod 不可用。
    • 設定為百分比時,則按比例動態計算。例如,replicas: 10maxUnavailable: 20% 表示最多允許 2 個 Pod 不可用。
  • 適用場景
    • 應用程式的 Pod 為無狀態(Stateless)服務,且短暫的不可用性不會對用戶體驗造成重大影響。
    • 資源受限的情況下,控制新舊 Pod 的替換過程以減少資源壓力。

常見配置

maxSurgemaxUnavailable適用場景影響
10高可用性應用,需要升級期間 100% 可用確保服務無中斷,但升級速度較慢,每次只能新增 1 個 Pod 並刪除 1 個舊 Pod。
11平衡升級速度與穩定性升級速度比前者快,可同時新增 1 個 Pod 並允許 1 個 Pod 不可用,適合能容忍短暫影響的應用。
01資源有限,不能新增額外 Pod 的小型部署不增加 Pod 數量,升級過程中允許最多 1 個 Pod 不可用,適合資源緊張但對穩定性要求不高的應用。
25%25%大型部署,需快速升級並容忍部分短暫影響升級效率高,允許部分 Pod 不可用,適合容忍部分服務影響但追求升級效率的場景,例如非關鍵業務的後端服務。
50%0需要快速升級且資源充足的高可用場景升級速度極快,可同時新增大量 Pod(如 replicas=10 時最多新增 5 個),但要求所有 Pod 在升級期間保持完全可用。

實作 Rolling Update Strategy

  1. 首先一樣建立一個 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
  1. 建立 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
  1. 透過 kubectl 指令來執行 v1 的 deployment。
kubectl.exe apply -f rolling-update/app-v1.yaml
---

deployment.apps/demo-deployment created
  1. 透過-w (--watch) 來觀察 pod 如何被更新的順序。
kubectl.exe get pods -w
  1. 利用 kubectl 來執行升版,將版本升級到 v2 版本。
kubectl.exe apply -f rolling-update/app-v2.yaml
---

deployment.apps/demo-deployment configured
  1. 透過觀察 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