StatefulSet 2

答案是:

StatefulSet 不使用 ReplicaSet 来创建 Pod。 ✅ StatefulSet Controller 直接创建并管理 Pod 对象,而且每个 Pod 都是有序的、具名的、不可替代的。

接下来我会详细讲清楚 StatefulSet 与 Deployment 的架构差异、实现机制、核心控制循环,让你能在实现 Operator 或高可靠应用时真正理解它的行为。


🧩 一、StatefulSet 与 Deployment 的根本区别

项目DeploymentStatefulSet
控制下层对象ReplicaSet → Pod直接管理 Pod
Pod 命名随机固定命名(有序索引)
Pod 身份可替换唯一、持久身份(Stable Identity)
更新策略滚动更新(无序)有序更新(从 0 开始逐个)
存储通常无状态绑定 PVC,数据与 Pod 一一对应
常见场景Web 服务、API、Job数据库、Zookeeper、Kafka、Etcd 等

⚙️ 二、StatefulSet 控制器工作原理

StatefulSet Controller 运行在 kube-controller-manager 中。 它同样是一个典型的 Controller + Informer + WorkQueue + Reconcile Loop 架构。

但是它的 核心循环逻辑 与 Deployment/ReplicaSet 明显不同:

1️⃣ Reconcile 流程概览

伪代码如下:

syncStatefulSet(set):
    pods := listPodsMatching(set.selector)
    sortPodsByOrdinal(pods)

    for i in 0..set.spec.replicas-1:
        ensurePodExists(set, ordinal=i)
        ensurePodPVCExists(set, ordinal=i)
        if updateRequired(set, pod[i]):
            deletePodAndWaitForReplacement(set, ordinal=i)

也就是说,StatefulSet controller 自己直接创建 Pod 和 PVC,并且顺序控制整个过程。


2️⃣ Pod 命名与序号机制

StatefulSet 会给每个 Pod 一个固定的命名模式:

<prefix>-<ordinal>

例如:

web-0
web-1
web-2

这些名字不是随机生成的 UID,而是根据序号确定的。 这让 Pod 可以拥有稳定的网络标识

  • Pod DNS:<podname>.<headless-service-name>.<namespace>.svc.cluster.local

  • 例如:

    web-0.web.default.svc.cluster.local
    web-1.web.default.svc.cluster.local

这对 Zookeeper、MySQL 集群等“节点必须有固定身份”的应用至关重要。


3️⃣ 存储(PVC)绑定机制

每个 StatefulSet Pod 都可以声明一个 volumeClaimTemplate

volumeClaimTemplates:
- metadata:
    name: data
  spec:
    accessModes: ["ReadWriteOnce"]
    resources:
      requests:
        storage: 10Gi

Controller 会为每个 Pod 创建一个独立的 PVC:

data-web-0
data-web-1
data-web-2

即使 Pod 被删除,这个 PVC 也不会被清理(除非手动删除), 这就实现了状态持久化


4️⃣ Pod 创建顺序与滚动更新顺序

StatefulSet 有严格的有序逻辑:

创建顺序

  • 先创建 web-0
  • web-0 变成 Running + Ready
  • 再创建 web-1
  • 依次类推。

删除顺序

  • 先删除最高序号 Pod;
  • 依次向下。

更新顺序(滚动更新)

  • 先更新最高序号 Pod;

  • 等该 Pod Ready 后,再更新下一个;

  • 可配置 podManagementPolicy

    • OrderedReady(默认,有序)
    • Parallel(并行)

5️⃣ StatefulSet 更新控制逻辑

当你修改 StatefulSet 的模板(例如更换镜像),控制器会:

  1. 比较 spec.template hash;
  2. 找出需要更新的 Pod;
  3. 按序更新;
  4. 每个 Pod 更新完毕、Ready 后,再进行下一个。

伪代码示例:

for i = replicas-1 downTo 0:
    if pod[i].template != set.template:
        delete(pod[i])
        waitUntilNewPodReady(i)

📦 三、StatefulSet 与 PVC 的生命周期

对象何时创建何时删除
Pod当 StatefulSet 第一次启动或扩容时缩容时(最高序号先删)
PVCPod 第一次被创建时不会自动删除(除非使用 StorageClass Retain 策略外的设置)

这意味着:

StatefulSet 的 数据持久性是通过 PVC 与序号绑定实现的

例如:

data-web-0 → 永远属于 web-0
data-web-1 → 永远属于 web-1

🔁 四、StatefulSet 的控制链路(事件流)

步骤执行者说明
用户kubectl apply 创建 StatefulSet
API Server写入 etcd
StatefulSet Controller检测 StatefulSet 对象变化
Controller创建第一个 Pod + PVC(ordinal=0)
Kubelet调度并运行容器
Controller检测 web-0 Ready 后,继续创建 web-1
直到所有 replicas Ready
更新按序滚动更新 Pod

🧠 五、StatefulSet 为什么不复用 ReplicaSet?

主要是因为 ReplicaSet 的特性与 StatefulSet 的设计目标相冲突:

功能ReplicaSetStatefulSet
Pod 匿名性✅ 所有 Pod 等价❌ 每个 Pod 唯一
更新无序性✅ 任意替换❌ 必须有序
PVC 管理❌ 无✅ 一一绑定
网络身份❌ 无✅ 稳定 DNS 名称

所以 Kubernetes 设计了专门的 StatefulSet Controller 来实现这一类“有状态副本控制”。


💡 六、StatefulSet 小结

特性描述
控制对象直接管理 Pod
Pod 命名固定命名(带序号)
更新策略有序(OrderedReady)或并行(Parallel)
持久化通过 PVC 一对一绑定
典型场景数据库、分布式存储、消息队列、协调服务等
优势稳定网络身份、持久存储、严格更新顺序
缺点扩缩容慢,调度受限,不适合无状态应用

🧭 七、视觉化理解(结构示意)

StatefulSet: kafka
│
├── Pod: kafka-0
│   ├── PVC: data-kafka-0
│   └── Hostname: kafka-0.kafka.default.svc
│
├── Pod: kafka-1
│   ├── PVC: data-kafka-1
│   └── Hostname: kafka-1.kafka.default.svc
│
└── Pod: kafka-2
    ├── PVC: data-kafka-2
    └── Hostname: kafka-2.kafka.default.svc