kubernetes之StatefulSet詳解
RC、Deployment、DaemonSetStatefulSet都是面向無狀態的服務,它們所管理的Pod的IP、名字,啟停順序等都是隨機的,而StatefulSet是什麽?顧名思義,有狀態的集合,管理所有有狀態的服務,比如MySQL、MongoDB集群等。
StatefulSet本質上是Deployment的一種變體,它是t是為了解決有狀態服務的問題,它所管理的Pod擁有固定的Pod名稱,啟停順序,在StatefulSet中,Pod名字稱為網絡標識,還必須要用到共享存儲,在v1.9版本中已成為GA版本。
在Deployment中,與之對應的服務是service,而在StatefulSet中與之對應的headless service,headless service,即無頭服務,與service的區別就是它沒有Cluster IP,解析它的名稱時將返回該Headless Service對應的全部Pod的Endpoint列表。
$(podname).(headless server name)
FQDN: $(podname).(headless server name).namespace.svc.cluster.local
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: selector: matchLabels: app: nginx # has to match .spec.template.metadata.labels serviceName: "nginx" #聲明它屬於哪個Headless Service. replicas: 3 # by default is 1 template: metadata: labels: app: nginx # has to match .spec.selector.matchLabels spec: terminationGracePeriodSeconds: 10 containers: - name: nginx image: k8s.gcr.io/nginx-slim:0.8 ports: - containerPort: 80 name: web volumeMounts: - name: www mountPath: /usr/share/nginx/html volumeClaimTemplates: #可看作pvc的模板 - metadata: name: www spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "gluster-heketi" #存儲類名,改為集群中已存在的 resources: requests: storage: 1Gi
通過該配置文件,可看出StatefulSet的組成部分:
- Headless Service,名為nginx,用來定義Pod網絡標識( DNS domain)。
- StatefulSet,定義具體應的,名為Nginx,有三個Pod副本,並為每個Pod定義了一個域名。
- volumeClaimTemplates,名為www,pvc模板,指定pvc名稱大小,將自動創建pvc,且pvc必須由存儲類供應。
$ kubectl create -f nginx.yaml
service "nginx" created
statefulset "web" created
看下這三個Pod創建過程:
#第一個是創建web-0 $ kubectl get pod web-0 1/1 ContainerCreating 0 51s #待web-0 running且ready時,創建web-1 $ kubectl get pod web-0 1/1 Running 0 51s web-1 0/1 ContainerCreating 0 42s #待web-1 running且ready時,啟動web-2 $ kubectl get pod web-0 1/1 Running 0 1m web-1 1/1 Running 0 45s web-2 1/1 ContainerCreating 0 36s #最後三個Pod全部running且ready $ kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 4m web-1 1/1 Running 0 3m web-2 1/1 Running 0 1m
Statefulset 名稱:web 三個副本
創建出來的Pod: web-0,web-1,web-2
volumeClaimTemplates名稱為:www,那麽自動創建出來的PVC名稱為www-web[0-2],為每個Pod創建一個PVC。
#根據volumeClaimTemplates自動創建的PVC
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-ecf003f3-828d-11e8-8815-000c29774d39 2G RWO gluster-heketi 7m
www-web-1 Bound pvc-0615e33e-828e-11e8-8815-000c29774d39 2G RWO gluster-heketi 6m
www-web-2 Bound pvc-43a97acf-828e-11e8-8815-000c29774d39 2G RWO gluster-heketi 4m
規律總結:
- 匹配Pod name(網絡標識)的模式為:$(statefulset名稱)-$(序號),比如上面的示例:web-0,web-1,web-2。
- StatefulSet為每個Pod副本創建了一個DNS域名,這個域名的格式為: $(podname).(headless server name)
- StatefulSet使用Headless服務來控制Pod的域名,這個域名的FQDN為:$(service name).$(namespace).svc.cluster.local,其中,“cluster.local”指的是集群的域名。
- 根據volumeClaimTemplates,為每個Pod創建一個pvc,pvc匹配模式為:(volume_name)-(pod_name),
比如上面的volumeMounts.name=www, Pod name=web-[0-2],因此創建出來的PVC是www-web-0、www-web-1、www-web-2。 - 刪除Pod不會刪除其pvc,刪除pvc將自動釋放pv。
Statefulset的啟停順序:
通常上面的示例發現:
- 有序部署:部署StatefulSet時,如果有多個Pod副本,它們會被順序地創建(從0到N-1)。
- 有序刪除:當Pod被刪除時,它們被終止的順序是從N-1到0。
- 有序擴展:當對Pod執行擴展操作時,與部署一樣,它前面的Pod必須都處於Running和Ready狀態。
Statefulset Pod管理策略:
在v1.7以後,通過允許修改Pod排序策略,同時通過.spec.podManagementPolicy字段確保其身份的唯一性。
OrderedReady: 上述的啟停順序,默認設置。
Parallel: 告訴StatefulSet控制器並行啟動或終止所有Pod,並且在啟動或終止另一個Pod之前不等待前一個Pod變為Running and Ready或完全終止。
更新策略
在Kubernetes 1.7及更高版本中,通過.spec.updateStrategy字段允許配置或禁用Pod、labels、esource request/limits、annotations自動滾動更新功能。
OnDelete:通過.spec.updateStrategy.type 字段設置為OnDelete,StatefulSet控制器不會自動更新StatefulSet中的Pod。用戶必須手動刪除Pod,以使控制器創建新的Pod
RollingUpdate:通過.spec.updateStrategy.type 字段設置為RollingUpdate,實現了Pod的自動滾動更新,如果.spec.updateStrategy未指定,則此為默認策略。
StatefulSet控制器將刪除並重新創建StatefulSet中的每個Pod。它將以Pod終止(從最大序數到最小序數)的順序進行,一次更新每個Pod。在更新下一個Pod之前,必須等待這個Pod Running and Ready。
Partitions:通過指定 .spec.updateStrategy.rollingUpdate.partition 來對 RollingUpdate 更新策略進行分區,如果指定了分區,則當 StatefulSet 的 .spec.template 更新時,具有大於或等於分區序數的所有 Pod 將被更新。
具有小於分區的序數的所有 Pod 將不會被更新,即使刪除它們也將被重新創建。如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大於其 .spec.replicas,則其 .spec.template 的更新將不會傳播到 Pod。
在大多數情況下,不需要使用分區。
kubernetes之StatefulSet詳解