对于数据库、消息队列等有状态应用,StatefulSet 可通过 volumeClaimTemplates
为每个 Pod 动态创建并绑定独立的云盘持久卷。Pod 被重建或重新调度时,能够自动挂载回原有的存储卷,从而实现数据持久化,保障业务连续性。
配置示例如下:
apiVersion: apps/v1
kind: StatefulSet
# ...
spec:
# ...
volumeClaimTemplates:
- metadata:
name: data-volume # PVC 模板名称
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "alicloud-disk-essd" # 指定存储类型
resources:
requests:
storage: 20Gi # 申请的存储空间大小
工作原理
创建与扩容
初始创建或扩容时,StatefulSet控制器会通过
volumeClaimTemplates
模板,为每个Pod副本(如web-0
、web-1
)创建并绑定一个名称唯一的PVC(如disk-essd-web-0
、disk-essd-web-1
,名称格式遵循[模板名]-[Pod名]
)。这一机制确保了Pod与其存储之间稳定的映射关系。CSI 会根据模板中的参数配置 (
storageClassName
、storage
、accessModes
),自动创建类型、大小和访问模式匹配的PV,完成绑定与挂载。缩容
缩容时,控制器仅删除 Pod 本身,其关联的 PVC 及后端 PV 仍会保留,以确保数据安全。
再次扩容与故障恢复
基于缩容时的留存数据,再次扩容(调高副本数)或故障恢复(Pod删除后重建)时,控制器会自动查找并复用此前保留的同名 PVC。
若存在,新的同名 Pod 会自动挂载此前的 PV,实现数据和状态的快速恢复。
若不存在(如扩容操作超过了历史副本数峰值),则会新建 PVC和对应的PV。
准备StatefulSet
创建
statefulset.yaml
。该示例将创建一个Service 和一个包含2个副本的 StatefulSet,StatefulSet通过
volumeClaimTemplates
为每个副本自动创建一个 20 GiB 的云盘。volumeClaimTemplates
中的参数说明如下。参数
说明
accessModes
存储卷的访问模式。
ReadWriteOnce
表示该卷一次只能被一个节点以读写方式挂载。storageClassName
待使用的StorageClass名称。
alicloud-disk-essd
是ACK默认提供的StorageClass,用于创建ESSD云盘,默认PL等级为PL1。云盘采用按量付费,请参见块存储计费、块存储价格。
storage
云盘存储卷的容量大小。
部署StatefulSet。
kubectl create -f statefulset.yaml
确认 Pod 处于 Running 状态。
kubectl get pod -l app=nginx
查看PVC,确认系统已经为每个 Pod 自动创建并绑定(Bound)了对应的 PVC。
kubectl get pvc
预期输出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE disk-essd-web-0 Bound d-m5eb5ozeseslnz7zq54b 20Gi RWO alicloud-disk-essd <unset> 3m31s disk-essd-web-1 Bound d-m5ecrvjrhqwehgzqpk5i 20Gi RWO alicloud-disk-essd <unset> 48s
通过扩缩容验证存储生命周期管理
通过扩容、缩容、再到扩容的流程,观察关联 PVC 的创建、保留和复用情况。
应用扩容
增加StatefulSet副本数至3个。
kubectl scale sts web --replicas=3
确认 Pod 处于 Running 状态。
kubectl get pod -l app=nginx
查看PVC,确认系统已自动创建了Pod
web-2
以及对应的PVCdisk-essd-web-2
。kubectl get pvc
预期输出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE disk-essd-web-0 Bound d-m5eb5ozeseslnz7zq54b 20Gi RWO alicloud-disk-essd <unset> 4m1s disk-essd-web-1 Bound d-m5ecrvjrhqwehgzqpk5i 20Gi RWO alicloud-disk-essd <unset> 78s disk-essd-web-2 Bound d-m5ee2cvzx4dog1lounjn 20Gi RWO alicloud-disk-essd <unset> 16s
应用缩容
减少StatefulSet副本数至2个。
kubectl scale sts web --replicas=2
确认 Pod 处于 Running 状态。
kubectl get pod -l app=nginx
查看PVC。
kubectl get pvc
预期输出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE disk-essd-web-0 Bound d-m5eb5ozeseslnz7zq54b 20Gi RWO alicloud-disk-essd <unset> 4m21s disk-essd-web-1 Bound d-m5ecrvjrhqwehgzqpk5i 20Gi RWO alicloud-disk-essd <unset> 98s disk-essd-web-2 Bound d-m5ee2cvzx4dog1lounjn 20Gi RWO alicloud-disk-essd <unset> 36s
此时,Pod
web-2
已被删除,但 PVCdisk-essd-web-2
仍然存在,以确保数据持久性。
应用再次扩容
再次增加StatefulSet副本数至3个。
kubectl scale sts web --replicas=3
确认 Pod 处于 Running 状态。
kubectl get pod -l app=nginx
查看PVC。
kubectl get pvc
预期输出:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE disk-essd-web-0 Bound d-m5eb5ozeseslnz7zq54b 20Gi RWO alicloud-disk-essd <unset> 4m50s disk-essd-web-1 Bound d-m5ecrvjrhqwehgzqpk5i 20Gi RWO alicloud-disk-essd <unset> 2m7s disk-essd-web-2 Bound d-m5ee2cvzx4dog1lounjn 20Gi RWO alicloud-disk-essd <unset> 65s
此时,新建的Pod
web-2
已自动绑定并使用此前遗留的PVCdisk-essd-web-2
。
通过模拟Pod故障验证持久化存储
通过“写入数据 -> 删除 Pod -> 检查数据”的流程,来验证存储在云盘上的数据在 Pod 重建后是否仍然存在。
在 Pod 中写入测试数据。
以Pod
web-1
为例,在其挂载的云盘路径/data
下创建一个test文件。kubectl exec web-1 -- touch /data/test kubectl exec web-1 -- ls /data
预期输出:
lost+found test
模拟 Pod 故障,删除 Pod。
kubectl delete pod web-1
再次执行
kubectl get pod -l app=nginx
,可以发现已自动创建一个同名的Podweb-1
。验证新 Pod 中的数据。
在新Pod
web-1
中再次检查/data
目录。kubectl exec web-1 -- ls /data
预期输出中,此前创建的 test 文件依然存在,表明即使 Pod 被删除重建,数据也实现了持久化存储。
lost+found test
应用于生产环境
成本与资源管理:StatefulSet 缩容或删除后,其关联的 PVC 和云盘默认会被保留,存留资源会持续产生费用。请及时清理无需使用的 PVC和PV,并释放云盘。
数据安全与备份:持久化存储仅解决 Pod 重建后的高可用问题,但不提供数据备份能力。对于核心业务,建议使用备份中心进行数据的备份和恢复。
高可用与容灾:云盘是可用区级别资源,不支持跨可用区挂载。建议选用支持多可用区容灾的云盘类型,将数据实时同步写入同一地域的不同可用区,实现跨可用区的故障恢复,请参见使用ESSD同城冗余云盘。
相关文档
使用云盘存储卷如遇问题,可参见云盘存储卷FAQ排查。