首頁 > 軟體

通過StatefulSet部署有狀態服務應用實現方式

2022-03-18 19:00:13

先總結後詳解:

  • 具有固定的網路標識,如主機名、域名等
  • 支援持久化儲存
  • 可以按順序部署和擴充套件
  • 可以按順序終止和刪除
  • 捲動升級也是按照一定順序

StatefulSet的基本概念:

StatefulSet主要用於管理有狀態的應用程式的工作負載的API物件。比如生產中的Elastic Search叢集、MongoDB叢集、Kafka叢集、Reids叢集、Zookeeper叢集等。。。

與Deployment相似的是,StatefulSet也同樣管理著基本相同容器規範的Pod。不同的是,StatefulSet為每個Pod維護了一個粘性標識。

這些Pod是根據相同的規範建立的,但是不可互換,每個Pod都有一個持久的識別符號,在重新排程時也會保留,一般格式為StatefulSetName-Number。

比如定義一個Redis-Sentinel的StatefulSet,指定三個副本,就會依次建立名為Redis-Sentinel-0、Redis-Sentinel-1、Redis-Sentinel-2的三個副本。而StatefulSet的Pod的Service一般使用Headless Service(無頭服務)進行通訊。

Headless的格式為一般為:

statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
  • statefulSetName:StatefulSet的名稱
  • {0…N-1}:名稱後面的序號
  • serviceName:Headless Service的名稱
  • namespace:服務所在的名稱空間
  • cluster.local:Cluster Daemon(叢集域)

StatefulSet用於有以下一條或多條需求的應用程式:

  • 需要穩定的獨一無二的網路識別符號
  • 需要持久化資料
  • 需要有序的、優雅的部署和擴充套件
  • 需要有序的自動捲動更新

如果都不需要,那應該使用Deployment部署。

範例:定義一個StatefulSet資源

建立一個nginx的StatefulSet作為示範:這個yaml啟動兩個副本,使用nginx映象,注意service一定要存在。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec: 
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector: 
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        ports:
        - containerPort: 80
          name: web

使用kubectl建立一下:可以看到service和statefulset副本都建立了

[root@k8s-master01 ~]# kubectl create -f nginx-sts.yaml 
service/nginx created
statefulset.apps/web created

檢視Pod:可以看到副本的名稱是按序號從0開始的

[root@k8s-master01 ~]# kubectl get pod
NAME      READY   STATUS    RESTARTS       AGE
busybox   1/1     Running   17 (50m ago)   7d18h
web-0     1/1     Running   0              74s
web-1     1/1     Running   0              73s

檢視service:可以看到nginx的service是沒有CLUSTER-IP的

[root@k8s-master01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   7d21h
nginx        ClusterIP   None         <none>        80/TCP    2m43s

擴容副本:可以看到與deployment不同的是,新生成的Pod名稱序號是有規律的

[root@k8s-master01 ~]# kubectl scale --replicas=3 sts web 
statefulset.apps/web scaled
[root@k8s-master01 ~]# kubectl get pod
NAME      READY   STATUS              RESTARTS       AGE
busybox   1/1     Running             17 (55m ago)   7d18h
web-0     1/1     Running             0              6m30s
web-1     1/1     Running             0              6m29s
web-2     0/1     ContainerCreating   0              28s

測試存取一下是否可以通訊:可以看到網路是通的,IP直接解析到172.18.195.18上,也就是Pod的IP而不用通過一層service代理。

[root@k8s-master01 ~]# kubectl exec -ti busybox -- sh
/ # nslookup web-0.nginx
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name:      web-0.nginx
Address 1: 172.18.195.18 web-0.nginx.default.svc.cluster.local
/ # ping web-0.nginx
PING web-0.nginx (172.18.195.18): 56 data bytes
64 bytes from 172.18.195.18: seq=0 ttl=62 time=1.020 ms
64 bytes from 172.18.195.18: seq=1 ttl=62 time=0.860 ms
[root@k8s-master01 ~]# kubectl get pod -o wide 
NAME      READY   STATUS    RESTARTS       AGE     IP               NODE           NOMINATED NODE   READINESS GATES
busybox   1/1     Running   18 (28s ago)   7d18h   172.27.14.193    k8s-node02     <none>           <none>
web-0     1/1     Running   0              11m     172.18.195.18    k8s-master03   <none>           <none>
web-1     1/1     Running   0              11m     172.25.92.78     k8s-master02   <none>           <none>
web-2     1/1     Running   0              5m9s    172.25.244.199   k8s-master01   <none>           <none>

StatefulSet的擴容與縮容

StatefulSet擴容:

擴容的時候會按照序號順序依次建立,比如我有上圖的三個web副本,我想擴容到五個,那麼就會先建立web-3副本,只要web-3副本建立成功後才會建立web-4;如果web-3出現故障無法建立,那麼後續任務將一直等待web-3的建立直到成功。

StatefulSet縮容:

縮容的時候與擴容相反,會從最後一個開始刪除,按照web-4、web-3這樣的順序依次刪除。

StatefulSet更新策略

支援兩種更新策略:

RollingUpdate:預設的更新策略為捲動更新,是從最後一個副本開始更新,成功後才會進行下一個副本,更新方式為先刪除再建立。

OnDelete:當把策略改為這個時,我們就需要先手動刪除要更新的副本,才會觸發副本的更新策略。

StatefulSet灰度釋出

利用更新策略中的Partition引數進行簡單的灰度釋出。

StatefulSet的級聯刪除和非級聯刪除

級聯刪除:刪除StatefulSet時同時刪除Pod,預設為級聯刪除

[root@k8s-master01 ~]# kubectl delete sts web

非級聯刪除:刪除StatefulSet時不會刪除Pod,注意此時再刪除Pod的話就不會再重建了

[root@k8s-master01 ~]# kubectl delete sts web --cascade=false

以上就是通過StatefulSet部署有狀態服務應用實現方式的詳細內容,更多關於StatefulSet部署有狀態服務的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com