返回首页

StatefulSet 完全指南 — 稳定网络标识 / 独立存储 / 有序部署

📅 创建于 2026-05-11 🔄 更新于 2026-05-19 📝 420 字

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-0mysql-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 → PVC data-mysql-0
  • Pod mysql-1 → PVC data-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-deploymentJenkins 多 Master + K8S 部署方案,与 StatefulSet 配合使用
k8s-architecture-core-conceptsK8s 架构与核心概念深度教程(组件原理/资源对象/工作负载)