返回文章列表

Kubernetes StatefulSet 滾動更新與回復策略

本文探討 Kubernetes StatefulSet 的滾動更新和回復策略,包含使用 Partition 進行 Canary 發布、觀察滾動更新狀態、利用宣告式模型進行回復以及最佳實踐建議。文章提供 YAML 組態範例和指令操作說明,協助您理解如何安全、有效地更新和管理有狀態應用程式。

容器技術 DevOps

在 Kubernetes 環境中,管理有狀態應用程式的更新至關重要。StatefulSet 提供了滾動更新機制,允許逐步更新 Pod,將服務中斷風險降至最低。本文將詳細介紹如何使用 RollingUpdate 策略和 Partition 引數實作更精細的控制,例如 Canary 發布,並探討如何觀察更新狀態和進行回復操作。同時,我們也會提供一些 StatefulSet 的最佳實踐,幫助您更好地管理有狀態應用程式。

在更新 StatefulSet 時,kubectl rollout status 命令可以幫助我們監控更新進度,確保每個 Pod 都按預期更新。updateStrategy.type: RollingUpdate 允許我們使用 rollingUpdate.partition 引數控制更新的 Pod 範圍。設定 Partition 後,只有序號大於或等於 Partition 值的 Pod 會被更新,方便進行 Canary 發布,驗證新版本的功能和穩定性後再更新剩餘 Pod。如果更新過程中出現問題,我們可以透過修改 YAML 檔案並重新套用,或是使用 kubectl rollout undo 命令回復到之前的版本,確保應用程式的穩定執行。

使用 StatefulSet 佈署有狀態應用程式

滾動更新與 Canary 發布

在 Kubernetes 中,StatefulSet 是一種用於管理有狀態應用程式的 API 物件。它確保了 Pod 的身份和永續性,使其非常適合用於需要穩定網路身份和持久儲存的應用程式,如資料函式庫。

滾動更新

滾動更新是一種 StatefulSet 更新策略,它允許您逐步更新 Pod,以最小化對應用程式的影響。以下是一個使用 MySQL 作為範例的滾動更新流程:

  1. 準備 StatefulSet 組態檔案:首先,您需要準備一個 StatefulSet 的 YAML 組態檔案,例如 mysql-statefulset-rolling-update.yaml。該檔案定義了 MySQL StatefulSet 的規格,包括容器映像、服務名稱等。

  2. 更新容器映像:在組態檔案中,將 MySQL 的映像版本從 8.3.0 更新至 8.4.0。這是透過修改 spec.containers.image 欄位來實作的。

    spec:
      containers:
      - name: mysql
        image: mysql:8.4.0
    
  3. 套用組態變更:使用 kubectl apply 命令將更新後的組態檔案套用到叢集。

    $ kubectl apply -f mysql-statefulset-rolling-update.yaml
    
  4. 觀察滾動更新過程:使用 kubectl rollout status 命令觀察 StatefulSet 的滾動更新過程。

    $ kubectl rollout status statefulset -n mysql
    

使用 Partition 進行 Canary 發布

在進行滾動更新時,您可以使用 partition 欄位來控制哪些 Pod 應該被更新。這使得您可以進行 canary 發布,即先更新一部分 Pod,以測試新版本是否穩定。

  1. 設定 Partition:在 StatefulSet 的 updateStrategy 部分,設定 partition 為所需的序號。這樣,只有序號大於或等於該值的 Pod 才會被更新。

    updateStrategy:
      type: RollingUpdate
      rollingUpdate:
        partition: 2
    
  2. 套用變更並觀察:套用變更後,觀察 StatefulSet 的更新過程。只有指定的 Pod 會被更新。

  3. 驗證 Canary:登入到新的 Pod 中,驗證新版本是否運作正常。

    $ kubectl exec -it -n mysql k8sutils -- /bin/bash
    root@k8sutils:/# mysql -u root -p -h mysql-stateful-2.mysql-headless
    
  4. 完成滾動更新:如果 canary 發布成功,您可以將 partition 設定為 0,以完成整個 StatefulSet 的滾動更新。

程式碼解說

以下是一個範例 YAML 組態檔案,用於定義 MySQL StatefulSet 的滾動更新策略:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-stateful
spec:
  serviceName: mysql-headless
  podManagementPolicy: OrderedReady
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.4.0
        ports:
        - containerPort: 3306

