K8s StatfulSet使用總結


StatefulSet:
在1.3以前K8s中StatefulSet叫PetSet(寵物集),由此也可看出StatefulSet是關注個體,而非群體。
StatefulSet要滿足以下幾點:

  • 穩定且唯一的網絡標識符;
  • 如: Redis集群, 在Redis集群中,它是通過槽位來存儲數據的,假如:第一個節點是0~1000,第二個節點是1001~2000,第三個節點2001~3000...等等,這就使得Redis集群中每個節點要通過ID來標識自己,如: 第二個節點宕機了,重建后它必須還叫第二個節點,或者說第二個節點叫R2,它必須還叫R2,這樣在獲取1001~2000槽位的數據時,才能找到數據,否則Redis集群將無法找到這段數據。
  • 穩定且持久的存儲
  • 有序、平滑的部署和擴展;如 MySQL集群,要先啟動主節點, 若從節點沒有要求,則可一起啟動,若從節點有啟動順序要求,可先啟動第一個從節點,接着第二從節點等;這個過程就是有順序,平滑安全的啟動。
  • 有序、平滑的終止和刪除;即: 我們先終止從節點,若從節點是有啟動順序的,那么關閉時,也要按照逆序終止,即啟動時是從S1~S4以此啟動,則關閉時,則是先關閉S4,然后時S3,依次關閉,最后在關閉主節點。
  • 有序的滾動更新;如: MySQL在更新時,應該先更新從節點,全部的從節點都更新完了,最后在更新主節點,因為新版本一般可兼容老版本,但是一定要注意,若新版本不兼容老版本就很很麻煩!
創建一個StatefulSet控制器的示例:
vim  pod-statefulset.yaml
apiVersion: v1
kind: Service
metadata:
 name: myapp
 labels:
   app: myapp
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp
  replicas: 3
    selector:
       matchLabels:
          app: myapp-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/share/nginx/html
  volumeClaimTemplates:
  #注意: 它是statefulset.spec.volumeClaimTemplates.
  -  metadata:
       name: myappdata
     spec:
       accessModes:  ["ReadWriteOnce"]                                                                
       #storageClassName: “gluster-dynamic”  #這是定義存儲類的。
       resources:
         requests:
            storage: 2Gi

#實驗中問題總結:
accessModes: [ “ReadWriteOnce” ]
  #這里需要注意: 你指定模式為RWO,那么你使用kubectl get pv時,必須有RWO權限的pv,因為本例是要創建3個StatefulSet的Pod,因此就需要3個RWO權限的pv,但我測試時,就只有一個pv是RWO的,因此導致創建Pod一直處於Pending狀態,而且只有一個! 使用kubectl describe pvc PVC_NAME 查看時提示: no persistent volumes available for this claim and no storage class is set(此聲明沒有可用持久卷,也沒有存儲類),其實問題已經說的很白了,但沒有經驗,所以這點要特別注意!!
  #第二個問題: 我后來新增了3個RWO權限的pv,但在NFS上,忘記創建對應的目錄了,使用exportfs -avr 也提示了,目錄沒有找到,但我沒仔細看,結果導致我創建Pod時,一直處於ContainerCreating,查看kubectl describe pod myapp-0 看到mount.nfs: mounting 192.168.111.83:/data/volumes/v6 failed, reason given by server: No such file or directory 這樣的錯誤,最后才想到可能是目錄沒有創建。
  #第三個問題:我在創建PV時,使用的是k8s集群外部的域名nfs.zcf.com 來指定NFS Server是誰,但我K8s集群內還不能解析集群外域名,也導致了訪問超時的問題。
  #第四個問題:創建serive時總提示ClusterIP是無效值:
  解決步驟:
    1. 檢查配置清單中clusterIP是否有寫錯.
    2. 檢查是否有service同名沖突:
      kubectl get svc

#創建statefulset:
#執行創建statefulSet前,需要先手動創建出符合條件的PV,若你已經實現了動態供給存儲卷,
#則可不用手動事先創建好PV。
  kubectl apply -f pod-statefulset.yaml

#查看:
  kubectl get svc
  kubectl get [statefulset |sts]
  kubectl get pvc    #volumeClaimTemplates可動態創建Pod內部的PVC,然后再創建名稱空間級的PVC
注:
    Pod內容器掛載PV的過程 或 層級是這樣的:
  容器要掛載網絡磁盤---->Pod中要有對應的PVC---->Pod所在的名稱空間中要有對於的PVC----->
  K8s集群中要有對應的PV---->要有輸出共享存儲的后端服務器上的共享空間
  而volumeClaimTemplates它可自動創建Pod 和 名稱空間中的PVC。
  kubectl get pv
  kubectl get pods

  

終端2:
 kubectl  get  pods  -w

終端1:
 kubectl  delete  -f  pod-statefulset.yaml          #刪除后,查看終端2上,刪除Pod的順序是否為先刪除2,10
    #在k8s 1.13.5中測試時,發現:
    #  刪除時,似乎沒有順序:
    kubect  get  pod  -w   -l  app=myapp-pod
        myapp-1   1/1   Terminating   0     31s
        myapp-0   1/1   Terminating   0     34s
        myapp-2   1/1   Terminating   0     28s
        myapp-1   0/1   Terminating   0     33s
        myapp-2   0/1   Terminating   0     31s
        myapp-0   0/1   Terminating   0     37s
        myapp-1   0/1   Terminating   0     41s
        myapp-1   0/1   Terminating   0     41s
        myapp-0   0/1   Terminating   0     47s
        myapp-0   0/1   Terminating   0     47s
        myapp-2   0/1   Terminating   0     41s
        myapp-2   0/1   Terminating   0     41s
                        
