欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > 【一起来学kubernetes】14、StatefulSet使用详解

【一起来学kubernetes】14、StatefulSet使用详解

2025/3/17 11:40:26 来源:https://blog.csdn.net/zhangzehai2234/article/details/146304006  浏览:    关键词:【一起来学kubernetes】14、StatefulSet使用详解

      • 一、核心特性
      • 二、架构与组件
      • 三、生命周期管理
      • 四、典型应用场景**
      • 五、注意事项与最佳实践
      • 六、对比Deployment
        • 一、应用场景
        • 二、Pod管理
        • 三、部署与更新策略
        • 四、其他特性
      • 七、常见问题
      • 八、拓展

前文中我们介绍了k8s中常用的一种控制器 Deployment,与之向对应的,还有另外一种我们不太常用的控制器也是k8s的重要组成部分:StatefulSet,StatefulSet(有状态集,缩写为sts)是Kubernetes中用于部署和管理有状态应用程序的一种工作负载API对象。


一、核心特性

  1. 唯一标识与稳定性
    • 每个Pod分配唯一索引标识(如pod-0, pod-1),即使重启或迁移,标识不变。
    • 依赖Headless Service提供稳定DNS记录(如pod-0.example.com),确保客户端始终连接到同一实例。

StatefulSet是用来管理有状态应用的服务。和无状态的Deployment不同,StatefulSet需要保持每个Pod的唯一性和持久性。比如数据库、消息队列这样的应用,每个实例的数据都是独立的,不能随意替换或删除,这时候就需要StatefulSet来管理。

  1. 持久化存储
    • 通过volumeClaimTemplates自动生成独立的PersistentVolumeClaim(PVC),每个Pod拥有专属存储卷,数据持久化。

关于存储,每个Pod的volumeClaimTemplate会创建一个独立的PersistentVolumeClaim,确保数据隔离。如果使用本地存储的话,可能需要特别注意节点的可用性,否则数据可能会丢失。所以通常推荐使用云提供商的持久磁盘或者其他可靠的存储方案。

  1. 有序扩缩容
    • 扩容时按索引顺序创建新Pod(如从pod-2pod-N),缩容时逆序删除旧Pod(如先删pod-0),保障服务连续性。

  2. 滚动更新策略
    • 支持配置maxSurge(最大并发更新数)和maxUnavailable(最大不可用数),默认策略为逐个更新,减少对集群的影响。


二、架构与组件

StatefulSet Spec
定义Pod模板、副本数、服务名、标签选择器等关键参数:

apiVersion: apps/v1
kind: StatefulSet
metadata:name: my-database
spec:serviceName: "mysql-cluster" # 对应的Headless Service名称replicas: 3selector:matchLabels:app: mysqltemplate:metadata:labels:app: mysqlspec:containers:- name: mysqlimage: mysql:5.7volumeMounts:- name: db-datamountPath: /var/lib/mysqlvolumeClaimTemplates:- metadata:name: db-dataspec:accessModes:- ReadWriteOnceresources:requests:storage: 100Gi

Headless Service
自动创建无集群IP的Service,暴露所有Pod的DNS记录:

apiVersion: v1
kind: Service
metadata:name: mysql-cluster
spec:clusterIP: Noneselector:app: mysql
  • PersistentVolume Provisioner
    Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置。这是为了确保Pod在重新调度时能够访问到相同的持久化数据。

PersistentVolume Provisioner的配置通常涉及创建StorageClass对象,该对象定义了动态卷供应的参数和配置。以下是一个基于YAML的配置示例,展示了如何配置一个使用AWS EBS作为后端存储的PersistentVolume Provisioner。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: standard
provisioner: kubernetes.io/aws-ebs
parameters:type: gp2reclaimPolicy: Delete
volumeBindingMode: Immediate

