入門Kubernetes-StatefulSets

chaney1992發表於2021-08-22

前言:

 前面文中對通過DaemonSet、儲存資源物件,實現了在指定節點中執行一個守護程式。

 在真實的業務場景中,部署的服務都是有狀態的、且有資料需要持久化的;那麼如何實現呢?

 那麼接下來學習一種更加重要的資源——StatefulSets。

一、StatefulSets 介紹

  StatefulSet 是用來管理有狀態應用的工作負載 API 物件。

  StatefulSet 用來管理某 Pod 集合的部署和擴縮, 併為這些 Pod 提供持久儲存和持久識別符號。

  與Deployment 類似,StatefulSet 管理基於相同容器規約的一組 Pod。但和 Deployment 不同的是,StatefulSet 為它們的每個 Pod 維護了一個有粘性的ID。這些 Pod 是基於相同的規約來建立的,但是不能相互替換:無論怎麼排程,每個 Pod 都有一個永久不變的 ID。

  如果希望使用儲存卷為工作負載提供持久儲存,可以使用 StatefulSet 作為解決方案的一部分。 儘管 StatefulSet 中的單個 Pod 仍可能出現故障, 但持久的 Pod 識別符號使得將現有卷與替換已失敗 Pod 的新 Pod 相匹配變得更加容易。

 應用場景:

· StatefulSets 對於需要滿足以下一個或多個需求的應用程式很有價值:

  • 穩定的、唯一的網路識別符號。
  • 穩定的、持久的儲存。
  • 有序的、優雅的部署和縮放。
  • 有序的、自動的滾動更新。

 使用限制:

  • 給定 Pod 的儲存必須由 PersistentVolume 驅動 基於所請求的 storage class 來提供,或者由管理員預先提供。
  • 刪除或者收縮 StatefulSet 並不會刪除它關聯的儲存卷。 這樣做是為了保證資料安全,它通常比自動清除 StatefulSet 所有相關的資源更有價值。
  • StatefulSet 當前需要無頭服務 來負責 Pod 的網路標識。你需要負責建立此服務。
  • 當刪除 StatefulSets 時,StatefulSet 不提供任何終止 Pod 的保證。 為了實現 StatefulSet 中的 Pod 可以有序地且體面地終止,可以在刪除之前將 StatefulSet 縮放為 0。
  • 在預設 Pod 管理策略(OrderedReady) 時使用 滾動更新,可能進入需要人工干預 才能修復的損壞狀態

二、StatefulSets使用方式

  • 建立StatefulSets

   建立StatefulSets的yaml格式:

apiVersion: apps/v1
kind: StatefulSet #StatefulSet型別
metadata:
  name: web #StatefulSet 名稱
spec:
  #service名稱
  serviceName: "nginx"
  #Pod數量
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  #Pod定義
  template:
    metadata:
      labels:
        app: nginx
    spec:
      #容器設定
      containers:
        - name: nginx
          #映象名稱
          image: nginx:1.9.6
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            #持久化儲存名稱
            - name: www
              mountPath: /usr/share/nginx/html
  #持久化儲存定義
  volumeClaimTemplates:
    - metadata:
        #名稱
        name: www
      spec:
        #訪問方式
        accessModes: ["ReadWriteOnce"]
        #資源定義
        resources:
          requests:
            storage: 1Gi

  應用該yaml後Pod建立順序如下:

>>kubectl apply -f web.yaml
service/nginx created
statefulset apps/web created

>>kubectl get pods -w -l app=nginx NAME READY STATUS RESTARTS AGE web-0 0/1 Pending 0 0s web-0 0/1 Pending 0 0s web-0 0/1 ContainerCreating 0 1s web-0 1/1 Running 0 3s web-1 0/1 Pending 0 0s web-1 0/1 Pending 0 0s web-1 0/1 ContainerCreating 0 0s web-1 1/1 Running 0 2s

  可見:StatefulSets中Pod順序建立成功。  

  再檢視下Nginx中持久化儲存資源:

kubectl get pvc -l app=nginx
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pvc-c431e9d6-0dba-4c1d-ba83-b9f1d5b8824a   1Gi        RWO            standard       137m
www-web-1   Bound    pvc-58070d7f-9fec-4e28-b77b-b15fdf30c965   1Gi        RWO            standard       124m
  • 擴容/縮容StatefulSets

   StatefulSet策略:

    • 對於包含 N 個 副本的 StatefulSet,當部署 Pod 時,它們是依次建立的,順序為 0..N-1
    • 當刪除 Pod 時,它們是逆序終止的,順序為 N-1..0
    • 在將縮放操作應用到 Pod 之前,它前面的所有 Pod 必須是 Running 和 Ready 狀態。
    • 在 Pod 終止之前,所有的繼任者必須完全關閉。

    擴容:StatefulSet 按序號索引順序的建立每個 Pod,並且會等待前一個 Pod 變為 Running 和 Ready 才會啟動下一個 Pod

