Kubernetes K8S之資源控制器StatefulSets詳解

 

Kubernetes的資源控制器StatefulSet詳解與示例html

 

主機配置規劃

服務器名稱(hostname) 系統版本 配置 內網IP 外網IP(模擬)
k8s-master CentOS7.7 2C/4G/20G 172.16.1.110 10.0.0.110
k8s-node01 CentOS7.7 2C/4G/20G 172.16.1.111 10.0.0.111
k8s-node02 CentOS7.7 2C/4G/20G 172.16.1.112 10.0.0.112

 

什麼是控制器

kubernetes中內建了不少controller(控制器),這些至關於一個狀態機,用來控制pod的具體狀態和行爲。node

部分控制器類型以下:
  • ReplicationController 和 ReplicaSet
  • Deployment
  • DaemonSet
  • StatefulSet
  • Job/CronJob
  • HorizontalPodAutoscaler

 

StatefulSet

StatefulSet 是用來管理有狀態應用的工做負載 API 對象。nginx

StatefulSet 中的 Pod 擁有一個具備黏性的、獨一無二的身份標識。這個標識基於 StatefulSet 控制器分配給每一個 Pod 的惟一順序索引。Pod 的名稱的形式爲<statefulset name>-<ordinal index> 。例如:web的StatefulSet 擁有兩個副本,因此它建立了兩個 Pod:web-0和web-1。web

和 Deployment 相同的是,StatefulSet 管理了基於相同容器定義的一組 Pod。但和 Deployment 不一樣的是,StatefulSet 爲它們的每一個 Pod 維護了一個固定的 ID。這些 Pod 是基於相同的聲明來建立的,可是不能相互替換:不管怎麼調度,每一個 Pod 都有一個永久不變的 IDapi

【使用場景】StatefulSets 對於須要知足如下一個或多個需求的應用程序頗有價值:安全

  • 穩定的、惟一的網絡標識符,即Pod從新調度後其PodName和HostName不變【固然IP是會變的】
  • 穩定的、持久的存儲,即Pod從新調度後仍是能訪問到相同的持久化數據,基於PVC實現
  • 有序的、優雅的部署和縮放
  • 有序的、自動的滾動更新

如上面,穩定意味着 Pod 調度或重調度的整個過程是有持久性的。服務器

若是應用程序不須要任何穩定的標識符或有序的部署、刪除或伸縮,則應該使用由一組無狀態的副本控制器提供的工做負載來部署應用程序,好比使用 Deployment 或者 ReplicaSet 可能更適用於無狀態應用部署須要。網絡

 

限制

  • 給定 Pod 的存儲必須由 PersistentVolume 驅動 基於所請求的 storage class 來提供,或者由管理員預先提供。
  • 刪除或者收縮 StatefulSet 並不會刪除它關聯的存儲卷。這樣作是爲了保證數據安全,它一般比自動清除 StatefulSet 全部相關的資源更有價值。
  • StatefulSet 當前須要 headless 服務 來負責 Pod 的網絡標識。你須要負責建立此服務。
  • 當刪除 StatefulSets 時,StatefulSet 不提供任何終止 Pod 的保證。爲了實現 StatefulSet 中的 Pod 能夠有序和優雅的終止,能夠在刪除以前將 StatefulSet 縮放爲 0。
  • 在默認 Pod 管理策略(OrderedReady) 時使用滾動更新,可能進入須要人工干預才能修復的損壞狀態。

 

有序索引

對於具備 N 個副本的 StatefulSet,StatefulSet 中的每一個 Pod 將被分配一個整數序號,從 0 到 N-1,該序號在 StatefulSet 上是惟一的。app

StatefulSet 中的每一個 Pod 根據 StatefulSet 中的名稱和 Pod 的序號來派生出它的主機名。組合主機名的格式爲$(StatefulSet 名稱)-$(序號)。less

 

