1,什麼是StatefulSet ?
StatefulSet又叫PetSet(以前的名稱),它和RS,RC,Deployment等同樣,都是pod控制器。
StatefulSet是爲了解決有狀態服務的問題(對應於deoloyment和RS,RC,ReplicaSet都是爲無狀態服務而設計的)。html
什麼是無狀態服務?
在生產環境中,pod的名稱是隨機的,擴縮容的是時候沒有規律,每個pod均可以被新生成的pod代替。nginx
2,StatefulSet的應用場景包括:web
從上面的引用場景能夠發現,statefulset由如下幾個部分組成:
1)headless Service:無頭服務。用來定義pod的網絡標識的(域名解析)。
2)statefulSet:定義具體的應用
3)volumeClaimTemplate:該模板自動爲每個pod建立pvc。vim
對比無狀態服務,總結StatefulSet特色:pod的名稱不變,每一個副本啓停有順序,持久化存儲,每一個pod中的數據不一樣,根據定義的模板自動建立pvc。api
3,接下來經過例子來實踐statefulset資源的使用
部署nginx服務,經過storage class和statefulset實現有狀態服務的數據持久化及其餘操做。安全
操做流程以下: 1)經過nfs服務部署storage class(建立pv) 2)建立statefulset資源對象(建立pvc) 3)測試數據持久化 4)replicas擴容與縮容 5)分區更新
1)經過nfs部署storage class
如下直接進行部署,具體信息及參數解釋請參考上章博文 k8s之StatefulSet
#開啓nfs:服務器
[root@master yaml]# yum -y install nfs-utils [root@master yaml]# vim /etc/exports /nfsdata *(rw,sync,no_root_squash) [root@master yaml]# mkdir /nfsdata [root@master yaml]# systemctl start rpcbind [root@master yaml]# systemctl start nfs-server [root@master yaml]# systemctl enable nfs-server [root@master yaml]# showmount -e Export list for master: /nfsdata *
#建立rbac權限:網絡
[root@master yaml]# vim rbac-rolebind.yaml apiVersion: v1 kind: ServiceAccount metadata: name: nfs-provisioner namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-provisioner-runner namespace: default rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["watch", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "endpoints"] verbs: ["get","create","list", "watch","update"] - apiGroups: ["extensions"] resources: ["podsecuritypolicies"] resourceNames: ["nfs-provisioner"] verbs: ["use"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io
運行yaml文件。
#建立nfs-Deployment:app
[root@master yaml]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-client-provisioner namespace: default spec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs-deploy #供給方的名稱(自定義) - name: NFS_SERVER value: 172.16.1.30 #nfs服務器的ip地址 - name: NFS_PATH value: /nfsdata #nfs共享的目錄 volumes: - name: nfs-client-root nfs: server: 172.16.1.30 path: /nfsdata
#建立storage class:less
[root@master yaml]# vim sc.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: statefu-nfs namespace: default provisioner: nfs-deploy reclaimPolicy: Retain
//運行yaml文件後,查看sc的信息: [root@master yaml]# kubectl get sc NAME PROVISIONER AGE statefu-nfs nfs-deploy 48s
2)建立statefulset資源:
[root@master yaml]# vim statefulset.yaml apiVersion: v1 kind: Service metadata: name: headless-svc #定義無頭服務,須要定義標籤 labels: app: headless-svc spec: ports: - name: testweb port: 80 clusterIP: None #須要將cluster ip定義爲none selector: app: nginx #此處指定的標籤須要在後邊進行定義 --- apiVersion: apps/v1 kind: StatefulSet metadata: name: sfs-web spec: serviceName: headless-svc #此處選擇的服務名爲上邊定義的無頭服務名 replicas: 3 selector: matchLabels: app: nginx #選擇標籤 template: metadata: labels: app: nginx #定義標籤 spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: #定義數據持久化 - name: test-nginx mountPath: /usr/share/nginx/html #掛載到容器內的路徑 volumeClaimTemplates: #經過該字段(模板)爲每一個pod建立pvc - metadata: name: test-nginx annotations: volume.beta.kubernetes.io/storage-class: statefu-nfs #此處選擇以前建立的storage class,名稱要一致 spec: accessModes: - ReadWriteOnce #採用ReadWriteOnce的訪問模式 resources: requests: storage: 100Mi #請求100M的空間
[root@master yaml]# kubectl apply -f statefulset.yaml service/headless-svc unchanged statefulset.apps/sfs-web created
//運行成功後,查看建立的headless service和statefulset的狀態:
//查看svc的詳細信息:
//查看建立的pod:(確保正常運行)
能夠看到每一個pod都是有序的,它們的名稱(域名)會以0,1,2....依次排序。
#根據上面咱們說到的,經過sc會建立pv,以及經過sts中的模板會自動建立pvc,咱們進行查看集羣中的pv和pvc:
咱們能夠看到pv和pvc建立成功,狀態已是Bound了,訪問模式是RWO(在sc中定義的模式),回收策略Delete ,都是經過sc和sts動態建立的,而並非咱們手動建立。
3)測試數據持久化
#查看掛載到nfs服務器上是否會生成每一個pvc的共享目錄:
#進入某個pod目錄下建立測試網頁文件:
[root@master yaml]# cd /nfsdata/default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023/ [root@master default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# echo "<h1>hello world</h1>" > index.html [root@master default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# ll total 4 -rw-r--r-- 1 root root 21 Jan 12 17:13 index.html
#咱們進入到pod中,查看文件是否掛載成功:
#接下來咱們將該pod刪除掉:
驗證從新生成的pod是否被替換,數據是否丟失?
經過上面的測試結果,咱們能夠得知有狀態的服務不一樣於無狀態服務,從新生成的pod名稱不會發生改變,即使刪除後也不會被新生成的pod覆蓋,且原有pod中的數據也一併會存在。
4)replicas的擴容與縮容:
(1)擴容操做:
[root@master yaml]# vim statefulset.yaml
//從新運行yaml文件,查看新生成的pod:
(2)縮容操做:(以倒序的方式依次縮減)
//從新運行服務,查看pod狀態:
經過上面的擴縮容操做,咱們能夠得知statefulset資源在生產環境中可以實現有序部署,即有序擴展,有序收縮,且pod的啓停都是有必定順序的。
5)分區更新操做:分區更新的主要目的是爲pod進行一個分區,爲了使咱們對某個應用全部pod中的某一部分或者有選擇性的pod進行更新操做。
#在更新以前,咱們先來查看更新的參數:
[root@master yaml]# kubectl explain sts.spec.updateStrategy.rollingUpdate KIND: StatefulSet VERSION: apps/v1 RESOURCE: rollingUpdate <Object> DESCRIPTION: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. RollingUpdateStatefulSetStrategy is used to communicate parameter for RollingUpdateStatefulSetStrategyType. FIELDS: partition <integer> Partition indicates the ordinal at which the StatefulSet should be partitioned. Default value is 0.
#根據以上參數,咱們對pod進行分區,而且對指定分區的pod進行版本升級:
咱們將replicas的數量設置爲8個,且定義分區更新,表示從第四個pod(分區)開始(包括第四個分區)進行更新,以前的pod是不會進行更新操做的。
注意:若是不指定分區,則默認分區從0開始。
#版本升級就不進行測試了,只需將鏡像更改成新的nginx版本,從新運行服務後,能夠看到從第四個pod開始(包括第四個)以後的pod鏡像版本將會進行升級,而以前分區的pod,版本不會發生改變。
4,StatefulSet限制
1)該資源對象還在beta(測試)狀態,須要kubernetes v1.5版本以上才支持。 2)全部pod的volume必須使用pv或者是管理員事先建立好的。 3)爲了保證數據安全,刪除statefulset時不會刪除volume。 4)statefulset須要一個Headless Service服務來定義DNS domin,須要在statefulset以前建立好。 5)目前statefulset功能還還沒有完善,好比上面的更新操做還須要手動解決。
以上就是statefulset資源的理解與實踐,若是應用程序不須要任何穩定的標識符,有序部署,刪除和scale,則使用Deployment或RS等無狀態控制器來部署。反之在生產中使用statefulset控制器爲保證pod與volume的關係不會斷開,即便pod掛了後還能使用以前掛載的磁盤