概述
Kubernetes中有很多的控制器,比如常用的ReplicaSet,Deployment,DaemonSet,StatefulSet等。以這四種爲例,我們可以將它們分爲兩種,一種爲有狀態控制器,一種爲無狀態控制器,StatefulSet則爲有狀態控制器,通常用於管理有狀態的服務,如:MySQL,Redis,MongoDB等。
有狀態控制器通常有以下幾個特點:
穩定的,唯一的網絡標識
穩定的,持久的存儲
有序的,優雅的部署和伸縮
有序的,優雅的刪除和停止
有序的,自動的滾更新
也就是說如果我們的應用如有以上的任何一個特點我們就可以使用statefulset控制器來完成應用的部署。
網絡標識:
Pod名稱:唯一且不會發生變化,由 $(statefulset name)-(0-N)組成,N爲一個無限大的正整數,從0開始。
容器內計算機名:與Pod名稱一至且不會發生變化。
DNS A記錄:每一個副本都擁有唯一且不變的一條A記錄指定自己,格式組成:$(pod name).$(service name).$(namespace name).svc。
唯一的Pod標籤,通過StatefulSet創建的每個副本都擁有一個唯一的標籤,格式爲:statefulset.kubernetes.io/pod-name=$(pod name),通常可以將新的service單獨關聯到此標籤,來解決某個Pod的問題等。
以上的標識只要配置不發生改變,發生重啓,升級,刪除後再創建這些標識都不會發生變化。
備註:Pod的IP地址會發生變化,但我們也可以使用另外的方案來結合StatefulSet實現固定IP的方案,通常不推薦這麼做。
持久存儲:
每個Pod都對應一個PVC,PVC的名稱組成:$(volumeClaimTemplates name)-$(pod name)-(0-N),N爲一個無限大的正整數,從0開始。
當Pod被刪除的時候不會自動刪除對應的PVC,需要手動刪除。
每次Pod升級,重啓,刪除重新創建後都呆以保證使用的是首次使用的PVC,保證數據的唯一性與持久化。
有序:
當部署有N個副本的StatefulSet時候,嚴格按照從0到N的順序創建,並且下一個Pod創建的前提是上一個Pod已經Running狀態。
當刪除有N個副本的StatefulSet時候,嚴格按照從N到0的順序刪除,並且下一個Pod刪除的前提是上一個Pod已經完全Delete。
當擴容StatefulSet副本的時候,每增加一個pod前提是上一個Pod已經Running狀態。
當減少StatefulSet副本的時候,每刪除一個pod前提是上一個Pod已經完全Delete。
當升級StatefulSet的時候,嚴格按照從N到1的順序升級,並且下一個Pod升級的前提是上一個Pod已經Running狀態。
無頭服務(headless service)
無頭服務是Kubernetes中service類型的一種,爲什麼需要無頭服務?通常我們在使用Deployment部署Pod的時候名稱是隨機的字符串,Pod也是無序的。但 StatefulSet是有序且名稱唯一,每一個Pod不可以被取代,所以這時候就需要使用無頭服務來實現。
無頭服務特點:當使用Kubernetes內DNS解析去訪問Service的時候,會將解析的IP指向Service後端的Pod。當無頭服務與StatefulSet控制器使用的時候,因爲每個Pod的數據可能是不一樣的,所以在Service名前面再加了一個Pod名,這樣我們的每個StatefulSet控制器的Pod就擁有了唯一的網絡標識(A記錄)。
無頭服務案例:
apiVersion: v1 kind: Service metadata: namespace: test name: mysql-test spec: selector: app: mysql-test clusterIP: None ports: - port: 3306 targetPort: 3306
ClusterIP:當此項的值爲“None”的時候,此服務就爲無頭服務,Kubernetes不會給此服務分配IP地址。當使用type爲NodePort的時候不可以使用無頭服務。
volumeClaimTemplates:
此爲Kubernetes中的一個對象,對象的路徑爲“statefulset.spec.volumeClaimTemplates”,用於給StatefulSet的Pod申請PVC,稱爲卷申請模板,它會爲每個Pod生成不同的PVC,關綁定到PV,從而實現Pod的專有存儲。
通常我們在使用Deployment中使用“deployment.spec.template.spec.volumes”與PVC建立關聯的時候,所有的副本使用的是相同的PV與PVC,他們的數據是相同的。而StatefulSet爲實現各Pod的專有存儲,所以纔有了“statefulset.spec.volumeClaimTemplates”此方法。
實際應用場景