#擴容Pod數量為4
>>kubectl scale sts web --replicas=4
statefulset.apps/web scaled

#檢視pod變化
>>kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          53m
web-1   1/1     Running   0          53m
web-2   0/1     Pending   0          0s
web-2   0/1     Pending   0          0s
web-2   0/1     Pending   0          3s
web-2   0/1     ContainerCreating   0          3s
web-2   1/1     Running             0          6s
web-3   0/1     Pending             0          0s
web-3   0/1     Pending             0          0s
web-3   0/1     Pending             0          2s
web-3   0/1     ContainerCreating   0          2s
web-3   1/1     Running             0          4s    

    縮容:會按照與 Pod 序號索引相反的順序每次刪除一個 Pod。在刪除下一個 Pod 前會等待上一個被完全關閉

#縮容為2個pod
>>kubectl scale -n default statefulset web --replicas=2

#檢視Pod變化:
>>kubectl get pods -w -l app=nginx
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          59m
web-1   1/1     Running   0          59m
web-2   1/1     Running   0          4m30s
web-3   1/1     Running   0          4m24s
web-3   1/1     Terminating   0          7m23s
web-3   0/1     Terminating   0          7m24s
web-3   0/1     Terminating   0          7m25s
web-3   0/1     Terminating   0          7m25s
web-2   1/1     Terminating   0          7m31s
web-2   0/1     Terminating   0          7m32s
web-2   0/1     Terminating   0          7m33s
web-2   0/1     Terminating   0          7m33s

   注意:擴容時會根據設定自動建立久化儲存資源(PVC)並關聯到Pod,當縮容時,PVC不會同步刪除。當再次擴容時;會自動繫結到之前的PVC上。   

  • StatefulSets更新策略

   更新策略由 StatefulSet API Object 的spec.updateStrategy 欄位決定。這個特效能夠用來更新一個 StatefulSet 中的 Pod 的 container images,resource requests,以及 limits,labels 和 annotations。 RollingUpdate滾動更新是 StatefulSets 預設策略。

   OnDelete:當 StatefulSet 的 .spec.updateStrategy.type 設定為 OnDelete 時,它的控制器將不會自動更新 StatefulSet 中的 Pod。 使用者必須手動刪除 Pod 以便讓控制器建立新的 Pod,以此來對 StatefulSet 的 .spec.template 的變動作出反應

   滾動更新:RollingUpdate 更新策略對 StatefulSet 中的 Pod 執行自動的滾動更新。 在沒有宣告 .spec.updateStrategy 時,RollingUpdate 是預設配置。 當 StatefulSet 的 .spec.updateStrategy.type 被設定為 RollingUpdate 時, StatefulSet 控制器會刪除和重建 StatefulSet 中的每個 Pod。 它將按照與 Pod 終止相同的順序(從最大序號到最小序號)進行,每次更新一個 Pod。 它會等到被更新的 Pod 進入 Running 和 Ready 狀態,然後再更新前一個

  • StatefulSets刪除

   StatefulSet 同時支援級聯和非級聯刪除。使用非級聯方式刪除 StatefulSet 時,StatefulSet 的 Pod 不會被刪除。使用級聯刪除時,StatefulSet 和它的 Pod 都會被刪除。

   StatefulSet 永遠不會刪除和一個 Pod 相關聯的 PersistentVolumes。 當你重建這個 StatefulSet 並且重新啟動了Pod時,它原本的 PersistentVolume 會被重新掛載

   非級聯刪除:Pod不會刪除

#非級聯刪除statefulset
kubectl delete statefulset web --cascade=orphan

    檢視狀態:Pod資訊,所有Pod依舊執行

   級聯刪除:StatefulSet 和它的 Pod 都會被刪除

#級聯刪除
kubectl delete statefulset web

    檢視狀態:Pod逐步從Pod1->Pod0刪除      

三、總結

  StatefulSet 是一種較常用的資源型別,能夠穩定、有序的部署和擴縮Pod集合, 併為這些 Pod 提供持久儲存和持久識別符號。