← 返回文章列表
Kubernetes StatefulSet 完全指南
深入理解 Kubernetes StatefulSet:与 Deployment 的区别、存储卷管理、有状态应用部署
6 分钟阅读
字号
Kubernetes StatefulSet 完全指南
本文基于 Kubernetes 1.28
概述
在 Kubernetes 中,Deployment 适合部署无状态应用,但对于数据库、消息队列等有状态应用,StatefulSet 是更好的选择。
StatefulSet 为 Pod 提供:
- 稳定的网络身份(固定的 Pod 名称和 DNS)
- 稳定的存储(每个 Pod 有专属的 PVC)
- 有序的部署和扩缩容
一、StatefulSet vs Deployment
对比表
| 特性 | Deployment | StatefulSet |
|---|---|---|
| Pod 名称 | 随机哈希 | 有序编号 |
| 存储 | 各 Pod 独立 | 每个 Pod 专属 PVC |
| 启动顺序 | 同时启动 | 按序号顺序 |
| 删除顺序 | 同时删除 | 逆序删除 |
| 网络身份 | 不稳定 | 稳定(DNS 固定) |
| 适用场景 | Web/API(无状态) | 数据库(有状态) |
示例对比
Deployment:
web-deployment-abcde123
web-deployment-defgh456
web-deployment-ijkl789
StatefulSet:
mysql-0 ← 固定名字
mysql-1 ← 固定名字
mysql-2 ← 固定名字二、核心概念
1. 稳定的网络身份
mysql-0.mysql-headless.default.svc.cluster.local → IP1
mysql-1.mysql-headless.default.svc.cluster.local → IP2
mysql-2.mysql-headless.default.svc.cluster.local → IP3
即使 Pod 重启:
- 名字不变(还是叫 mysql-0)
- DNS 会更新指向新 IP2. 稳定的存储
mysql-0 → 专属 PVC:mysql-data-mysql-0(20Gi)
mysql-1 → 专属 PVC:mysql-data-mysql-1(20Gi)
mysql-2 → 专属 PVC:mysql-data-mysql-2(20Gi)
即使 Pod 重启:
- 绑定的 PVC 不变
- 数据不会丢失3. 有序的部署和扩缩容
部署顺序:mysql-0 → mysql-1 → mysql-2
扩容顺序:先创建 mysql-3,再创建 mysql-4
缩容顺序:先删除 mysql-2,再删除 mysql-1...三、YAML 详解
StatefulSet 完整示例
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
# 1. 服务名(必须和无头 Service 对应)
serviceName: mysql-headless
# 2. 副本数
replicas: 3
# 3. 选择器
selector:
matchLabels:
app: mysql
# 4. Pod 模板
template:
metadata:
labels:
app: mysql
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "root123"
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
# 健康检查
readinessProbe:
exec:
command: ["mysqladmin", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
# 5. 卷声明模板(自动创建 PVC)
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 20Gi无头 Service
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None # 关键:设为 None
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306四、Volume Claim Templates
什么是 Volume Claim Templates
自动为每个 Pod 创建专属 PVC。
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 20Gi自动创建的 PVC 名称
格式:{metadata.name}-{StatefulSet名}-{Pod序号}
示例:
mysql-data-mysql-0 → mysql-0 用的 PVC
mysql-data-mysql-1 → mysql-1 用的 PVC
mysql-data-mysql-2 → mysql-2 用的 PVC五、创建过程
1. 创建 StatefulSet
kubectl apply -f mysql-statefulset.yaml2. 按顺序创建 Pod
mysql-0 创建中...
→ PVC: mysql-data-mysql-0 创建
→ PVC: Bound
→ Pod: mysql-0 创建
→ Pod: Running & Ready
mysql-1 创建中...
→ PVC: mysql-data-mysql-1 创建
→ ...
mysql-2 创建中...
→ ...3. 查看状态
kubectl get statefulset
# NAME READY AGE
# mysql 3/3 5m
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# mysql-0 1/1 Running 0 5m
# mysql-1 1/1 Running 0 3m
# mysql-2 1/1 Running 0 1m
kubectl get pvc
# NAME STATUS VOLUME CAPACITY
# mysql-data-mysql-0 Bound pvc-xxx 20Gi
# mysql-data-mysql-1 Bound pvc-yyy 20Gi
# mysql-data-mysql-2 Bound pvc-zzz 20Gi六、扩缩容
扩容
kubectl scale statefulset mysql --replicas=5过程(从后往前创建):
mysql-3 创建 → PVC mysql-data-mysql-3 创建 → Bound → Pod Ready
mysql-4 创建 → PVC mysql-data-mysql-4 创建 → Bound → Pod Ready缩容
kubectl scale statefulset mysql --replicas=2过程(逆序删除):
mysql-4 终止(等待优雅终止完成)
mysql-4 删除
mysql-3 终止...
注意:缩容不会删除 PVC!数据保留。七、删除
删除 StatefulSet
kubectl delete statefulset mysql
# PVC 保留!数据不会丢失删除 PVC
# 手动删除才会丢失数据
kubectl delete pvc mysql-data-mysql-0
kubectl delete pvc mysql-data-mysql-1
kubectl delete pvc mysql-data-mysql-2八、适用场景
| 应用 | 为什么用 StatefulSet |
|---|---|
| MySQL/MariaDB | 每个实例有独立数据 |
| PostgreSQL | 副本集成员数据独立 |
| Redis | 主从数据独立 |
| MongoDB | 副本集成员数据独立 |
| Kafka | 每个 Broker 有独立数据 |
| Elasticsearch | 每个节点有独立数据 |
九、注意事项
- 存储选择:使用支持 ReadWriteOnce 的存储(云盘)
- 数据备份:缩容/删除前确保数据已备份
- 节点亲和性:避免所有 Pod 调度到同一节点
- 健康检查:配置 livenessProbe 和 readinessProbe
- 优雅终止:设置 terminationGracePeriodSeconds
十、总结
Deployment → 无状态应用(Web/API)
StatefulSet → 有状态应用(数据库)
StatefulSet 核心特点:
- 稳定的网络身份(Pod 名称固定)
- 稳定的存储(每个 Pod 专属 PVC)
- 有序的部署和扩缩容相关文档
分享