返回文章列表

Kubernetes Deployment 無狀態負載管理

本文探討如何使用 Kubernetes Deployment 管理無狀態工作負載,涵蓋滾動更新、版本控制、復原策略以及 Canary Deployment 等關鍵技術,並提供最佳實踐建議,幫助您在 Kubernetes 環境中高效佈署和管理應用程式。

容器技術 DevOps

Kubernetes Deployment 提供了宣告式方法管理無狀態應用程式,實作自動化佈署、擴縮減和版本更新。本文詳細介紹了 Deployment 的核心概念,包括滾動更新策略、版本控制、復原機制以及 Canary Deployment 的實踐方式。同時,也提供了一些 Deployment 的最佳實踐,例如使用宣告式組態管理、避免 Recreate 策略、謹慎組態探針以及合理使用標籤選擇器等,以確保應用程式在 Kubernetes 叢集中的穩定性和可靠性。透過理解這些概念和技巧,開發者可以更好地利用 Deployment 的優勢,簡化應用程式佈署流程,提高維運效率。

使用 Kubernetes Deployment 管理無狀態工作負載

刪除 Deployment 物件

要刪除 Deployment 物件,可以採取兩種方法:

  • 刪除 Deployment 物件及其所擁有的 Pod。這可以透過先縮小 Deployment 的規模來實作。
  • 刪除 Deployment 物件但保留其所擁有的 Pod。

要刪除 Deployment 物件及其 Pod,可以使用 kubectl delete 命令:

$ kubectl delete deploy nginx-deployment-readiness

執行此命令後,您會看到 Pod 被終止,Deployment 物件被刪除。

如果只想刪除 Deployment 物件而保留其 Pod,可以使用 --cascade=orphan 選項:

$ kubectl delete deploy nginx-deployment-readiness --cascade=orphan

執行此命令後,您會看到 Deployment 物件被刪除,但其所擁有的 Pod 仍然存在。

Kubernetes Deployment 如何無縫處理版本更新和滾動發布

到目前為止,我們只討論了對 Deployment 的一種可能的修改,即透過更改 replicas 引數來擴充套件或縮小 Deployment。但是,這不是我們唯一能做的!我們可以修改 Deployment 的 Pod 範本(.spec.template)來觸發滾動發布。這個滾動發布可能是由簡單的更改引起的,例如更改 Pod 的標籤,但也可能是更複雜的操作,例如將容器映像更改為不同的版本。這是最常見的場景,因為它使您能夠作為 Kubernetes 叢集操作員,以可控和可預測的方式滾動發布新版本的映像,並有效地建立新版本的 Deployment。

Deployment 使用滾動策略,可以在 YAML 清單檔案中使用 .spec.strategy.type 指定。Kubernetes 支援兩種策略:

  • RollingUpdate:這是預設策略,允許您以可控的方式滾動發布新版本的應用程式。這種策略在內部使用兩個 ReplicaSet。當您對 Deployment 的規範進行更改,導致滾動發布時,Kubernetes 將建立一個新的 ReplicaSet,其 Pod 範本更新為新的版本,並初始縮放到 0 個 Pod。舊的 ReplicaSet 將保持不變。然後,舊的 ReplicaSet 將逐漸縮小,而新的 ReplicaSet 將逐漸擴大。Pod 的不可用數量由 .spec.strategy.rollingUpdate.maxUnavailable 引數控制。
  • Recreate:這是一種簡單的策略,適用於開發場景,其中所有舊的 Pod 都被終止並替換為新的 Pod。這種策略會立即刪除任何現有的 ReplicaSet 並替換為新的 ReplicaSet。

更新 Deployment 物件

我們將透過一個實際示例來探討 RollingUpdate 策略。首先,讓我們重新建立之前用於 readiness probe 示範的 Deployment:

  1. 複製之前的 YAML 清單檔案:
$ cp nginx-deployment-readinessprobe.yaml nginx-deployment-rollingupdate.yaml
  1. 確保您具有 RollingUpdate 策略和 readinessProbe 設定,以及映像版本 nginx:1.17。這應該已經在 nginx-deployment-readinessprobe.yaml 清單檔案中設定好了:
# nginx-deployment-rollingupdate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-rollingupdate
spec:
  replicas: 3
  ...
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      ...

