StatefulSet 完全指南
StatefulSet 是 Kubernetes 专门管理"有状态服务"的控制器。 提供稳定网络标识、独立持久化存储、有序部署与滚动更新三大核心能力, 是数据库(MySQL/Redis/Kafka/ZK)等有状态应用在 K8s 上的标准运行方式。
与 Deployment 的本质区别
| 特性 | Deployment | StatefulSet |
|---|---|---|
| Pod 名称 | 随机哈希(nginx-abc123) |
有序编号(web-0, web-1, web-2) |
| Pod 重建名称 | 新随机名 | 不变 |
| 存储 | 共享 PVC 或无 | 每个 Pod 独立 PVC(volumeClaimTemplates) |
| 启动/删除顺序 | 无序并行 | 有序(0→1→2 创建,2→1→0 删除) |
| 网络标识 | 通过 Service 负载均衡访问 | 每个 Pod 有固定 DNS 名称 |
| 适用场景 | Web/API/无状态服务 | 数据库/中间件/有状态服务 |
三大核心特性
① 稳定网络标识
Pod 命名格式:{statefulset-name}-{ordinal-index},如 mysql-0、mysql-1。
即使 Pod 被删除重建,新 Pod 继承同一名称和序号,DNS 记录自动更新指向新 IP。
必须搭配 Headless Service(clusterIP: None)使用:
apiVersion: v1
kind: Service
metadata:
name: my-headless-svc
spec:
clusterIP: None
selector:
app: my-app
ports:
- port: 80
Headless Service 不做负载均衡,DNS 查询 my-headless-svc 返回所有 Ready Pod 的 IP 列表。
可通过 pod-name.service-name.namespace.svc.cluster.local 直接访问特定 Pod。
② 稳定存储(volumeClaimTemplates)
为每个 Pod 自动创建独立 PVC,PVC 名称与 Pod 序号绑定:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage: 10Gi
PVC 命名规则: {volumeClaimTemplate-name}-{statefulset-name}-{ordinal-index}
- Pod
mysql-0→ PVCdata-mysql-0 - Pod
mysql-1→ PVCdata-mysql-1
Pod 被删除重建后,新 Pod 自动绑定到同名 PVC,数据不丢失。
底层存储机制参见 k8s-persistent-storage-guide(PV/PVC/StorageClass 原理与生产配置)。
③ 有序部署与滚动更新
StatefulSet 的滚动更新策略与 Deployment 不同:默认 OrderedReady(序号从大到小)。详见 k8s-rolling-update-pitfalls(滚动更新与非无损发布误区对比)。
- 创建顺序: 从 0 开始,前一个 Pod Ready 后创建下一个
- 删除顺序: 从最大序号开始,前一个完全终止后删除下一个
- 滚动更新: 默认 OrderedReady(序号从大到小),支持
OnDelete策略
# 查看 Pod 序号标签
kubectl get pod -L apps.kubernetes.io/pod-index
# 通过 DNS 直接访问特定副本
kubectl run test --image=busybox -- nslookup mysql-0.mysql.default.svc.cluster.local
# 查看 StatefulSet 状态
kubectl rollout status sts/<name>
为什么数据库必须用 StatefulSet
以 MySQL 主从为例,对比 Deployment 和 StatefulSet:
Deployment 的问题:
- Pod 重建后名字变了 → 主从关系乱掉
- 没有独立 PVC → 数据随 Pod 销毁
- 启动顺序不可控 → master/slave 可能同时启动
StatefulSet 的解决方案:
mysql-0固定为主节点,mysql-1/2固定为从节点- 独立 PVC 保证数据持久化
- 有序启动保证主节点先就绪
- 每个节点有稳定 DNS 名称,配置
replicate-from直接写mysql-0.svc
适用有状态应用的完整清单:MySQL、PostgreSQL、Redis Cluster、Kafka、Zookeeper、Elasticsearch、MongoDB、Cassandra。
关于有状态应用上 K8s 的完整权衡,参见 database-on-kubernetes-debate。
StatefulSet 排障
StatefulSet 的 Pod 排障与 Deployment 基本一致,但需特别关注:
- PVC 未绑定 → Pod Pending:
kubectl describe pod可看到pod has unbound immediate PersistentVolumeClaims - 数据迁移: 直接替换 PV/PVC 关联,不要直接操作 Pod
- 回滚更新:
kubectl rollout undo sts/<name> - 缩减副本: StatefulSet 缩减时按序号从大到小删除,数据 PVC 不会自动删除(安全机制)
参见 pod-troubleshooting 了解通用 Pod 排障方法,storage-troubleshooting 了解存储相关排障。
核心组件总结
| 组件 | 作用 |
|---|---|
| Headless Service (clusterIP: None) | 不做负载均衡,直接解析到 Pod IP;提供每个 Pod 的独立 DNS 名称 |
| volumeClaimTemplates | 自动为每个 Pod 创建独立 PVC,数据与 Pod 生命周期解耦 |
| 有序控制机制 | StatefulSet Controller 按序号顺序创建/删除/更新,保证先后顺序 |
关联页面
| 页面 | 关联点 |
|---|---|
| jenkins-multi-master-k8s-deployment | Jenkins 多 Master + K8S 部署方案,与 StatefulSet 配合使用 |
| k8s-architecture-core-concepts | K8s 架构与核心概念深度教程(组件原理/资源对象/工作负载) |