StatefulSet 是什么
StatefulSet 面向有状态应用,提供两类稳定性:稳定的网络标识,Pod 名字固定为 名称-0、名称-1 依次递增,重建后名字不变;稳定的存储,通过 volumeClaimTemplates 为每个 Pod 生成独立的 PVC,重新调度后仍然挂回自己的数据卷。默认按序号串行创建与删除,前一个就绪后才处理下一个。它必须搭配 Headless Service 才能获得稳定的 DNS 记录,这是与 Deployment 最本质的区别。
基本信息
| 稳定网络标识 | Pod 名为 <sts>-0、<sts>-1,重建后名字保持不变 |
|---|---|
| 稳定存储 | volumeClaimTemplates 为每个 Pod 生成独立 PVC |
| 顺序控制 | 默认 OrderedReady 串行建删;podManagementPolicy: Parallel 可改为并行 |
| DNS 依赖 | 需要 serviceName 指向 Headless Service,否则没有稳定域名 |
| 扩缩容行为 | 缩容按序号从大到小删除;数据卷默认保留不清除 |
典型使用场景
- 数据库集群:MySQL 主从、PostgreSQL 高可用依赖固定的实例标识与各自的数据目录
- 分布式协调与消息组件:ZooKeeper、Kafka 需要节点身份与序号稳定才能正确选主
- 有状态中间件:Redis Cluster、Elasticsearch 需要每实例独立持久卷
- 需要为每个实例单独配置的场景,例如每个副本独立的证书与配置项
- 对端需要按固定域名逐台指名的系统对接,例如上游按节点地址分发任务
StatefulSet 示例
StatefulSet 示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: db
spec:
serviceName: db-headless # 指向 Headless Service,提供稳定 DNS
replicas: 3
selector:
matchLabels: { app: db }
template:
metadata:
labels: { app: db }
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
与 Deployment 对比
| 维度 | Deployment | StatefulSet |
|---|---|---|
| Pod 命名 | 随机后缀,重建后名字变化 | 固定序号,重建后名字不变 |
| 存储 | 通常共享卷或无状态 | 每 Pod 独立 PVC,跟随身份 |
| 启动顺序 | 并行滚动,不保证次序 | 默认按序号串行 |
| 服务发现 | 普通 Service 负载均衡 | 配合 Headless Service 提供稳定域名 |
| 适用对象 | 无状态服务、Web API | 数据库、消息队列、有状态中间件 |
删除 StatefulSet 不会自动删除 PVC:数据默认保留,这既是安全特性,也解释了『删了工作负载为什么存储空间没释放』,需要手工确认后再清理 PVC。
缩容时 Pod 按序号从大到小删除且 PVC 默认保留:再次扩容时旧的卷会被重新挂载,可能读到过期或半同步的数据,扩容前要确认数据同步状态。