五、K8S-StatefulSet(STS有状态服务)

发布时间:2024年01月12日

StatefulSet详解

一、介绍

????????RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是管理所有有状态的服务,比如MySQL、MongoDB集群等。

????????StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。

????????在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。

????????除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,

这个域名的格式为:statefulSetName-{0…N-1}.serviceName.namespace.svc.cluster.local
1、statefulSetName为StatefulSet的名字
2、0..N-1为Pod所在的序号,从0开始到N-1
3、serviceName为Headless Service的名字
4、namespace为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace
5、.svc.cluster.local为Cluster Domain

二、特点

  1. 有序的滚动更新
  2. 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  3. 有序收缩,有序删除(即从N-1到0)
  4. 稳定的网络:Pod的hostname模式为( s t a t e f u l s e t 名 称 ) ? (statefulset名称)-(statefulset名称)?(序号);
  5. 稳定的持久化存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。

三、组成部分

  • Headless Service:(无头服务)用于为Pod资源标识符,生成可解析的DNS记录
  • volumeClaimTemplates :存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应;
  • StatefulSet :用于管控Pod资源

四、使用演示

创建顺序如下:
1、Volume
2、Persistent Volume
3、Persistent Volume Claim
4、Service
5、StatefulSet

一个完整的StatefulSet由一个Headless Service、一个StatefulSet、和一个volumeClaim Template组成。

#StatefulSet  资源清单
[root@k8s-master mainfests]# vim stateful-demo.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  labels:
    app: myapp-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: myapp-pod
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp-svc #声明它属于哪个Headless Service.
  replicas: 3#副本数
  selector:#那个pod 是由自己管理的
    matchLabels:
      app: myapp-pod  #必须匹配 .spec.template.metadata.labels
  template:#定义pod模板
    metadata:
      labels:
        app: myapp-pod # 必须配置 .spec.selector.matchLabels
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: myappdata
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates: #生成PVC模板
  - metadata:
      name: myappdata
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

创建Headless Service和StatefulSet,并进行解析验证

再打开一个界面 #kubectl  get pods  -w -lapp=demo-nginx  使用 -w -l 实时查看创建过程
[root@k8s-master-1 test]# kubectl apply -f statefulSet.yaml 
service/demo-service created
statefulset.apps/demo-statefulset created
#创建成功之后就可以看到service以及创建的3个pod
[root@k8s-master-1 test]# kubectl get service
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
demo-service   ClusterIP   None         <none>        80/TCP         2m24s
[root@k8s-master-1 test]# kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
busybox               1/1     Running   61         9d
demo-statefulset-0    1/1     Running   0          4m13s
demo-statefulset-1    1/1     Running   0          4m12s
demo-statefulset-2    1/1     Running   0          4m10s
#检查状态   发现StatefulSet给他所管理的pod的名字,进行了编号,pod的hostname与Pod的名字一致。
[root@k8s-master-1 test]# kubectl exec demo-statefulset-0 -- sh -c 'hostname'
demo-statefulset-0
[root@k8s-master-1 test]# kubectl exec demo-statefulset-1 -- sh -c 'hostname'
demo-statefulset-1
[root@k8s-master-1 test]# kubectl exec demo-statefulset-2 -- sh -c 'hostname'
demo-statefulset-2
[root@k8s-master-1 test]#
#验证DNS
#进入一个容器,可以看到已经被成功解析
[root@k8s-master-1 test]# kubectl exec -it busybox sh
/ # 


/ # nslookup demo-service
Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local

Name:      demo-service
Address 1: 10.244.0.72 demo-statefulset-0.demo-service.default.svc.cluster.local
Address 2: 10.244.0.73 demo-statefulset-2.demo-service.default.svc.cluster.local
Address 3: 10.244.1.61 demo-statefulset-1.demo-service.default.svc.cluster.local
#单独解析
/ # 
/ # nslookup demo-statefulset-0.demo-service.default.svc.cluster.local
Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local

Name:      demo-statefulset-0.demo-service.default.svc.cluster.local
Address 1: 10.244.0.95 demo-statefulset-0.demo-service.default.svc.cluster.local
/ # 
/ # nslookup demo-statefulset-1.demo-service.default.svc.cluster.local
Server:    10.0.0.2
Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local

Name:      demo-statefulset-1.demo-service.default.svc.cluster.local
Address 1: 10.244.1.77 demo-statefulset-1.demo-service.default.svc.cluster.local
/ # 
/ # ping 也是可以ping通的 

/ # ping demo-statefulset-0.demo-service.default.svc.cluster.local
PING demo-statefulset-0.demo-service.default.svc.cluster.local (10.244.0.95): 56 data bytes
64 bytes from 10.244.0.95: seq=0 ttl=62 time=0.315 ms
64 bytes from 10.244.0.95: seq=1 ttl=62 time=0.274 ms
64 bytes from 10.244.0.95: seq=2 ttl=62 time=0.267 ms
/ # 

/ # exit
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl get pod -owide
NAME                  READY   STATUS    RESTARTS   AGE    IP            NODE         NOMINATED NODE   READINESS GATES
busybox               1/1     Running   62         9d     10.244.1.57   k8s-node-2   <none>           <none>
demo-statefulset-0    1/1     Running   0          23m    10.244.0.72   k8s-node-1   <none>           <none>
demo-statefulset-1    1/1     Running   0          23m    10.244.1.61   k8s-node-2   <none>           <none>
demo-statefulset-2    1/1     Running   0          23m    10.244.0.73   k8s-node-1   <none>           <none>
web-96d5df5c8-sw784   1/1     Running   5          5d1h   10.244.0.69   k8s-node-1   <none>           <none>

