← 返回首页
🔧

Kubernetes StatefulSet 有状态应用

📂 devops ⏱ 2 min 365 words

Kubernetes StatefulSet 有状态应用

什么是 StatefulSet

StatefulSet 是 Kubernetes 中用于管理有状态应用的控制器。与 Deployment 不同,StatefulSet 为每个 Pod 提供稳定的网络标识和持久存储,适用于数据库、消息队列等需要持久状态的应用。

StatefulSet 的特点

创建 StatefulSet

YAML 文件

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: root-password
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mysql-data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: standard
        resources:
          requests:
            storage: 10Gi

Headless Service

StatefulSet 需要配套的 Headless Service:

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
    - port: 3306

创建 Secret

kubectl create secret generic mysql-secret \
  --from-literal=root-password=S3cr3tP@ss

部署

kubectl apply -f headless-service.yaml
kubectl apply -f statefulset.yaml

# 查看状态
kubectl get pods -l app=mysql
kubectl get statefulset mysql

访问 Pod

# 访问特定 Pod
mysql-0.mysql.default.svc.cluster.local
mysql-1.mysql.default.svc.cluster.local
mysql-2.mysql.default.svc.cluster.local

# 测试 DNS 解析
kubectl run test --image=busybox --rm -it -- nslookup mysql

扩展和收缩

# 扩展到 5 个副本
kubectl scale statefulset mysql --replicas=5

# 收缩到 2 个副本
kubectl scale statefulset mysql --replicas=2

# 查看 PVC
kubectl get pvc

更新策略

Rolling Update(默认)

spec:
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0

OnDelete

spec:
  updateStrategy:
    type: OnDelete

更新镜像

# 更新 StatefulSet
kubectl set image statefulset mysql mysql=mysql:8.0.28

# 分区更新(只更新 ordinal >= partition 的 Pod)
kubectl patch statefulset mysql -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":1}}}}'

常用操作

# 查看 StatefulSet 状态
kubectl describe statefulset mysql

# 暂停和恢复
kubectl rollout pause statefulset mysql
kubectl rollout resume statefulset mysql

# 回滚
kubectl rollout undo statefulset mysql
kubectl rollout history statefulset mysql

# 删除 StatefulSet(保留 PVC)
kubectl delete statefulset mysql --cascade=orphan

实践案例:部署 MySQL 集群

部署主从架构

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-replica
spec:
  serviceName: mysql-replica
  replicas: 3
  selector:
    matchLabels:
      app: mysql-replica
  template:
    metadata:
      labels:
        app: mysql-replica
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mysql-data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 20Gi

常见问题

Pod 无法启动

# 检查 PVC 状态
kubectl get pvc

# 检查 Pod 事件
kubectl describe pod mysql-0

Headless Service 配置

确保 StatefulSet 的 serviceName 与 Headless Service 的 name 匹配。

最佳实践

总结

StatefulSet 是部署有状态应用的核心组件,提供稳定的网络标识和持久存储。掌握 StatefulSet 的使用可以更好地管理数据库、消息队列等有状态应用。