1. 程式人生 > >如何在Kubernetes中管理有狀態應用

如何在Kubernetes中管理有狀態應用

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。

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



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.localcluster.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、部署和擴容保證


  • 對於一個帶有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。


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中管理有狀態應用