StatefulSet 有状态应用

StatefulSet 用于管理有状态应用——每个副本都"有身份、有名字、有独立存储",重启后仍然认得自己是谁。数据库、消息队列、注册中心这类需要稳定标识的中间件,通常用它来部署。

与 Deployment 的差异

对比点DeploymentStatefulSet
Pod 名称随机后缀,如 app-7d9c5d有序编号,如 web-0、web-1
网络标识无固定 DNS 名有稳定 DNS 名(配合 headless Service)
存储副本共享同一份模板每个副本有独立 PVC
启停顺序无顺序要求按编号顺序启动、逆序优雅删除
适用无状态应用有状态应用(数据库、注册中心)

稳定网络标识:序号与 headless Service

StatefulSet 的每个 Pod 名字固定为"控制器名-序号"(从 0 递增),Pod 重建后名字不变,IP 却可能变化,所以再配一个 clusterIP 为 None 的 headless Service,为每个 Pod 提供稳定的 DNS 名:

kubectl get pods -l app=web
# NAME    READY   STATUS    RESTARTS   AGE
# web-0   1/1     Running   0          5m
# web-1   1/1     Running   0          4m
kubectl exec web-0 -- hostname
# web-0
# 集群内可用 web-0.web-svc.default.svc 之类域名直连某个实例

YAML 示例:headless Service + StatefulSet

apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  clusterIP: None            # headless:不分配虚拟 IP
  selector:
    app: web
  ports:
    - port: 80
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: web-svc       # 必须绑定 headless Service
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:      # 为每个副本生成独立 PVC
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 1Gi

serviceName 把 StatefulSet 与 headless Service 绑定;volumeClaimTemplates 按模板为每个副本自动创建 PVC(本例生成 data-web-0、data-web-1、data-web-2),写坏的数据不会因为 Pod 重建而丢失。

启动与下线顺序

默认 OrderedReady 策略下,Pod 严格按 0、1、2……顺序启动,前一个 Ready 才启动下一个;缩容或删除时则逆序进行,保证同一时刻只有少数副本在变化:

kubectl scale statefulset web --replicas=5    # 扩容:web-3、web-4 依次就绪
kubectl delete pod web-1                      # 重建后名字仍是 web-1,PVC 仍挂回原数据

适用场景

  • 需要稳定成员名单与编号的:MySQL 主从、Redis、MongoDB 等数据库集群。
  • 需要选举与有序加入的:ZooKeeper、etcd、Consul 等注册与协调服务。
  • 每个实例必须有独享存储的应用。

如果应用完全无状态(任何副本可互换、数据放外部存储),Deployment 更简单;只有"实例必须认识自己、数据不能混用"时才上 StatefulSet。

小结:StatefulSet 用"固定序号名字 + headless Service + volumeClaimTemplates"换来三个稳定:稳定标识、稳定 DNS、稳定存储。代价是没有 Deployment 那么随意——启停有序、缩容逆序,适合把数据库这类敏感应用搬上集群的场景。

笔记加载中…