在这个例子中:

  • apiVersion 指定了Kubernetes API的版本,这里是storage.k8s.io/v1
  • kind 指定了这是一个StorageClass对象。
  • metadata.name 是这个StorageClass的名称,这里是standard
  • provisioner 指定了动态供应器的名称,这里是kubernetes.io/aws-ebs,表示使用AWS EBS作为后端存储。
  • parameters 部分包含了供应器特定的参数:
    • type 指定了EBS卷的类型,这里是gp2(通用型SSD)。
    • reclaimPolicy 指定了当PersistentVolume被删除时,后端存储的回收策略。这里是Delete,表示删除PV时也会删除对应的EBS卷。
    • volumeBindingMode 设置了卷绑定模式,这里是Immediate,表示在PVC创建时立即绑定PV。

请注意,这个配置示例是针对AWS EBS的。如果你使用其他类型的存储,比如NFS、Ceph等,你需要相应地更改provisionerparameters部分。

例如,如果你使用NFS作为后端存储,你的StorageClass配置可能看起来像这样:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: nfs-storage
provisioner: example.com/nfs
parameters:path: /exports/dataserver: nfs-server.example.com

在这个NFS示例中:

  • provisioner 被设置为一个假想的NFS供应器名称example.com/nfs(在实际使用中,你需要替换为实际的NFS供应器名称)。
  • parameters 部分包含了NFS服务器的地址和共享路径。

要应用这个YAML配置,你可以使用kubectl create -f <filename>.yaml命令,其中<filename>.yaml是你的YAML文件的名称。例如:

kubectl create -f storageclass-nfs.yaml

这将创建一个名为nfs-storage的StorageClass对象,用于动态供应NFS类型的PersistentVolumes。请确保你的Kubernetes集群已经配置了相应的动态供应器,并且该供应器能够访问你指定的后端存储。


三、生命周期管理

StatefulSet的生命周期管理。当增加或减少副本时,它会按顺序创建或删除Pod,确保旧的Pod先下线,新的Pod再上线,这样可以避免服务中断。而Deployment则是并行更新的,可能导致短暂的服务不可用。不过,这也要看具体的更新策略设置是否正确。主要的步骤有如下的几步:

  1. 创建与扩展
    • 执行kubectl apply -f statefulset.yaml创建资源。
    • 扩容:kubectl scale statefulset my-database --replicas=5,按索引顺序新增Pod。

  2. 更新与滚动机制
    • 修改Pod镜像触发更新,新Pod按索引顺序启动,旧Pod逐步终止。
    • 可观察kubectl describe statefulset中的UpdateStrategyProgress

  3. 删除与清理
    • 缩容至0后删除StatefulSet,自动清理关联的PVC(需设置storageClassName并配置回收策略)。


四、典型应用场景**

  1. 数据库集群(MySQL、MongoDB、 ClickHouse)
    每个Pod作为独立数据库实例,数据持久化且可通过稳定域名连接。

  2. 消息队列(Kafka、RabbitMQ, RocketMq)
    Broker节点需要唯一标识和持久存储,确保分区和数据的分布一致性。

  3. 缓存系统(Redis Cluster)
    实例间需协同工作,StatefulSet帮助管理节点位置和故障转移。

StatefulSet的应用场景,除了数据库,像Redis集群、Kafka这样的分布式系统也可能用到。例如,Kafka的Broker需要每个实例对应不同的分区,这时候StatefulSet可以方便地管理和扩展。


五、注意事项与最佳实践

  1. 存储配置
    • 使用StorageClass动态供应PVC,避免手动创建。
    • 根据业务需求设置accessModes(如ReadWriteOnceReadWriteMany)。

  2. 更新策略
    • 生产环境建议设置maxUnavailable: 1,防止大规模宕机:

    updateStrategy:type: RollingUpdaterollingUpdate:maxSurge: 1maxUnavailable: 1
    
  3. 监控与调试
    • 使用kubectl get pods -w观察Pod状态变化。
    • 结合Prometheus监控存储使用率和Pod健康状态。

监控和维护方面,可能需要关注StatefulSet的状态,比如当前有多少个Pod处于就绪状态,是否有重建或升级正在进行。同时,需要定期检查每个Pod的日志和健康状况,确保数据的一致性和服务的稳定性。

  1. 高可用性
    • 配合Deployment部署StatefulSet控制器,实现自我修复。
    • 在多可用区部署时,结合云厂商的托管数据库服务(如AWS RDS)。