終端1:
 kubectl   apply  -f   pod-statefulset.yaml   #查看創建Pod的過程是否為先0,12
   #此測試是正常的:
    myapp-0   0/1   Pending   0     0s
    myapp-0   0/1   Pending   0     0s
    myapp-0   0/1   ContainerCreating   0     0s
    myapp-0   1/1   Running   0     3s
    myapp-1   0/1   Pending   0     0s
    myapp-1   0/1   Pending   0     0s
    myapp-1   0/1   ContainerCreating   0     0s
    myapp-1   1/1   Running   0     3s
    myapp-2   0/1   Pending   0     0s
    myapp-2   0/1   Pending   0     0s
    myapp-2   0/1   ContainerCreating   0     0s
    myapp-2   1/1   Running   0     2s


 kubectl  describe  pods  myapp-2  #查看myapp-2是否依然綁定PV-2,而且當你刪除pod后,kubectl  get  pv,也會發現,Retain策略是不會釋放綁定關系的.
 
#statefulSet的域名結構為:
pod_name.service_name.namespace_name.svc.cluster.local
如:
    上例中創建了三個Pod,其中一個叫myapp-0
    myapp-0.myapp.default.svc.cluster.local

#對statefulSet做擴縮容:
#擴容:
  kubectl  scale  sts  myapp  --replicas=5
    #注意:
    #   在定義StatefulSet時,Pod的模板中指定自動創建pvc,並關聯可用PV時,選擇可用大小為1Gi,我期望時,它自動關聯時,選擇最匹配的,但事實似乎並非如此。
    #   查看
    # kubectl get pv
    NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                       STORAGECLASS   REASON   AGE
    pv01   1Gi        RWO,RWX        Retain           Available                                                       87m
    pv02   2Gi        ROX,RWX        Retain           Bound       default/myappdata-myapp-3                           87m
    pv03   5Gi        ROX,RWX        Retain           Bound       default/myappdata-myapp-4                           87m      #明明有一個1Gi的,它沒有選擇,而是選擇了5Gi的
    pv04   10Gi       ROX,RWX        Retain           Available                                                       87m
    pv05   20Gi       ROX,RWX        Retain           Available                                                       87m
    pv06   1Gi        ROX,RWX        Retain           Bound       default/myappdata-myapp-0                           87m
    pv07   1Gi        ROX,RWX        Retain           Bound       default/myappdata-myapp-1                           87m
    pv08   2Gi        ROX,RWX        Retain           Bound       default/myappdata-myapp-2                           87m
            

終端2:
    kubectl  get  pods  -w          #當執行擴容Pod后, 會看到先創建myapp-3,然后是myapp-4

#縮容:
    kubectl  patch  sts  myapp  -p  ‘{"spec":{"replicas":2}}’

終端2:
    kubectl  get  pods  -w          #依然查看其縮容的過程,在縮容時,竟然是按順序的,432
    myapp-4   1/1   Terminating   0     5m41s
    myapp-4   0/1   Terminating   0     5m43s
    myapp-4   0/1   Terminating   0     5m53s
    myapp-4   0/1   Terminating   0     5m53s
    myapp-3   1/1   Terminating   0     5m56s
    myapp-3   0/1   Terminating   0     5m57s
    myapp-3   0/1   Terminating   0     5m58s
    myapp-3   0/1   Terminating   0     5m58s
    myapp-2   1/1   Terminating   0     8m41s
    myapp-2   0/1   Terminating   0     8m43s
    myapp-2   0/1   Terminating   0     8m49s

#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":4}}}}’
     #注:
        在打補丁時,若對象為list類型,則需要使用"[]",來指明其下標,如: containers[0],就是第一個容器.

kubectl  describe  sts  myapp      #查看其滾動更新策略中partition的值是否修改為4了。
#在k8s 1.13.5中查看如下:
    .......
    Replicas:           824638453880 desired | 5 total
    Update Strategy:    RollingUpdate
      Partition:        824638454284
    .......
 #但通過kubectl  get  sts  myapp  -o  yaml  查看,就可以看到,已經修改為4了。
    .........
      updateStrategy:
        rollingUpdate:
          partition: 4
        type: RollingUpdate
   .......

  #以上statefulSet的更新策略已經修改好了,接着來修改pod的鏡像為新版鏡像,來查看其滾動更新的
  kubectl set image sts/myapp myapp=ikubernetes/myapp:v2

#查看:
  kubectl get sts -o wide    #查看statefulSet控制器層面的容器鏡像是否修改成功了。

  kubectl get pods myapp-4 -o yaml    #查看statefulSet控制器下myapp-4這個容器的state(當前運行狀態信息)中image是否修改成功了.
  kubectl get pods myapp-3 -o yaml    #查看其image應該是沒有改變的

終端2:
  kubectl get pods -w    #當修改更新策略后,這里將可以看到滾動更新的效果了。

終端1:
  kubectl patch sts myapp -p ‘{"spec":{"updateStrategy":{"rollingUpdate":{"partition":0}}}}’
  #由於上面已經跟新了鏡像,當這里修改了更新策略后,馬上就會觸發滾動更新!! 需要注意!!
  注意:
    statefulSet在實際使用中還是需要謹慎!

附上一張PVC和PV的關系圖:

  

 

另外,最好的學習平台是githup,它上面有很多別人做好的清單文件,可作為學習的參考。

 


免責聲明!

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



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