內容解密:

  1. apiVersionkind:定義了 Kubernetes 物件的 API 版本和型別。
  2. metadata:提供了關於物件的中繼資料,如名稱。
  3. spec.serviceName:指定了與 StatefulSet 相關聯的無頭服務名稱。
  4. updateStrategy.type:定義了更新策略的型別,這裡使用的是 RollingUpdate
  5. rollingUpdate.partition:控制哪些 Pod 應該被更新,設為 0 表示全部更新。
  6. replicas:指定了 StatefulSet 中 Pod 的副本數量。
  7. template.spec.containers.image:定義了容器所使用的映像版本。

管理StatefulSet的滾動更新與回復

在前一章中,我們討論瞭如何使用Kubernetes Deployment來管理無狀態應用程式。本章節將著重於StatefulSet的滾動更新與回復操作。

觀察StatefulSet的滾動更新狀態

使用kubectl rollout status命令可以觀察StatefulSet的滾動更新狀態:

$ kubectl rollout status statefulset -n mysql
Waiting for partitioned roll out to finish: 1 out of 3 new pods have been updated...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for partitioned roll out to finish: 2 out of 3 new pods have been updated...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
partitioned roll out complete: 3 new pods have been updated...

如上所示,滾動更新到mysql:8.4.0映像版本已成功完成。

回復StatefulSet

對於StatefulSet,回復操作與Deployment類別似,可以使用kubectl rollout undo命令。但是,對於StatefulSet,建議使用宣告式模型來引入變更。

使用宣告式模型進行回復

宣告式模型的優點是,可以將變更提交到原始碼儲存函式庫,並透過CI/CD管道自動套用變更。要回復StatefulSet,只需還原提交並重新套用組態即可。

# 修改YAML manifest檔案或還原提交
# 套用變更
$ kubectl apply -f mysql-statefulset.yaml

使用指令式模型進行分階段滾動更新

雖然可以使用kubectl patch命令進行分階段滾動更新,但這種方法可讀性較差,且容易出錯。

$ kubectl patch sts mysql-stateful -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}' -n mysql

StatefulSet最佳實踐

本文總結了使用StatefulSet時的已知最佳實踐。

使用宣告式物件管理

宣告式模型是DevOps世界中的良好實踐,可以使用kubectl apply命令進行宣告式更新。

避免將TerminationGracePeriodSeconds設定為0

TerminationGracePeriodSeconds設定為0將導致Pod立即終止,這對於StatefulSet來說是強烈不建議的。StatefulSet通常需要優雅的清理或preStop生命週期鉤子來執行。

使用指令式命令刪除物件

使用指令式命令刪除物件更可預測,且不容易出錯。宣告式刪除資源主要用於CI/CD場景中。

重點整理

  • 使用宣告式模型管理StatefulSet。
  • 避免將TerminationGracePeriodSeconds設定為0。
  • 使用指令式命令刪除物件。

DaemonSet – 在節點上維護 Pod 單例

前幾章已經解釋並演示瞭如何使用最常見的 Kubernetes 控制器來管理 Pods,例如 ReplicaSet、Deployment 和 StatefulSet。一般來說,當執行包含實際業務邏輯的雲應用程式元件時,您需要使用 Deployments 或 StatefulSets 來控制您的 Pods。在某些情況下,當您需要將批處理工作負載作為應用程式的一部分執行時,您將使用 Jobs 和 CronJobs。

然而,在某些情況下,您需要執行具有支援功能的元件,例如執行維護任務或彙總日誌和指標。更具體地說,如果您有任何需要在叢集中的每個節點上執行的任務,則可以使用 DaemonSet 來執行它們。DaemonSet 的目的是確保每個節點(除非另有指定)執行一個 Pod 副本。如果您將新的節點新增到叢集,它將自動獲得一個排程的 Pod 副本。同樣,如果您從叢集中刪除一個節點,Pod 副本將被終止 – DaemonSet 將執行所有所需的操作。

介紹 DaemonSet 物件

DaemonSet 是 Kubernetes 中的一種控制器,用於確保每個節點上執行一個 Pod 副本。它通常用於執行具有支援功能的元件,例如日誌收集、監控代理或節點級別的儲存管理。

建立和管理 DaemonSets

要建立 DaemonSet,您需要建立一個 YAML 或 JSON 檔案,定義 DaemonSet 物件。以下是一個簡單的範例:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
spec:
  selector:
    matchLabels:
      name: example-daemonset
  template:
    metadata:
      labels:
        name: example-daemonset
    spec:
      containers:
      - name: example-container
        image: example/image
        ports:
        - containerPort: 8080

程式碼解密:

此 YAML 檔案定義了一個名為 example-daemonset 的 DaemonSet 物件。它指定了一個選擇器,用於匹配具有 name: example-daemonset 標籤的 Pods。範本部分定義了要建立的 Pod 的規格,包括容器映像和連線埠。

要建立 DaemonSet,請執行以下命令:

