Kubernetes中StatefulSet介紹


StatefulSet 是Kubernetes1.9版本中穩定的特性,本文使用的環境為 Kubernetes 1.11。如何搭建環境可以參考kubeadm安裝kubernetes V1.11.1 集群

0. 介紹

使用Kubernetes來調度無狀態的應用非常簡單,那Kubernetes如何來管理調度有狀態的應用呢?Kubernetes中提供了一個StatefulSet控制器來管理有狀態的應用,本文就介紹StatefulSet的應用,解決以下幾個問題:

  • 如何創建StatefulSet
  • StatefulSet如何管理Pods
  • 如何刪除StatefulSet
  • 如何對StatefulSet進行擴容
  • 如何更新StatefulSet中的Pods

1. StatefulSet 是什么

StatefulSet是Kubernetes提供的管理有狀態應用的負載管理控制器API。在Pods管理的基礎上,保證Pods的順序和一致性。與Deployment一樣,StatefulSet也是使用容器的Spec來創建Pod,與之不同StatefulSet創建的Pods在生命周期中會保持持久的標記(例如Pod Name)。

StatefulSet適用於具有以下特點的應用:

  • 具有固定的網絡標記(主機名)
  • 具有持久化存儲
  • 需要按順序部署和擴展
  • 需要按順序終止及刪除
  • 需要按順序滾動更新

2. StatefulSet 創建

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
     matchLabels:
       app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: docker.io/nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      volumeMode: Filesystem
      resources:
        requests:
          storage: 50Mi
      storageClassName: local-storage

StatefulSet創建順序是從0到N-1,終止順序則是相反。如果需要對StatefulSet擴容,則之前的N個Pod必須已經存在。如果要終止一個Pod,則它的后序Pod必須全部終止。

If web-0 should fail, after web-1 is Running and Ready, but before web-2 is launched, web-2 will not be launched until web-0 is successfully relaunched and becomes Running and Ready.

在Kubernetes 1.7版本后,放松了順序的保證策略,對應的參數為 .spec.podManagementPolicy

執行創建命令,並且觀察對象是否正常創建。

[root@devops-101 ~]# kubectl create -f ss-nginx.yml 
service "nginx" created
statefulset "web" created
[root@devops-101 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   9d
nginx        ClusterIP   None         <none>        80/TCP    1d
[root@devops-101 ~]# kubectl get statefulset 
NAME      DESIRED   CURRENT   AGE
web       2         2         1d

看一下Pod是否是有順序的

[root@devops-101 ~]# kubectl get pods -l app=nginx
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          11m
web-1     1/1       Running   0          11m

根據Pod的順序,每個Pod擁有對應的主機名,在Pod中執行hostname命令確認下。

[root@devops-101 ~]# for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1

使用帶有nslookup命令的busybox鏡像啟動一個Pod,檢查集群內的DNS地址設置。

3. 擴縮容

將Pod實例擴充到5個。

[root@devops-101 ~]# kubectl scale sts web --replicas=5
statefulset.apps/web scaled
[root@devops-101 ~]# kubectl get pods -w
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          5m
web-1     1/1       Running   0          5m
web-2     0/1       Pending   0         1s
web-2     0/1       Pending   0         1s

因為我的集群PV不是動態供給的,所以擴容停留在等待PV的階段,本文要按照后面的辦法手工創建相應的PV。

將實例減少到2個。

[root@devops-101 ~]# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          24m
web-1     1/1       Running   0          23m
web-2     1/1       Running   0          18m
web-3     1/1       Running   0          10m
web-4     1/1       Running   0          6m
[root@devops-101 ~]# kubectl patch sts web -p '{"spec":{"replicas":2}}'
statefulset.apps/web patched

4. 更新策略

4.1 滾動更新

默認的更新策略,以相反的順序依次更新Pod

4.2 Partition

4.3 金絲雀發布 Canary

金絲雀發布。

5. 刪除 StatefulSet

StatefulSet支持級連刪除和非級連刪除,在非級連刪除模式下,僅刪除StatefulSet不刪除Pod,級連刪除則全部刪除。

非級連刪除StatefulSet后,如果刪除Pod,就不會重新拉起原來的Pod,而是新建一個Pod。但是如果重新創建StatefulSet,則會對現有的Pod按照規則進行重新整理。

一些分布式系統,並不希望按照順序來管理啟停Pod,因此在1.7版本之后,提供了.spec.podManagementPolicy這個參數,默認為OrderedReady,可以設置為Parallel這樣Pod的創建就不必等待,而是會同時創建、同時刪除。

X. 坑

官方的文檔沒有創建PVC對應的PV,按照官方文檔操作創建后會遇到下面的錯誤,需要提前創建PV及PVC。關於存儲的更詳細的內容,可以參考Kubernetes 存儲系統 Storage 介紹

pod has unbound PersistentVolumeClaims

官方文檔里解釋了,因為他所用的集群配置為動態提供PV,所以不用手工創建。

As the cluster used in this tutorial is configured to dynamically provision PersistentVolumes, the PersistentVolumes were created and bound automatically.

PV的創建腳本如下:

kind: List
apiVersion: v1
items:
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: es-storage-pv-01
  spec:
    capacity:
      storage: 100Mi
    volumeMode: Filesystem
    accessModes: ["ReadWriteOnce"]
    persistentVolumeReclaimPolicy: Delete
    storageClassName: local-storage
    local:
      path: /home/es
    nodeAffinity:
      required:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - devops-102
            - devops-103
- apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: es-storage-pv-02
  spec:
    capacity:
      storage: 100Mi
    volumeMode: Filesystem
    accessModes: ["ReadWriteOnce"]
    persistentVolumeReclaimPolicy: Delete
    storageClassName: local-storage
    local:
      path: /home/es01
    nodeAffinity:
      required:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - devops-102
            - devops-103

參考資料

  1. StatefulSet Basics
  2. DNS for Services and Pods
  3. Services
  4. Persistent Volumes
  5. PersistentVolume Provisioning
  6. StatefulSet Concept


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM