Skip to content

02 - StatefulSet:有状态应用管理

Deployment vs StatefulSet

特性DeploymentStatefulSet
Pod 名称随机后缀 (web-abc123)有序编号 (web-0, web-1, web-2)
存储共享 / 无状态每个 Pod 独立 PVC
启动顺序并行有序(0→1→2)
删除顺序并行逆序(2→1→0)
网络标识不固定固定 DNS(通过 Headless Service)
适用场景Web 应用、API数据库、消息队列、分布式存储

何时使用 StatefulSet?

当你的应用需要以下特性时:

  • 稳定的网络标识:Pod 重建后 DNS 名不变
  • 稳定的持久存储:每个 Pod 有自己的 PVC
  • 有序部署和扩缩容:按顺序启停

典型场景:MySQL 主从、Redis Cluster、Kafka、ZooKeeper、Elasticsearch


Headless Service

StatefulSet 需要配合 Headless Service 使用(clusterIP: None),为每个 Pod 提供固定 DNS:

<pod-name>.<service-name>.<namespace>.svc.cluster.local

例如:

mysql-0.mysql-headless.default.svc.cluster.local
mysql-1.mysql-headless.default.svc.cluster.local
mysql-2.mysql-headless.default.svc.cluster.local

StatefulSet 示例:MySQL

yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None            # Headless Service
  selector:
    app: mysql
  ports:
  - port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless  # 关联 Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: secret
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:        # 每个 Pod 自动创建独立 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi

volumeClaimTemplates

这是 StatefulSet 特有的字段。对于每个 Pod 副本,K8s 会自动创建一个 PVC:

  • mysql-0 → PVC data-mysql-0
  • mysql-1 → PVC data-mysql-1
  • mysql-2 → PVC data-mysql-2

Pod 被删除重建后,仍然会绑定到原来的 PVC,数据不丢失。


操作命令

bash
# 查看 StatefulSet
kubectl get statefulset
kubectl describe statefulset mysql

# 查看 Pod(注意有序命名)
kubectl get pods -l app=mysql

# 查看 PVC(每个 Pod 一个)
kubectl get pvc

# 扩容(会按顺序创建 mysql-3)
kubectl scale statefulset mysql --replicas=4

# 缩容(会先删除 mysql-3,但 PVC 保留!)
kubectl scale statefulset mysql --replicas=3

# 删除 StatefulSet 不会删除 PVC,需要手动清理
kubectl delete statefulset mysql
kubectl delete pvc -l app=mysql

下一步

Phase 7 - K8s 调度与扩缩容