kubectl apply -f example-daemonset.yaml

要管理 DaemonSet,您可以使用各種 kubectl 命令,例如 kubectl getkubectl describekubectl delete

DaemonSets 的常見使用案例

DaemonSets 通常用於執行具有支援功能的元件,例如:

  • 日誌收集:DaemonSet 可以用於在每個節點上執行日誌收集代理,將日誌傳送到中央日誌儲存。
  • 監控代理:DaemonSet 可以用於在每個節點上執行監控代理,收集節點和應用程式的指標。
  • 節點級別的儲存管理:DaemonSet 可以用於在每個節點上執行儲存管理代理,管理節點級別的儲存資源。

DaemonSets 的替代方案

在某些情況下,您可能不需要使用 DaemonSet。以下是一些替代方案:

  • ReplicaSet 或 Deployment:如果您需要在叢集中執行固定數量的 Pods,您可以使用 ReplicaSet 或 Deployment。
  • Job 或 CronJob:如果您需要執行批處理工作負載,您可以使用 Job 或 CronJob。

進一步閱讀

  • DaemonSet:https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
  • ReplicaSet:https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
  • Deployment:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

此圖示展示了 DaemonSet 的架構:

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 進一步閱讀

rectangle "runs" as node1
rectangle "manages" as node2

node1 --> node2

@enduml

圖示解密:

此圖示展示了一個 DaemonSet 管理三個節點上的三個 Pods。每個節點執行一個 Pod 副本,DaemonSet 負責確保每個節點上執行一個 Pod 副本。

DaemonSet:維護節點上的Pod單例

DaemonSet是Kubernetes中的一種重要資源物件,用於確保在叢集中的每個節點(Node)上執行一個Pod副本。這種機制對於需要監控、記錄、儲存管理或網路管理的應用程式至關重要。DaemonSet會自動根據叢集節點的變化調整Pod的數量,確保每個節點都有所需的Pod在執行。

介紹DaemonSet物件

DaemonSet的概念源自Unix-like作業系統中的守護程式(daemon),這些程式在背景執行,負責處理維護任務、服務網路請求或監控硬體活動。在Kubernetes中,DaemonSet確保在每個節點上執行一個Pod副本,這些Pod處理著對整個叢集至關重要的任務。

DaemonSet的主要應用場景

  • 監控:監控每個節點的健康狀態。
  • 日誌收集:收集節點和執行其上的Pod的資訊。
  • 儲存管理:處理應用程式的儲存空間請求。
  • 網路管理:提供連線性,例如kube-proxy和CNI(例如Calico)。

DaemonSet的工作原理

DaemonSet控制器會根據節點的變化動態地建立或刪除Pod。當新的節點加入叢集時,DaemonSet會自動在該節點上建立一個Pod;當節點被移除時,相關的Pod也會被清理。這種機制確保了叢集的動態管理和資源的最佳利用。

DaemonSet Pod的排程

DaemonSet保證在每個符合條件的節點上執行一個Pod。DaemonSet控制器會建立具有節點親和性規則的Pod,以確保這些Pod只會被排程到符合特定條件的節點上。預設的排程器會將Pod繫結到目標節點,如果資源不足,可能會搶佔現有的Pod。

檢查DaemonSet資源

在佈署Kubernetes叢集後,您可能已經在使用一些由Kubernetes或叢集支援元件佈署的DaemonSet,例如DNS服務或CNI。您可以使用kubectl get daemonsets -A命令檢查目前叢集中的DaemonSet資源。

$ minikube start \
--driver=virtualbox \
--nodes 3 \
--cni calico \
--cpus=2 \
--memory=2g \
--kubernetes-version=v1.31.0 \
--container-runtime=containerd

$ kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
minikube      Ready    control-plane   3m28s v1.31.0
minikube-m02 Ready    <none>          2m29s v1.31.0
minikube-m03 Ready    <none>          91s   v1.31.0

$ kubectl get daemonsets -A
NAMESPACE     NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE

DaemonSet與其他資源的比較

DaemonSet與ReplicaSet、Deployment和StatefulSet等資源物件有相似之處,都需要提供Pod範本和標籤選擇器。然而,DaemonSet主要關注在每個節點上執行一個Pod副本,這使得它在某些特定場景下非常有用。

DaemonSet Pod的通訊模式

根據使用場景,DaemonSet Pod可能需要與其他Pod或外部網路進行通訊。常見的通訊模式包括:

  • 將容器埠對映到主機埠。
  • 將資料推播到其他服務。
  • 使用無頭服務(Headless Service)匹配DaemonSet Pod標籤選擇器。
  • 使用正常服務(Normal Service)匹配DaemonSet Pod標籤選擇器。