內容解密:

此 YAML 檔案定義了一個名為 nginx-deployment-rollingupdate 的 Deployment,具有 3 個副本,使用 RollingUpdate 策略,並設定了 minReadySeconds 為 10 秒。其中,strategy.type 指定了滾動策略的型別,而 rollingUpdate 部分則定義了滾動更新的具體引數。

將 Deployment 策略視為更進階的 Deployment 場景的基本構建塊。例如,如果您對藍綠佈署(blue/green Deployments)感興趣,可以透過結合使用 Deployments 和 Services,並操縱標籤選擇器,在 Kubernetes 中輕鬆實作這一點。您可以透過官方 Kubernetes 部落格文章瞭解更多相關資訊:https://kubernetes.io/blog/2018/04/30/zero-downtime-deployment-kubernetes-jenkins/。

使用 Kubernetes Deployment 管理無狀態工作負載

在 Kubernetes 中,Deployment 是一種用於管理無狀態工作負載的重要資源。它提供了一種宣告式的方式來定義和管理應用程式的佈署和升級。本文將探討如何使用 Kubernetes Deployment 來管理無狀態工作負載,並介紹其相關組態和操作。

滾動更新組態

在 Deployment 中,滾動更新是一種常見的升級策略。它允許在不中斷服務的情況下,逐步將舊版本的 Pod 替換為新版本的 Pod。以下是一個範例組態檔案,展示瞭如何組態滾動更新:

spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    ...
    spec:
      containers:
      - name: nginx
        image: nginx:1.17
        ...
        readinessProbe:
          httpGet:
            ...

內容解密:

  • replicas: 3 指定了 Deployment 應該維護的 Pod 數量為 3。
  • strategy.type: RollingUpdate 表示使用滾動更新策略。
  • maxUnavailable: 1 表示在滾動更新過程中,允許最多有一個 Pod 不可用(未準備好)。這意味著至少有兩個 Pod 必須保持就緒狀態,以繼續服務流量。
  • maxSurge: 1 表示在滾動更新過程中,可以建立一個額外的 Pod 超出目標數量(3 個)。這意味著在滾動更新期間,叢集中最多可以有四個 Pod(就緒或未就緒)。
  • readinessProbe 用於檢查 Pod 是否就緒。在此範例中,它透過 HTTP GET 請求檢查容器的健康狀態。

應用組態和觀察滾動更新

  1. 將上述組態儲存到檔案 nginx-deployment-rollingupdate.yaml 中。
  2. 使用 kubectl apply -f nginx-deployment-rollingupdate.yaml 命令將組態應用到叢集中。
  3. 使用 kubectl get pod 命令檢查 Pod 的狀態。

更新應用程式版本

  1. 修改 nginx-deployment-rollingupdate.yaml 檔案中的容器映象版本為 nginx:1.18
  2. 再次使用 kubectl apply -f nginx-deployment-rollingupdate.yaml 命令應用更新。
  3. 使用 kubectl rollout status deployment.apps/nginx-deployment-rollingupdate 命令觀察滾動更新的進度。

內容解密:

  • 更新容器映象版本會觸發滾動更新。
  • kubectl rollout status 命令用於觀察滾動更新的實時進度。

檢視 ReplicaSet 和 Pod 狀態

  1. 使用 kubectl describe deploy nginx-deployment-rollingupdate 命令檢視 Deployment 的詳細資訊,包括事件日誌。
  2. 使用 kubectl get rs 命令檢視 ReplicaSet 的狀態。
  3. 使用 kubectl get po 命令檢視 Pod 的狀態,並使用 kubectl describe pod <pod-name> 命令檢查特定 Pod 的詳細資訊,包括其使用的映象版本。

內容解密:

  • 舊的 ReplicaSet 會被縮小到零,但不會被刪除,以保留 Deployment 的修訂歷史。
  • .spec.revisionHistoryLimit 引數控制保留的修訂歷史數量,預設為 10。
  • 新版本的 Pod 將使用更新後的映象版本。

11.3 復原 Deployment 物件

