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

ops/2025/3/17 19:03:30/

      • 一、核心特性
      • 二、架构与组件
      • 三、生命周期管理
      • 四、典型应用场景**
      • 五、注意事项与最佳实践
      • 六、对比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过程中常见异常处理


http://www.ppmy.cn/ops/166592.html

相关文章

vscode 导入语句排序和删除未使用的导入

vscode 自带的格式化 vscode 默认支持导入语句排序和删除未使用的导入。 对应的配置是&#xff1a;source.organizeImports 可选值&#xff1a; never&#xff1a;关闭explicit&#xff1a;仅在显式手动保存时触发always&#xff1a;自动保存时也会触发 我喜欢在手动 Ctrl…

算法专题一:双指针

1.移动零 题目链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 我们可以定义一个dest&#xff0c;一个cur&#xff0c;dest表示数组中不为零的数的最后一位&#xff0c;cur用来遍历数组 class Solution {public void moveZeroes(int[] nums) {for(int cur…

Unity打包Android平台调用sherpa-onnx

https://github.com/xue-fei/sherpa-onnx-unity 最初测试了PC的Win和Linux平台&#xff0c;直接从nuget缓存包中拷贝相关文件&#xff0c;按示例写了语音转文字和文字转语音的测试代码&#xff0c;功能都正常。 然后是Android端&#xff0c;看了示例发现有编译好的jni.so之类的…

重生之我在学Vue--第14天 Vue 3 国际化(i18n)实战指南

重生之我在学Vue–第14天 Vue 3 国际化(i18n)实战指南 文章目录 重生之我在学Vue--第14天 Vue 3 国际化(i18n)实战指南前言一、Vue I18n 核心配置1.1 基础环境搭建1.2 初始化配置1.3 全局挂载 二、多语言实现方案2.1 基础使用2.2 动态切换语言2.3 高级功能实现复数处理日期/货币…

sql靶场--布尔盲注(第八关)保姆级教程

目录 布尔盲注&#xff08;第八关&#xff09; 1.判断 2.确认布尔盲注 3.手工尝试布尔盲注 表名字符 表数 表名长度 表字符 字段数 字段名长度 字段字符 4.脚本布尔盲注注入 布尔盲注&#xff08;第八关&#xff09; 1.判断 布尔盲注了&#xff0c;这种页面只会有…

考研408-数据结构完整代码 线性表的顺序存储结构 - 顺序表

线性表的顺序存储结构 - 顺序表 1. 顺序表的定义 ​ 用一组地址连续的存储单元依次存储线性表的数据元素&#xff0c;从而使逻辑上相邻的两个元素在物理位置上也相邻 2. 顺序表的特点 随机访问&#xff1a; 即通过首地址和元素序号可以在O(1) 时间内找到指定元素&#xff0…

设计模式(行为型)-备忘录模式

目录 定义 类图 角色 角色详解 &#xff08;一&#xff09;发起人角色&#xff08;Originator&#xff09;​ &#xff08;二&#xff09;备忘录角色&#xff08;Memento&#xff09;​ &#xff08;三&#xff09;备忘录管理员角色&#xff08;Caretaker&#xff09;​…

django 运行时仅显示500 但是不提示其他内容 如何令其显示更多错误信息

在 Django 中&#xff0c;当发生 500 错误时默认仅显示简单的错误页面&#xff08;不包含堆栈跟踪等详细信息&#xff09;&#xff0c;这通常是因为 生产环境配置禁用了调试模式&#xff08;DEBUG False&#xff09;。以下是逐步解决方案&#xff0c;帮助你显示更详细的错误信…