部署和擴縮保證

  • 對於包含 N 個 副本的 StatefulSet,當部署 Pod 時,它們是依次建立的,順序爲 0~(N-1)。
  • 當刪除 Pod 時,它們是逆序終止的,順序爲 (N-1)~0。
  • 在將縮放操做應用到 Pod 以前,它前面的全部 Pod 必須是 Running 和 Ready 狀態。
  • 在 Pod 終止以前,全部的繼任者必須徹底關閉。

StatefulSet 不該將 pod.Spec.TerminationGracePeriodSeconds 設置爲 0。這種作法是不安全的,要強烈阻止。

部署順序

在下面的 nginx 示例被建立後,會按照 web-0、web-一、web-2 的順序部署三個 Pod。在 web-0 進入 Running 和 Ready 狀態前不會部署 web-1。在 web-1 進入 Running 和 Ready 狀態前不會部署 web-2。

若是 web-1 已經處於 Running 和 Ready 狀態,而 web-2 還沒有部署,在此期間發生了 web-0 運行失敗,那麼 web-2 將不會被部署,要等到 web-0 部署完成並進入 Running 和 Ready 狀態後,纔會部署 web-2。

收縮順序

若是想將示例中的 StatefulSet 收縮爲 replicas=1,首先被終止的是 web-2。在 web-2 沒有被徹底中止和刪除前,web-1 不會被終止。當 web-2 已被終止和刪除;但web-1 還沒有被終止,若是在此期間發生 web-0 運行失敗,那麼就不會終止 web-1,必須等到 web-0 進入 Running 和 Ready 狀態後纔會終止 web-1。

 

StatefulSet示例

說明:本次示例不涉及存儲,StatefulSet的存儲示例會在「Kubernetes K8S之存儲PV-PVC詳解」文章中演示。

yaml文件

 1 [root@k8s-master controller]# pwd
 2 /root/k8s_practice/controller
 3 [root@k8s-master controller]# cat statefulset.yaml 
 4 apiVersion: v1
 5 kind: Service
 6 metadata:
 7   name: nginx
 8   labels:
 9     app: nginx
10 spec:
11   ports:
12   - port: 80
13     name: http
14   clusterIP: None
15   selector:
16     app: nginx
17 ---
18 apiVersion: apps/v1
19 kind: StatefulSet
20 metadata:
21   name: web
22 spec:
23   selector:
24     matchLabels:
25       app: nginx # has to match .spec.template.metadata.labels
26   serviceName: "nginx"
27   replicas: 3 # by default is 1
28   template:
29     metadata:
30       labels:
31         app: nginx # has to match .spec.selector.matchLabels
32     spec:
33       terminationGracePeriodSeconds: 10   # 默認30秒
34       containers:
35       - name: nginx
36         image: registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17
37         ports:
38         - containerPort: 80
39           name: http

 

啓動StatefulSet和Service,並查看狀態

 1 [root@k8s-master controller]# kubectl apply -f statefulset.yaml 
 2 service/nginx created
 3 statefulset.apps/web created
 4 [root@k8s-master controller]# kubectl get service -o wide
 5 NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
 6 kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   17d   <none>
 7 nginx        ClusterIP   None         <none>        80/TCP    87s   app=nginx
 8 [root@k8s-master controller]# 
 9 [root@k8s-master controller]# kubectl get statefulset -o wide
10 NAME   READY   AGE   CONTAINERS   IMAGES
11 web    3/3     15m   nginx        registry.cn-beijing.aliyuncs.com/google_registry/nginx:1.17
12 [root@k8s-master controller]# 
13 [root@k8s-master controller]# kubectl get pod -o wide
14 NAME    READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
15 web-0   1/1     Running   0          16m   10.244.2.95    k8s-node02   <none>           <none>
16 web-1   1/1     Running   0          16m   10.244.3.103   k8s-node01   <none>           <none>
17 web-2   1/1     Running   0          16m   10.244.3.104   k8s-node01   <none>           <none>

由上可見,StatefulSet 中的pod是有序的。有N個副本,那麼序列號爲0~(N-1)。

 

