如何在Kubernetes中管理有狀態應用
在Kubernetes中,StatefulSet被用來管理有狀態應用的API對象。StatefulSets在Kubernetes 1.9版本才穩定。StatefulSet管理Pod部署和擴容,並為這些Pod提供順序和唯一性的保證。與Deployment相似的地方是,StatefulSet基於spec規格管理Pod;與Deployment不同的地方是,StatefulSet需要維護每一個Pod的唯一身份標識。這些Pod基於同樣的spec創建,但互相之間不能替換,每一個Pod都保留自己的持久化標識。
1、使用StatefulSet的場景 對於下面的應用場景,StatefulSets是有價值的: 穩定、唯一的網絡標識 穩定、持久的存儲 按照順序、優雅的部署和擴容 按照順序、優雅的刪除和終止 按照順序、自動滾動更新 上述的穩定是持久的同義詞,如果應用不需要穩定的標識或者順序的部署、刪除、擴容,則應該使用無狀態的副本集。Deployment或者ReplicaSet的控制器更加適合無狀態業務場景。 2、StatefulSet的限制
在Kubernetes 1.9版本之前是beta版本,在Kubernetes 1.5版本之前是不提供的。
Pod存儲由PersistentVolume(storage類或者管理員預先創建)提供。 刪除或者縮容StatefulSet不會刪除與StatefulSet關聯的數據卷,這樣能夠保證數據的安全性。 當前的StatefulSets需要一個Headless服務來為Pod提供網絡標識,此Headless服務需要通過手工創建。 3、組件 下面是一個StatefuleSet組成的示例: 一個名稱為nginx的Headless服務,用來控制網絡域。 一個名稱為web的statefulSet,它擁有nginx容器(在唯一的Pod啟動)的3個副本集。 使用PersistenVolumes(由PersistentVolume Provisioner提供)提供穩定存儲的volumeClaimTemplates。 4、Pod選擇器 必須設置StatefulSet的sepc.selector,以匹配.spec.template.metadata.labels。在Kubernetes 1.8之前,spec.selector是可以忽略的,它被設置一個默認值。在1.8或者後續的版本,如果不設置sepc.selector,則會導致創建StatefulSet失敗。 5、Pod身份標識 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。 6、部署和擴容保證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
對於一個帶有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的值進行保證。 OrderedReady pod管理是StatefulSets默認的管理模式,此模式安裝順序啟動或者終止Pod。 並行Pod管理告訴StatefulSet控制器以並行的方式啟動或者終止所有的Pod。 7、更新策略 在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將被不會進行更新。在大部分的情況下,不會使用分隔;當希望進行金絲雀發布,或者執行階段發布時,分隔是很有用的。 作者簡介: 季向遠,北京神舟航天軟件技術有限公司產品經理。本文版權歸原作者所有。
如何在Kubernetes中管理有狀態應用