一、StatefulSet 扩缩容为什么要比 Deployment 更谨慎

StatefulSet 同样支持改 replicas,也支持 kubectl editkubectl scalekubectl patch,但它的扩缩容过程带有明确顺序。

kubectl edit sts web
kubectl scale sts web --replicas=5
kubectl patch sts web -p '{"spec":{"replicas":3}}'

扩容时,Pod 会按照序号逐个补齐;缩容时,则会从最大序号开始逐个回收。对于带状态业务来说,这种串行行为恰恰是价值所在。

二、OnDelete 和 RollingUpdate 有什么区别

1.1 OnDelete:你不删,我不更

OnDelete 是很保守的更新模式。即使你修改了 StatefulSet 的 Pod 模板,控制器也不会主动替换 Pod,只有你手动删除某个 Pod,它才会按新模板重建。

spec:
  updateStrategy:
    type: OnDelete

实操流程通常像这样:

kubectl replace -f stateful-ondelete.yaml
kubectl get pods -l app=nginx -oyaml | grep image
kubectl delete pod web-1
kubectl get pods -l app=nginx -oyaml | grep image

这类策略适合特别谨慎的状态服务,便于你“一台一台、一个序号一个序号”地验证。

1.2 RollingUpdate:默认的自动滚动

如果采用 RollingUpdate,StatefulSet 会按序号逆序进行更新,高序号 Pod 会先替换。

kubectl replace -f stateful.yaml
kubectl get pods -l app=nginx -oyaml | grep image

这意味着你要提前确认:

  • readiness 是否足够准确
  • 新版本是否兼容旧数据
  • 高序号实例先更新是否符合业务预期

三、如何用 partition 做 StatefulSet 灰度发布

StatefulSet 也可以做分段更新,关键配置是:

spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 3
  replicas: 5

partition: 3 时,只有序号大于等于 3 的 Pod 会更新,也就是 web-3web-4。低于这个分区号的 Pod 即使被删除,也会按照旧版本模板重建。

这类配置非常适合:

  • 先更新少量高序号实例做验证
  • 按阶段逐步推进版本
  • 做最小范围金丝雀发布

四、回滚能不能用,怎么用

StatefulSet 同样支持 rollout historyrollout undo

kubectl rollout history sts web
kubectl rollout undo sts web
kubectl rollout undo sts web --to-revision=2

原文也特别提醒了一点:真实生产里,StatefulSet 一般不会像 Deployment 那样频繁回滚。原因很简单,镜像可以回去,数据状态未必能一起回去。所以回滚命令能用,不代表业务上一定安全。

五、删除 StatefulSet 时,级联和非级联差别很大

删除 StatefulSet 主要有两种方式。

非级联删除:

kubectl delete statefulset web --cascade=false

这种方式会删除 StatefulSet 对象,但保留现有 Pod。保留下来的 Pod 会变成“孤儿 Pod”,后续再删掉它们时,不会自动重建。

级联删除:

kubectl delete sts web

这种方式会把 StatefulSet 和它管理的 Pod 一并删除。

最后还要额外记住一条:无论是删除还是缩容,StatefulSet 关联的存储通常不会自动清掉。对数据服务来说,这是一种保护;对运维来说,也意味着你必须对卷和数据生命周期单独负责。