在Kubernetes中,StatefulSet被用來管理有狀態應用的API對象。StatefulSets在Kubernetes 1.9版本才穩定。StatefulSet管理Pod部署和擴容,併爲這些Pod提供順序和惟一性的保證。與Deployment類似的地方是,StatefulSet基於spec規格管理Pod;與Deployment不一樣的地方是,StatefulSet須要維護每個Pod的惟一身份標識。這些Pod基於一樣的spec建立,但互相之間不能替換,每個Pod都保留本身的持久化標識。html
對於下面的應用場景,StatefulSets是有價值的:nginx
穩定、惟一的網絡標識web
穩定、持久的存儲api
按照順序、優雅的部署和擴容安全
按照順序、優雅的刪除和終止網絡
按照順序、自動滾動更新app
上述的穩定是持久的同義詞,若是應用不須要穩定的標識或者順序的部署、刪除、擴容,則應該使用無狀態的副本集。Deployment或者ReplicaSet的控制器更加適合無狀態業務場景。less
在Kubernetes 1.9版本以前是beta版本,在Kubernetes 1.5版本以前是不提供的。dom
Pod存儲由PersistentVolume(storage類或者管理員預先建立)提供。spa
刪除或者縮容StatefulSet不會刪除與StatefulSet關聯的數據卷,這樣可以保證數據的安全性。
當前的StatefulSets須要一個Headless服務來爲Pod提供網絡標識,此Headless服務須要經過手工建立。
下面是一個StatefuleSet組成的示例:
一個名稱爲nginx的Headless服務,用來控制網絡域。
一個名稱爲web的statefulSet,它擁有nginx容器(在惟一的Pod啓動)的3個副本集。
使用PersistenVolumes(由PersistentVolume Provisioner提供)提供穩定存儲的volumeClaimTemplates。
apiVersion:v1 kind:Service metadata: name:nginx labels: app:nginx spec: ports: -port:80 name:web clusterIP:None //Headless服務 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" 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 #掛接路徑爲容器的/usr/share/nginx/html volumeClaimTemplates: #數據卷生命模板 -metadata: name:www spec: accessModes:["ReadWriteOnce"] storageClassName:my-storage-class resources: requests: storage:1Gi
必須設置StatefulSet的sepc.selector,以匹配.spec.template.metadata.labels。在Kubernetes 1.8以前,spec.selector是能夠忽略的,它被設置一個默認值。在1.8或者後續的版本,若是不設置sepc.selector,則會致使建立StatefulSet失敗。
StatfuleSet Pod擁有一個惟一的身份標識,它由順序、穩定的網絡標識和穩定的存儲所組成。此身份標識一直跟隨着Pod,不過它被調度到那個Node上。
5.1 序數索引(Ordinal Index)
對於擁有N個副本集的StatefulSet,在StatefulSet中的每個Pod都會被指派一個整型的序數,此序數在0和N之間,在整個集合中是惟一的。
5.2 網絡ID(Stable Network ID)
在StatefulSet中,每個Pod的主機名稱都由StatefulSet的名稱和序數所組成。Pod的主機名稱的格式:$(statefulset name)-$(ordinal)。若是建立了三個Pod,這他們的主機名稱爲web-0,web-1,web-2。StatefulSet可以使用Headless服務來控制Pod的域。Service管理的域的格式爲:$(service name).$(namespace).svc.cluster.local,cluster.local是集羣域。對於每個被建立的Pod,它將獲得一個DNS子域,格式爲: $(podname).$(governing service domain),這裏的管理服務在StatefulSet中,經過serviceName設置。
下面是StatefulSet中Pod在DNS中的名稱:
5.3 穩定的存儲
kubernetes爲每個VolumeClaimTemplate建立一個對應的PersistentVolume。在前面的nginx實例中,每個Pod將會my-storage-class存儲類型的PersistenVolume單一實例和1Gib的存儲空間。
若是沒有指定存儲類,則會使用默認的存儲。但一個Pod被調度到Node上,它的volumeMounts將會掛接PersistentVolumes,並將其與PersistentVolumeClaims進行關聯。須要注意的是,即便在Pod被刪除,PersistentVolumes與PersistentVolumeClaims之間的關聯關係也不會被刪除。
5.4 Pod命名標籤
當StatefulSet控制器建立了Pod,它將會添加一個標籤,爲此Pod名稱的集合。此標籤將可以管理服務到指定的Pod。
對於一個帶有N個副本集的StatefulSet,當Pod被部署,它們將按0到N-1的順序被建立。
當一Pod被刪除時,它們將按照N-1到0的倒序被終止。
在進行Pod擴容前,全部依賴的Pod應該都已在運行和準備好。
在Pod被終止前,全部的依賴它的Pod都必須徹底中止。
在前文建立的nginx例子中,將按照順序部署web-0,web-1和web-2。web-1只能在web-0運行和準備好之後纔可以被部署,web-2只能在web-1運行和準備好之後纔可以被部署。若是web-0失敗,就算web-1正在運行,web-2也是不能正常啓動的,除非web-0被重啓,並正常運行。
若是縮容上述例子,設置replicas=1,則web-2首先被終止,接着是web-1。若是在web-2被終止後,但在web-1被終止前,web-0失敗了,web-1將不能被終止,除非web-0處於正常運行狀態。
6.1 Pod管理策略
在Kubernetes 1.7之後,StatefulSet的惟一性標識能夠經過.spec.podManagementPolicy的值進行保證。
6.1.1 OrderedReady Pod管理
OrderedReady pod管理是StatefulSets默認的管理模式,此模式安裝順序啓動或者終止Pod。
6.1.2 並行Pod管理
並行Pod管理告訴StatefulSet控制器以並行的方式啓動或者終止全部的Pod。
在Kubernetes 1.7以後,運行經過配置StatefulSet的.spec.updateStrategy,實現Pod的容器、標籤、資源請求/限制和註釋自動更新。
7.1 On Delete策略
OnDelete更新策略是1.6以前版本的行爲。當StatefulSet的.spec.updateStrategy.type被設置爲OnDelete,則StatefulSet控制器將不會知道更新Pod。
7.2 Rolling Updates策略
RollingUpdate更新策略將實現StatefulSet中Pod的自動滾動更新,這是StatefulSet的默認更新模式。若是.spec.updateStrategy.type設置爲 RollingUpdate,則StatefulSet控制器將會刪除和重建StatefulSet中的每一Pod。它將會按照從最大到最小的序數終止Pod,並按照從小到大順序重建Pod。
7.3 Partitions
RollingUpdate更新策略可以經過指定.spec.updateStrategy.rollingUpdate.partition進行分隔。當分隔被指定,全部序數大於或等於分隔的Pod將會被更新,其它的Pod將被不會進行更新。在大部分的狀況下,不會使用分隔;當但願進行金絲雀發佈,或者執行階段發佈時,分隔是頗有用的。
做者簡介:
季向遠,北京神舟航天軟件技術有限公司產品經理。本文版權歸原做者全部。