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

在Kubernetes中,StatefulSet被用來管理有狀態應用的API對象。StatefulSets在Kubernetes 1.9版本才穩定。StatefulSet管理Pod部署和擴容,併爲這些Pod提供順序和惟一性的保證。與Deployment類似的地方是,StatefulSet基於spec規格管理Pod;與Deployment不一樣的地方是,StatefulSet須要維護每個Pod的惟一身份標識。這些Pod基於一樣的spec建立,但互相之間不能替換,每個Pod都保留本身的持久化標識。html

輸入圖片說明

一、使用StatefulSet的場景

對於下面的應用場景,StatefulSets是有價值的:nginx

  • 穩定、惟一的網絡標識web

  • 穩定、持久的存儲api

  • 按照順序、優雅的部署和擴容安全

  • 按照順序、優雅的刪除和終止網絡

  • 按照順序、自動滾動更新app

上述的穩定是持久的同義詞,若是應用不須要穩定的標識或者順序的部署、刪除、擴容,則應該使用無狀態的副本集。Deployment或者ReplicaSet的控制器更加適合無狀態業務場景。less

二、StatefulSet的限制

  • 在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

四、Pod選擇器

必須設置StatefulSet的sepc.selector,以匹配.spec.template.metadata.labels。在Kubernetes 1.8以前,spec.selector是能夠忽略的,它被設置一個默認值。在1.8或者後續的版本,若是不設置sepc.selector,則會致使建立StatefulSet失敗。

五、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。

六、部署和擴容保證

  • 對於一個帶有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將被不會進行更新。在大部分的狀況下,不會使用分隔;當但願進行金絲雀發佈,或者執行階段發佈時,分隔是頗有用的。

做者簡介:

季向遠,北京神舟航天軟件技術有限公司產品經理。本文版權歸原做者全部。

相關文章
相關標籤/搜索