StatefulSet-有状态pod副本集管理

StatefulSet用于管理有状态的Pod副本集,与deployment管理的无状态pod区别在于: 有状态意味着每个pod副本都具有唯一不变的身份标识,例如:id或者服务名称,多个Pod副本不是对等无差别的,而是相互之间可能需要通信来实现某种功能,每个Pod需要独立的持久化存储(保存日志或者数据等),以及多个pod可能需要按照固定的顺序逐个启动等业务需求

StatefulSet会为有状态pod副本集提供一下功能:

  • 每个pod具有唯一且不变的身份标识,包括ID和网络访问地址
  • 每个pod都配置稳定的持久化存储
  • 对多个Pod提供有序的,优雅的部署和扩缩容等管理功能
  • 对多个Pod提供有序的,优雅的滚动更新等管理功能

使用StatefulSet也存在以下一些限制

  • 为每个Pod配置的持久化存储必须是PVC类型的共享存储
  • 删除pod不会删除后端关联的存储,需要手动删除存储数据
  • 必须创建一个Headless Service(无头服务),用于创建每个Pod的网络访问地址
  • 删除StatefulSet资源时,不保证pod会终止,如要优雅删除,可将Pod副本缩容为0然后删除
  • 使用OrderedReady策略执行滚动更新时,可能存在某个pod损坏,不能Ready状态,需要手动修复

1、下面例子为一个完整的有状态pod副本集,如下:

apiVersion: apps/v1
kind: StatefulSet 
metadata:
  name: busybox-stateful
spec:
  selector:
    matchLabels:
      app: busybox
  replicas: 2
  serviceName: "busybox-service"
  minReadySeconds: 10
  template:
    metadata:
      labels:
        app: busybox
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: [ "sh","-c","sleep 3600" ]
        ports:
        - containerPort: 80
        volumeMounts:
        - name: busybox-volume
          mountPath: /usr/share/busybox
          subPath: busybox
  volumeClaimTemplates:
  - metadata:
      name: busybox-volume
    spec:
      storageClassName: "nfs-storage"
      accessModes: [ "ReadWriteOnce" ]
      resources:
         requests:
           storage: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  name: busybox-service
  labels:
    app: busybox
spec:
  selector:
    app: busybox
  clusterIP: None
  ports:
  - port: 80
  • serviceName:指向一个无头服务,就是最下面创建的Service
  • minReadySeconds:pod最短就绪时间,达到这个时间后才会设置pod为Ready状态,默认为0
  • terminationGracePeriodSeconds 是容器优雅终止的宽限期,定义 Pod 被删除时 Kubernetes 等待容器正常退出的最长时间,默认值为30s,时间到了后容器会被强制删除
  • volumeClaimTemplates:后端存储的PVC模板
  • clusterIP: None 定义为一个无头服务

创建完成后可以看到pod的命名规则为:由statefulset名称和序号组成,中间用”-“连接,默认序号从0开始,这个完整的pod名字也将作为pod内容器的主机名,如图:

从1.26版本开始,引入了新字段spec.ordinals.start,可用于自定义pod的起始起始序号,比如设置为5,那么创建pod后将会变成busybox-stateful-5开始,如图:

2、StatefulSet会将Headless Service名称和Pod名称组合为pod的访问地址,以DNS域名格式表示,完整的域名格式为:<pod-name>.<service-name>.<namespace.svc>.<clusterDomain>,可通过nslookup工具验证,如图:

在同个K8s集群中,其他的Pod都可以通过此域名来访问StatefulSet中的pod,并且系统会保证此域名是一直不变,即使pod被重建,pod名称,服务域名都不会变,只有Pod的IP地址会变

3、StatefulSet删除机制

StatefulSet支持级联方式删除全部Pod和非级联方式保留Pod,默认是级联模式,通过kubectl delete命令的时候,指定参数–cascade=orphan=true 来禁止使用级联模式

4、StatefulSet扩缩容

kubectl scale statefulset statefulset-name --replicas=5 #可执行此命令实现副本增加减少

5、更新策略

  • RollingUpdate:滚动更新,默认
  • OnDelete:需要手动删除全部pod,触发statefulset controller来重新创建pod

标签