在 Kubernetes 中,如果你使用宣告式模型來引入變更並將每次變更提交到原始碼儲存函式庫,那麼執行復原則非常簡單,只需還原提交並重新套用組態即可。通常,套用變更的過程是作為原始碼儲存函式庫的 CI/CD 管道的一部分,而不是由操作人員(例如應用程式團隊或管理員)手動套用。在基礎設施即程式碼和組態即程式碼正規化中,這是管理 Deployments 的最簡單方法,也是一般推薦的方法。

然而,Kubernetes 仍然提供了一種命令式方法來使用修訂歷史記錄復原 Deployment。對於已經宣告式更新的 Deployments,也可以執行命令式復原。

使用 kubectl 進行復原

現在,我們將示範如何使用 kubectl 進行復原。請按照以下步驟進行:

  1. 首先,讓我們命令式地推出另一個版本的 Deployment。這次,我們將 nginx 映像更新到版本 1.19:

    $ kubectl set image deployment nginx-deployment-rollingupdate nginx=nginx:1.19
    deployment.apps/nginx-deployment-rollingupdate image updated
    

    請注意,nginx=nginx:1.19 表示我們正在為 nginx-deployment-rollingupdate Deployment 中的名為 nginx 的容器設定 nginx:1.19 映像。

  2. 使用 kubectl rollout status 等待 Deployment 完成:

    $ kubectl rollout status deployment.apps/nginx-deployment-rollingupdate
    deployment "nginx-deployment-rollingupdate" successfully rolled out
    
  3. 現在,假設新版本的應用程式映像(1.19)出現問題,您的團隊決定復原到之前正常運作的映像版本。您可以使用 kubectl set image deployment nginx-deployment-example nginx=nginx:1.18 命令命令式地更改 Deployment 容器映像。此方法僅建議用於非生產場景,並且與命令式復原配合良好。

  4. Flux (https://fluxcd.io/) 是在實踐中使用宣告式模型的一個強大例子。Flux 最初由 Cloud Native Computing Foundation (CNCF) 孵化,現已畢業並成為 CNCF 景觀中的成熟專案。Flux 是 GitOps 方法的核心,用於實作雲原生應用程式的持續佈署。它透過利用 Git 和持續佈署管道等熟悉的工具,優先考慮開發人員中心的體驗,從而簡化開發人員的基礎設施管理。

檢視 Deployment 的修訂歷史

  1. 使用以下 kubectl rollout history 命令檢視 Deployment 的所有可用修訂版本:

    $ kubectl rollout history deployment.apps/nginx-deployment-rollingupdate
    deployment.apps/nginx-deployment-rollingupdate
    REVISION CHANGE-CAUSE
    1 <none>
    2 <none>
    3 <none>
    
  2. 如您所見,我們有三個修訂版本。第一個修訂版本是我們最初建立 Deployment。第二個修訂版本是宣告式更新 Deployment 到 nginx:1.18 映像。最後,第三個修訂版本是我們最後一次命令式更新 Deployment,導致 nginx:1.19 映像被推出。由於我們沒有使用 --record 旗標,因此 CHANGE-CAUSE 為空,因為 --record 旗標已被棄用,並將在未來版本中刪除。如果您需要更新 CHANGE-CAUSE,則需要手動更新 Deployment 註解。

  3. 由於宣告式變更建立的修訂版本在 CHANGE-CAUSE 中沒有太多資訊,因此若要了解有關第二個修訂版本的更多資訊,可以使用以下命令:

    $ kubectl rollout history deploy nginx-deployment-rollingupdate --revision=2
    deployment.apps/nginx-deployment-rollingupdate with revision #2
    Pod Template:
    ...<removed for brevity>...
    Containers:
    nginx:
      Image: nginx:1.18
    ...<removed for brevity>...
    
  4. 現在,讓我們執行復原到此修訂版本。由於它是前一個修訂版本,因此您可以簡單地執行以下命令:

    $ kubectl rollout undo deploy nginx-deployment-rollingupdate
    deployment.apps/nginx-deployment-rollingupdate rolled back
    

    這相當於執行復原到特定的修訂版本號:

    $ kubectl rollout undo deploy nginx-deployment-rollingupdate --to-revision=2
    
  5. 與正常推出一樣,您可以使用以下命令跟蹤復原過程:

    $ kubectl rollout status deploy nginx-deployment-rollingupdate
    
  6. 再次檢查修訂歷史:

    $ kubectl rollout history deployment.apps/nginx-deployment-rollingupdate
    deployment.apps/nginx-deployment-rollingupdate
    REVISION CHANGE-CAUSE
    1 <none>
    3 <none>
    4 <none>
    

    您會注意到版本 2 不見了,並且已建立新的 Deployment 版本。

金絲雀佈署策略(Canary Deployment Strategy)

金絲雀佈署提供了一種有價值的策略,用於在應用程式推出過程中最小化風險。它們的靈感來自於將金絲雀(鳥類別)送入煤礦以偵測危險氣體的做法。同樣,金絲雀佈署在將新版本的應用程式暴露給整個生產環境之前,將其引入有限的使用者子集。

這種受控的推出允許對新版本進行真實世界的測試,同時最小化潛在的中斷。以下是其工作原理:假設您正在為您的電子商務網站佈署更新。傳統上,整個網站會同時切換到新版本。然而,透過金絲雀佈署,可以建立兩個佈署:一個執行當前版本的穩定佈署,為大多數使用者提供服務;另一個執行新版本的金絲雀佈署,為一小部分使用者提供服務。然後,像 ingress 控制器或服務註解這樣的流量路由機制會將特定比例的流量(例如 10%)引導到金絲雀佈署。

金絲雀佈署的 YAML 範例

# 穩定應用程式
...
name: frontend-stable
replicas: 3

透過密切監控金絲雀佈署的效能(透過錯誤率、回應時間和使用者回饋等指標),您可以評估新版本的穩定性。如果一切順利,您可以逐漸增加引導到金絲雀佈署的流量比例,直到它為所有使用者提供服務。相反,如果出現問題,您可以輕鬆地回復金絲雀佈署並維護穩定版本,從而防止對您的使用者群產生更廣泛的影響。

如何暫停和還原 Deployment 的推出

如果您需要暫停和還原 Deployment 的持續推出,可以使用 kubectl rollout pause deployment nginx-deployment-examplekubectl rollout resume deployment nginx-deployment-example 命令。

使用 Kubernetes Deployment 管理無狀態工作負載的最佳實踐

在 Kubernetes 中,Deployment 是一種強大的資源,用於管理無狀態應用程式的佈署和更新。本文將探討如何使用 Deployment 管理無狀態工作負載,並提供一些最佳實踐。

什麼是 Canary Deployment?

Canary Deployment 是一種佈署策略,允許您在生產環境中測試新版本的應用程式,同時保持舊版本的穩定執行。透過調整 Deployment 的副本數量,您可以控制流量分配給新舊版本的比例。

以下是一個 Canary Deployment 的範例:

# 穩定版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-stable
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      tier: frontend
      version: stable
  template:
    metadata:
      labels:
        app: myapp
        tier: frontend
        version: stable
    spec:
      containers:
      - name: frontend
        image: frontend-app:1.0

# Canary 版本
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      tier: frontend
      version: canary
  template:
    metadata:
      labels:
        app: myapp
        tier: frontend
        version: canary
    spec:
      containers:
      - name: frontend
        image: frontend-app:2.0

# Service 將流量路由到兩種版本的 Deployment
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    app: myapp
    tier: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

內容解密:

此範例中,我們定義了兩個 Deployment:frontend-stablefrontend-canary,分別執行穩定版本和 Canary 版本的應用程式。Service frontend-service 將流量路由到兩種版本的 Deployment,透過調整副本數量來控制流量分配。

使用 Deployment 的最佳實踐

使用宣告式管理

在 DevOps 和容器化應用程式的世界中,宣告式管理是最佳實踐。使用 kubectl apply 命令可以輕鬆地對 Deployment 進行宣告式更新。

避免使用 Recreate 策略

Recreate 策略可能會導致停機,因此在生產環境中應避免使用。相反,使用 RollingUpdate 策略可以實作零停機佈署。

不要建立與現有 Deployment 標籤選擇器匹配的 Pod

建立與現有 Deployment 標籤選擇器匹配的 Pod 可能會導致衝突和不可預測的結果。應使用語義標籤來避免此類別問題。

謹慎組態容器探針

容器探針(liveness、readiness 和 startup)可以提供許多好處,但如果組態錯誤,也可能導致停機或級聯故障。應謹慎組態探針,並瞭解其對其他 Kubernetes 資源的影響。