查看StatefulSet相關的域名信息

啓動一個pod

 1 [root@k8s-master test]# pwd
 2 /root/k8s_practice/test
 3 [root@k8s-master test]# cat myapp_demo.yaml 
 4 apiVersion: v1
 5 kind: Pod
 6 metadata:
 7   name: myapp-demo
 8   namespace: default
 9   labels:
10     k8s-app: myapp
11 spec:
12   containers:
13   - name: myapp
14     image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
15     imagePullPolicy: IfNotPresent
16     ports:
17     - name: httpd
18       containerPort: 80
19       protocol: TCP
20 [root@k8s-master test]# 
21 [root@k8s-master test]# kubectl apply -f myapp_demo.yaml
22 pod/myapp-demo created
23 [root@k8s-master test]# 
24 [root@k8s-master test]# kubectl get pod -o wide | grep 'myapp'
25 myapp-demo   1/1     Running   0          3m24s   10.244.2.101   k8s-node02   <none>           <none>

 

進入pod並查看StatefulSet域名信息

 1 # 進入一個k8s管理的myapp鏡像容器。
 2 [root@k8s-master test]# kubectl exec -it myapp-demo sh
 3 / # nslookup 10.244.2.95
 4 nslookup: can't resolve '(null)': Name does not resolve
 5 
 6 Name:      10.244.2.95
 7 Address 1: 10.244.2.95 web-0.nginx.default.svc.cluster.local
 8 / # 
 9 / # 
10 / # nslookup 10.244.3.103
11 nslookup: can't resolve '(null)': Name does not resolve
12 
13 Name:      10.244.3.103
14 Address 1: 10.244.3.103 web-1.nginx.default.svc.cluster.local
15 / # 
16 / # 
17 / # nslookup 10.244.3.104
18 nslookup: can't resolve '(null)': Name does not resolve
19 
20 Name:      10.244.3.104
21 Address 1: 10.244.3.104 web-2.nginx.default.svc.cluster.local
22 / # 
23 / # 
24 ##### nginx.default.svc.cluster.local   爲service的域名信息
25 / # nslookup nginx.default.svc.cluster.local
26 nslookup: can't resolve '(null)': Name does not resolve
27 
28 Name:      nginx.default.svc.cluster.local
29 Address 1: 10.244.3.104 web-2.nginx.default.svc.cluster.local
30 Address 2: 10.244.3.103 web-1.nginx.default.svc.cluster.local
31 Address 3: 10.244.2.95 web-0.nginx.default.svc.cluster.local

 

StatefulSet網絡標識與PVC

有上文可得以下信息:

一、匹配StatefulSet的Pod name(網絡標識)的模式爲:$(statefulset名稱)-$(序號),好比StatefulSet名稱爲web,副本數爲3。則爲:web-0、web-一、web-2

二、StatefulSet爲每一個Pod副本建立了一個DNS域名,這個域名的格式爲:$(podname).(headless service name),也就意味着服務之間是經過Pod域名來通訊而非Pod IP。當Pod所在Node發生故障時,Pod會被漂移到其餘Node上,Pod IP會發生改變,但Pod域名不會變化

三、StatefulSet使用Headless服務來控制Pod的域名,這個Headless服務域名的爲:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的集羣的域名

四、根據volumeClaimTemplates,爲每一個Pod建立一個PVC,PVC的命令規則爲:$(volumeClaimTemplates name)-$(pod name),好比volumeClaimTemplates爲www,pod name爲web-0、web-一、web-2;那麼建立出來的PVC爲:www-web-0、www-web-一、www-web-2

五、刪除Pod不會刪除對應的PVC,手動刪除PVC將自動釋放PV。

 

相關閱讀

一、Kubernetes K8S之資源控制器RC、RS、Deployment詳解

完畢!

 


 

———END———
若是以爲不錯就關注下唄 (-^O^-) !

相關文章
相關標籤/搜索