十,StatefulSet簡介及簡單使用


StatefulSet簡介

有狀態應用副本集

為什么要用statefulset控制器

有狀態和無狀態

無狀態的, 更關注的是群體

有狀態的, 更關注的是個體

有狀態應用集的特點:

  1. 穩定且需要唯一的網絡標識符;
    • 如: Redis集群,
      在Redis集群中,它是通過槽位來存儲數據的,假如:第一個節點是01000,第二個節點是10012000,第三個節點2001~3000...等等,這就使得Redis集群中每個節點要通過ID來標識自己,如:
      第二個節點宕機了,重建后它必須還叫第二個節點,或者說第二個節點叫R2,它必須還叫R2,這樣在獲取1001~2000槽位的數據時,才能找到數據,否則Redis集群將無法找到這段數據。
  2. 穩定且持久的存儲;
    • 可實現持久存儲,新增或減少pod,存儲不會隨之發生變化。
  3. 要求有序, 平滑的部署和擴展;
    • 如 MySQL集群,要先啟動主節點, 若從節點沒有要求,則可一起啟動,若從節點有啟動順序要求,可先啟動第一個從節點,接着第二從節點等;這個過程就是有順序,平滑安全的啟動。
  4. 要求有序, 平滑的終止和刪除;
    • 我們先終止從節點,若從節點是有啟動順序的,那么關閉時,也要按照逆序終止,即啟動時是從S1~S4以此啟動,則關閉時,則是先關閉S4,然后時S3,依次關閉,最后在關閉主節點。
  5. 有序的滾動更新;
    • MySQL在更新時,應該先更新從節點,全部的從節點都更新完了,最后在更新主節點,因為新版本一般可兼容老版本,但是一定要注意,若新版本不兼容老版本就很很麻煩

statefulset的組成:

  1. headless service 用於定義網絡標識(DNS)
  2. StatefulSet 控制器,用於定義具體應用
  3. volumeClaimTemplate 存儲卷申請模板,用於創建PV

簡單測試 使用 StatefulSet

創建基礎的PV

[root@master configmap]# cat ../volume/pv-demo.yaml 
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv001
  labels:
    name: pv001
spec:
  nfs:
    path: /data/volumes/v1
    server: 172.27.1.241
  accessModes: ["ReadWriteMany", "ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv002
  labels:
    name: pv002
spec:
  nfs:
    path: /data/volumes/v2
    server: 172.27.1.241
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv003
  labels:
    name: pv003
spec:
  nfs:
    path: /data/volumes/v3
    server: 172.27.1.241
  accessModes: ["ReadWriteMany", "ReadWriteOnce"]
  capacity:
    storage: 5Gi
---
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv004
  labels:
    name: pv004
spec:
  nfs:
    path: /data/volumes/v4
    server: 172.27.1.241
  accessModes: ["ReadWriteMany", "ReadWriteOnce"]
  capacity:
    storage: 10Gi
---
apiVersion: v1
kind: PersistentVolume
metadata: 
  name: pv005
  labels:
    name: pv005
spec:
  nfs:
    path: /data/volumes/v5
    server: 172.27.1.241
  accessModes: ["ReadWriteMany", "ReadWriteOnce"]
  capacity:
    storage: 10Gi
[root@master volume]# kubectl apply -f pv-demo.yaml 
persistentvolume/pv001 created
persistentvolume/pv002 created
persistentvolume/pv003 created
persistentvolume/pv004 created
persistentvolume/pv005 created
[root@master volume]# kubectl get pv -o wide
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE   VOLUMEMODE
pv001   5Gi        RWO,RWX        Retain           Available                                   5s    Filesystem
pv002   5Gi        RWO            Retain           Available                                   5s    Filesystem
pv003   5Gi        RWO,RWX        Retain           Available                                   5s    Filesystem
pv004   10Gi       RWO,RWX        Retain           Available                                   5s    Filesystem
pv005   10Gi       RWO,RWX        Retain           Available                                   5s    Filesystem

StatefulSet 清單

[root@master manifests]# cat statefulset-demo.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
  labels:
    app: myapp                  # service 名稱
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None               # 配置headless service
  selector:
    app: myapp-pod              # 匹配Pod 標簽
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp            # 名稱
  replicas: 3                   # 三個副本
  selector:
    matchLabels:
      app: myapp-pod            # 匹配Pod 
  template:
    metadata:
      labels:
        app: myapp-pod
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: myappdata
          mountPath: /usr/shar/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: myappdata                   # pvc名稱
    spec:
      accessModes: ["ReadWriteOnce"]    # 權限
      resources:
        requests:
          storage: 5Gi                  # pv 大小

創建

[root@master manifests]# kubectl apply -f statefulset-demo.yaml 
service/myapp-svc unchanged
statefulset.apps/myapp created
[root@master manifests]# kubectl get sts
NAME    READY   AGE
myapp   3/3     5s
[root@master manifests]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
myapp-0   1/1     Running   0          92s
myapp-1   1/1     Running   0          91s
myapp-2   1/1     Running   0          32s

StatefulSet 會自動創建pvc, 然后去綁定對應符合要求的PV

[root@master manifests]# kubectl get pvc
NAME                STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myappdata-myapp-0   Bound    pv002    5Gi        RWO                           2m42s
myappdata-myapp-1   Bound    pv003    5Gi        RWO,RWX                       66s
myappdata-myapp-2   Bound    pv001    5Gi        RWO,RWX                       7s
[root@master manifests]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                       STORAGECLASS   REASON   AGE
pv001   5Gi        RWO,RWX        Retain           Bound       default/myappdata-myapp-2                           20m
pv002   5Gi        RWO            Retain           Bound       default/myappdata-myapp-0                           20m
pv003   5Gi        RWO,RWX        Retain           Bound       default/myappdata-myapp-1                           20m
pv004   10Gi       RWO,RWX        Retain           Available                                                       20m
pv005   10Gi       RWO,RWX        Retain           Available                                                       20m

statefulset管理pod的啟停順序

  • 有序部署:部署StatefulSet時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)並且,在下一個Pod運行之前所有之前的Pod必須都是Running和Ready狀態。
  • 有序刪除:當Pod被刪除時,它們被終止的順序是從N-1到0。
  • 有序擴展:當對Pod執行擴展操作時,與部署一樣,它前面的Pod必須都處於Running和Ready狀態