滚动更新时,把这几个 Pod 删除之后,Kubernetes 会按照原先编号的顺序,创建出了两个新的 Pod。并且,
Kubernetes 依然为它们分配了与原来相同的“网络身份”:demo-statefulset-0 ,demo-statefulset-1 和demo-statefulset-2。
通过这种严格的对应规则,StatefulSet 就保证了 Pod 网络标识的稳定性。

总结:

????????Kubernetes成功的将Pod的拓扑状态,按照Pod的名字+编号的方式固定下来,此外Kubernetes还为每个pod提供了一个固定并且唯一的访问入口,即:这个Pod对应额DNS记录,这些状态,在StatefulSet的整个生命周期里都保持不变,绝不会因为pod的删除或者重新创建而时效。

????????当StatefulSet的控制循环发现pod 的实际状态于“期望状态”不一致时,需要新建或者删除POD进行调谐的时候, 会严格按照pod的编号顺序,逐一完成操作。

五、存储状态

????????Kubernetes项目引入了一组叫做 Persistent Volume Clain(PVC)和 Persistent Volume(PV)的API对象,大大降低了用户声明和使用持久化Volume的门槛。

????????PVC :PVC就是一种特殊的Volume,只不过一个PVC具体是什么类型的Volume,要在跟某个PV绑定之后才知道,这些PVC,都以“--”的方式命名并且处于Bound状态,这个StatefulSet创建出来的多有pod,都会声明使用编号的PVC.?

六、statefulSet更新策略

????????statefulSet支持两种更新策略:OnDelete和人rollingUpdate(默认),其中Ondelete表示删除之后才更新,RollingUpdate是滚动更新

  1. RollingUpdate:更新策略是从序号的最大数开始依次往前更新,如果更新过程中,前边的pod发生率变化,会暂停更新,等pod状态正常之后,在继续更新。
  2. OnDelete:当type被设置为OnDelete时,StatefulSet并不会自动更新,而是通过手动删除pod之后,才会触发创建新的pod实例来弥补,就是一种手动升级模式。
  3. Partitioned:updateStrategy也支持特殊的分区升级策略,在这种模式下,用户指定一个序号,StatefulSet中序号大于等于此序号的pod实例会全部升级,小于此序号的则被保留旧版本,即使这些pod 被删除,重建,也仍然保持原来的旧版本,这种分区升级的策略通常用于按计划分步骤的系统升级过程
updateStrategy:
  rollingUpdate: # 如果更新的策略是OnDelete,那么rollingUpdate就失效
    partition: 2 # 表示从第2个分区开始更新,<2的pod 不会被更新。默认是0,
  type: RollingUpdate /OnDelete # 滚动更新

七、statefulSet扩缩容

#扩容语法:kubectl scale sts <statefulsetPodName> --replicas=5
[root@k8s-master-1 test]# kubectl scale sts demo-statefulset --replicas=5
statefulset.apps/demo-statefulset scaled
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
busybox               1/1     Running   5          22h
demo-statefulset-0    1/1     Running   0          109s
demo-statefulset-1    1/1     Running   0          108s
demo-statefulset-2    1/1     Running   0          106s
demo-statefulset-3    1/1     Running   0          4s
demo-statefulset-4    1/1     Running   0          3s
web-96d5df5c8-sw784   1/1     Running   6          6d1h

#缩容
[root@k8s-master-1 test]# kubectl scale sts demo-statefulset --replicas=3
statefulset.apps/demo-statefulset scaled
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE
busybox               1/1     Running   5          22h
demo-statefulset-0    1/1     Running   0          5m35s
demo-statefulset-1    1/1     Running   0          5m34s
demo-statefulset-2    1/1     Running   0          5m32s
web-96d5df5c8-sw784   1/1     Running   6          6d1h

#查看标签
[root@k8s-master-1 test]# kubectl get pod --show-labels
#查看详细执行过程
[root@k8s-master-1 ~]# kubectl get pod -w -l app=demo-nginx

八、StatefulSet级联删除(默认)和非级联删除

  1. 级联删除:就是删除sts时也删除pod
  2. 非级联删除:就是删除sts时不删除pod
[root@k8s-master-1 test]# #级联删除
[root@k8s-master-1 test]# kubectl delete sts demo-statefulset
statefulset.apps "demo-statefulset" deleted
[root@k8s-master-1 test]# #非级联删除
[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl delete sts demo-statefulset --cascade=false
statefulset.apps "demo-statefulset" deleted
[root@k8s-master-1 test]# 

[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl get sts
No resources found in default namespace.

[root@k8s-master-1 test]# 
[root@k8s-master-1 test]# kubectl get pod
NAME                  READY   STATUS    RESTARTS   AGE

demo-statefulset-0    1/1     Running   0          118s
demo-statefulset-1    1/1     Running   0          117s
demo-statefulset-2    1/1     Running   0          115s

 #此时pod就成了孤儿pod,删除pod时不会被重建,如果不是非级联删除,单独删除pod则回被重新创建。

文章来源:https://blog.csdn.net/weixin_42171272/article/details/135439687
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。