目錄html
RC、Deployment、DaemonSet都是面向無狀態的服務,它們所管理的Pod的IP、名字,啓停順序等都是隨機的,而StatefulSet是什麼?顧名思義,有狀態的集合,管理全部有狀態的服務,好比MySQL、MongoDB集羣等。 StatefulSet本質上是Deployment的一種變體,在v1.9版本中已成爲GA版本,它爲了解決有狀態服務的問題,它所管理的Pod擁有固定的Pod名稱,啓停順序,在StatefulSet中,Pod名字稱爲網絡標識(hostname),還必需要用到共享存儲。 在Deployment中,與之對應的服務是service,而在StatefulSet中與之對應的headless service,headless service,即無頭服務,與service的區別就是它沒有Cluster IP,解析它的名稱時將返回該Headless Service對應的所有Pod的Endpoint列表。 除此以外,StatefulSet在Headless Service的基礎上又爲StatefulSet控制的每一個Pod副本建立了一個DNS域名,這個域名的格式爲: |
$(podname).(headless server name) FQDN: $(podname).(headless server name).namespace.svc.cluster.local
穩定且惟一的網絡標識符;nginx
如: Redis集羣, 在Redis集羣中,它是經過槽位來存儲數據的,假如:第一個節點是0~1000,第二個節點是1001~2000,第三個節點2001~3000...等等,這就使得Redis集羣中每一個節點要經過ID來標識本身,如: 第二個節點宕機了,重建後它必須還叫第二個節點,或者說第二個節點叫R2,它必須還叫R2,這樣在獲取1001~2000槽位的數據時,才能找到數據,不然Redis集羣將沒法找到這段數據。web
穩定且持久的存儲api
有序、平滑的部署和擴展安全
如 MySQL集羣,要先啓動主節點, 若從節點沒有要求,則可一塊兒啓動,若從節點有啓動順序要求,可先啓動第一個從節點,接着第二從節點等;這個過程就是有順序,平滑安全的啓動。網絡
有序、平滑的終止和刪除app
即: 咱們先終止從節點,若從節點是有啓動順序的,那麼關閉時,也要按照逆序終止,即啓動時是從S1~S4以此啓動,則關閉時,則是先關閉S4,而後時S3,依次關閉,最後在關閉主節點。less
有序的滾動更新ide
MySQL在更新時,應該先更新從節點,所有的從節點都更新完了,最後在更新主節點,由於新版本通常可兼容老版本,可是必定要注意,若新版本不兼容老版本就很很麻煩spa
apiVersion: v1 kind: Service metadata: name: myapp-sts labels: app: myapp-sts spec: ports: - port: 80 name: web clusterIP: "None" selector: app: myapp-pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp spec: serviceName: myapp-sts #聲明它屬於哪一個Headless Service. replicas: 2 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: - metadata: name: myappdata spec: accessModes: ["ReadWriteOnce"] #storageClassName: "rook-ceph-block" resources: requests: storage: 1Gi
能夠正確解析到ip
[root@master statfulset]# nslookup myapp-1.myapp-sts.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: myapp-1.myapp-sts.default.svc.cluster.local Address: 10.244.1.30 [root@master statfulset]# nslookup myapp-0.myapp-sts.default.svc.cluster.local 10.96.0.10 Server: 10.96.0.10 Address: 10.96.0.10#53 Name: myapp-0.myapp-sts.default.svc.cluster.local Address: 10.244.1.29
#擴容至三個pod kubectl scale sts myapp --replicas=3 #而後從新縮容至兩個pod kubectl scale sts myapp --replicas=2
擴容當中出現了一個問題, 新建立的pod處於pending狀態, describe看到是mount的問題, 原來是以前pod掛載的pv變成了released狀態, 並無變成available狀態, 通過查找發現最關鍵的是PV的
spec.claimRef
字段,該字段記錄着原來PVC的綁定信息,刪除綁定信息,便可從新釋放PV從而達到Available。
OrderedReady:上述的啓停順序,默認設置。
spec: podManagementPolicy: OrderedReady
Parallel:告訴StatefulSet控制器並行啓動或終止全部Pod,而且在啓動或終止另外一個Pod以前不等待前一個Pod變爲Running and Ready或徹底終止。
spec: podManagementPolicy: Parallel
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/
https://www.cnblogs.com/wn1m/p/11289079.html
https://www.cnblogs.com/tylerzhou/p/11027559.html
https://www.cnblogs.com/xzkzzz/p/9871837.html
https://pdf.us/2019/03/15/3013.html