statefulset管理策略

  • OrderedReady:上述的啟停順序,默認設置。

    spec:
      podManagementPolicy: OrderedReady
    
  • Parallel:告訴StatefulSet控制器並行啟動或終止所有Pod,並且在啟動或終止另一個Pod之前不等待前一個Pod變為Running and Ready或完全終止。

    spec:
      podManagementPolicy: Parallel
    
擴容pod實驗(順序增加)
[root@master manifests]# kubectl scale sts myapp --replicas=5  #擴容到5個pod
[root@master manifests]# kubectl get pvc
NAME                STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myappdata-myapp-0   Bound    pv002    5Gi        RWO                           14m
myappdata-myapp-1   Bound    pv003    5Gi        RWO,RWX                       14m
myappdata-myapp-2   Bound    pv001    5Gi        RWO,RWX                       14m
myappdata-myapp-3   Bound    pv004    10Gi        RWO,RWX                       7s
myappdata-myapp-4   Bound    pv005    10i        RWO,RWX                       7s


縮減pod實驗(逆序減小,從最后的開始縮減)
[root@master manifests]# kubectl scale sts myapp --replicas=2  #縮減到2個pod
[root@master manifests]# kubectl get pvc
NAME                STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myappdata-myapp-0   Bound    pv002    5Gi        RWO                           14m
myappdata-myapp-1   Bound    pv003    5Gi        RWO,RWX                       14m

statefulSet的更新策略:

kubectl explain sts.spec.updateStrategy.rollingUpdate

partition: 這種更新策略的含義是, 若當前statefulSet的副本數為5個,則Pod名為pod-0~pod-4,那么此時定義partition=4, 就意味着我要更新大於等於4的Pod,而只有pod-4的ID 4 是大於等於4的,所以只有pod-4會被更新,其它不會,這就是金絲雀更新。若后期發現pod-4更新后,工作一切正常,那么就可以調整partition=0,這樣只要大於等於0的pod ID都將被更新。

金絲雀更新

修改滾動更新策略,查看效果

kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
#修改statefulset的image
kubectl set image sts/myapp myapp=ikubernetes/myapp:v2

#查看已經修改成功了
[root@master statfulset]# kubectl get sts myapp -o wide
NAME    READY   AGE   CONTAINERS   IMAGES
myapp   4/4     16h   myapp        ikubernetes/myapp:v2

因為策略寫的是從第二個容器開始更新

通過命令kubectl get pod myapp-1 -o yaml可以看到2之前的image沒有改變

通過命令kubectl get pod myapp-2 -o yaml可以看到2之后的image都已經改變了

#再重新把partition改為0, 則把之前的pod的image都修改生效了
kubectl patch sts myapp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}'
[root@master statfulset]# kubectl get pods -l app=myapp-pod -o custom-columns=NAME:metadata.name,IMAGE:spec.containers[0].image
NAME      IMAGE
myapp-0   ikubernetes/myapp:v2
myapp-1   ikubernetes/myapp:v2
myapp-2   ikubernetes/myapp:v2
myapp-3   ikubernetes/myapp:v2

暫存更新操作

分區更新操作
將spec.updateStrategy.rollingUpdate.partition設置為Pod副本數量時,即意味着所有Pod資源都不會處於可直接更新的分區內,直到partition小於Pod數時,才會開始更新

此時,即便刪除某Pod,也會按舊版本進行重建,即暫存狀態的更新對所有Pod資源均不產生影響

使用go-template自定義資源輸出信息

kubectl get pod myapp-1 -o go-template --template='{{.status.podIP}}'
[root@master statfulset]# kubectl get pod myapp-1 -o go-template --template='{{range .spec.containers}}{{.image}}{{end}}'
ikubernetes/myapp:v2

因為這里查看containers的image信息是一個列表信息, 所以要用到range

關於更多的go-template的使用方法, 可以參考這位老哥寫的博客: https://www.bbsmax.com/A/gAJGgjX3JZ/

訪問測試:pod_name.service.ns_name.svc.cluster.local (myapp-2.myapp.default.svc.cluster.local)


免責聲明!

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



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