六、对比Deployment

特性StatefulSetDeployment
网络标识稳定DNS(pod-0.example.com)随机IP(pod-a.example.com)
存储每个Pod独立PVC共享Volume或无存储
扩缩容顺序有序(索引递增/递减)无序
适用场景数据库、消息队列等有状态应用无状态微服务、批处理任务

StatefulSet与Deployment都是Kubernetes中用于管理Pod的资源对象,但它们的设计目的和服务场景有所不同。以下是StatefulSet与Deployment的主要区别:

一、应用场景
  1. Deployment

    • 主要用于管理无状态应用。
    • 无状态应用通常不需要持久化数据或唯一网络标识符。
    • Deployment提供了一种简单的方式来部署和更新应用,支持滚动更新和回滚。
  2. StatefulSet

    • 主要用于管理有状态应用。
    • 有状态应用需要持久化数据或具有唯一网络标识符。
    • StatefulSet提供了持久化存储和稳定的网络标识符,适用于需要保持数据完整性和服务身份的应用。
二、Pod管理
  1. Pod命名与标识

    • Deployment:Pod名称是随机生成的,没有固定的顺序或标识。每个Pod都是可替换的,具有相同的配置和环境。
    • StatefulSet:Pod名称是基于索引的,具有固定的顺序和标识。每个Pod都有一个唯一的、持久的身份标识。
  2. 存储

    • Deployment:Pod通常共享存储卷,但这不适用于有状态应用,因为数据可能会相互干扰。
    • StatefulSet:每个Pod可以有独自的存储卷,通常与PersistentVolumeClaim(PVC)结合使用,以确保数据的持久化和隔离。
  3. 网络标识符

    • Deployment:Pod没有稳定的网络标识,通常通过Service进行通信。
    • StatefulSet:Pod具有稳定的网络标识,如DNS名称,可以通过Headless Service精确访问到每一个Pod。
三、部署与更新策略
  1. 部署

    • Deployment:通过ReplicaSet管理Pod的副本数,支持滚动更新策略,允许逐个替换Pod以保持服务的可用性。
    • StatefulSet:支持有序的创建和删除Pod,这在需要特定顺序执行初始化脚本或清理操作的情况下非常有用。StatefulSet不直接支持滚动更新,因为需要考虑数据的一致性和服务的连续性,更新过程通常需要更谨慎的操作,可能需要手动干预。
  2. 回滚

    • Deployment:支持自动回滚和暂停/恢复更新。
    • StatefulSet:更新过程需要更谨慎的操作,回滚也可能需要手动管理。
四、其他特性
  • Deployment:适用于Web应用服务器、微服务以及任何不需要持久化数据或特定网络标识的应用。
  • StatefulSet:适用于数据库集群(如MySQL、Cassandra)、分布式缓存系统(如Redis集群)以及任何需要持久化数据或特定网络标识的应用。

Deployment和StatefulSet各有其适用场景和特性。在选择使用哪个资源对象时,应根据应用的具体需求进行考虑。对于无状态应用,使用Deployment可以提供简便的部署和更新流程;而对于有状态应用,使用StatefulSet可以确保数据的安全性和服务的连续性。


七、常见问题

Q: Pod无法获取唯一标识?
A: 确保serviceName正确,并检查Headless Service的DNS解析是否正常。

Q: 数据丢失怎么办?
A: 验证PVC的reclaimPolicy(如DeleteRetain),并检查备份策略。

Q: 更新过程中服务中断?
A: 调整maxUnavailablemaxSurge,或采用蓝绿部署替代滚动更新。


通过合理利用StatefulSet,开发者可以高效管理复杂的有状态应用,确保数据的可靠性和服务的稳定性。理解其底层机制和最佳实践,是构建健壮Kubernetes集群的关键一步。

八、拓展

【一起来学kubernetes】11、Deployment使用详解

【一起来学kubernetes】13、k8s中的controller的前世今生

【一起来学kubernetes】0、通过yum安装k8s过程中常见异常处理

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词