Kubernetes K8S之資源控制器StatefulSets詳解
Kubernetes的資源控制器StatefulSet詳解與示例
主機配置規劃
伺服器名稱(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的具體狀態和行為。
- ReplicationController 和 ReplicaSet
- Deployment
- DaemonSet
- StatefulSet
- Job/CronJob
- HorizontalPodAutoscaler
StatefulSet
StatefulSet 是用來管理有狀態應用的工作負載 API 對象。
StatefulSet 中的 Pod 擁有一個具有黏性的、獨一無二的身份標識。這個標識基於 StatefulSet 控制器分配給每個 Pod 的唯一順序索引。Pod 的名稱的形式為<statefulset name>-<ordinal index> 。例如:web的StatefulSet 擁有兩個副本,所以它創建了兩個 Pod:web-0和web-1。
和 Deployment 相同的是,StatefulSet 管理了基於相同容器定義的一組 Pod。但和 Deployment 不同的是,StatefulSet 為它們的每個 Pod 維護了一個固定的 ID。這些 Pod 是基於相同的聲明來創建的,但是不能相互替換:無論怎麼調度,每個 Pod 都有一個永久不變的 ID。
【使用場景】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 上是唯一的。
StatefulSet 中的每個 Pod 根據 StatefulSet 中的名稱和 Pod 的序號來派生出它的主機名。組合主機名的格式為$(StatefulSet 名稱)-$(序號)。
部署和擴縮保證
- 對於包含 N 個 副本的 StatefulSet,當部署 Pod 時,它們是依次創建的,順序為 0~(N-1)。
- 當刪除 Pod 時,它們是逆序終止的,順序為 (N-1)~0。
- 在將縮放操作應用到 Pod 之前,它前面的所有 Pod 必須是 Running 和 Ready 狀態。
- 在 Pod 終止之前,所有的繼任者必須完全關閉。
StatefulSet 不應將 pod.Spec.TerminationGracePeriodSeconds 設置為 0。這種做法是不安全的,要強烈阻止。
在下面的 nginx 示例被創建後,會按照 web-0、web-1、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
有上文可得如下資訊:
1、匹配StatefulSet的Pod name(網路標識)的模式為:$(statefulset名稱)-$(序號),比如StatefulSet名稱為web,副本數為3。則為:web-0、web-1、web-2
2、StatefulSet為每個Pod副本創建了一個DNS域名,這個域名的格式為:$(podname).(headless service name),也就意味著服務之間是通過Pod域名來通訊而非Pod IP。當Pod所在Node發生故障時,Pod會被漂移到其他Node上,Pod IP會發生改變,但Pod域名不會變化
3、StatefulSet使用Headless服務來控制Pod的域名,這個Headless服務域名的為:$(service name).$(namespace).svc.cluster.local,其中 cluster.local 指定的集群的域名
4、根據volumeClaimTemplates,為每個Pod創建一個PVC,PVC的命令規則為:$(volumeClaimTemplates name)-$(pod name),比如volumeClaimTemplates為www,pod name為web-0、web-1、web-2;那麼創建出來的PVC為:www-web-0、www-web-1、www-web-2
5、刪除Pod不會刪除對應的PVC,手動刪除PVC將自動釋放PV。
相關閱讀
1、Kubernetes K8S之資源控制器RC、RS、Deployment詳解
完畢!
———END———
如果覺得不錯就關注下唄 (-^O^-) !