StatefulSet是部署MySQL的唯一安全选择,因其通过volumeClaimTemplates为每个Pod自动创建独立PVC(如data-volume-mysql-0),确保数据隔离与持久化;手动创建编号PVC难维护且不支持自动扩缩,而Deployment挂PVC会导致多Pod写同一存储,损坏InnoDB。

StatefulSet 是唯一能安全持久化 MySQL 数据的控制器,用 Deployment 挂 PVC 会导致多个 Pod 写同一份数据,InnoDB 文件系统直接损坏。
为什么必须用 volumeClaimTemplates 而不是手动创建 PVC
StatefulSet 的每个 Pod 必须绑定独立、专属的存储卷,不能复用 PVC。
手动创建一堆带编号的 PVC(如 mysql-data-0、mysql-data-1)难维护,且扩缩容时无法自动增减。volumeClaimTemplates 是 StatefulSet 原生机制:Pod 名为 mysql-0 时,自动生成名为 data-volume-mysql-0 的 PVC,并严格绑定对应 PV。
- 模板中
name(如data)必须与volumeMounts.name完全一致 -
storageClassName必须存在且可用,否则 PVC 卡在Pending -
accessModes只能是["ReadWriteOnce"]—— MySQL 不支持多节点并发写 - 不要在模板里写
selector或volumeName,它们会被忽略或报错
StorageClass 的 volumebindingmode 必须设为 WaitForFirstConsumer
云环境(如阿里云 alicloud-disk-essd、AWS gp3)下,若 volumebindingmode 是 Immediate,PV 可能提前创建在错误可用区,导致 Pod 卡在 ContainerCreating。
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
- 检查命令:
kubectl describe sc alicloud-disk-essd,确认VolumeBindingMode是WaitForFirstConsumer - 如果不是,必须新建 SC 并在 StatefulSet 中显式引用新名称 —— 不能修改默认 SC
- 本地 NFS 或 Longhorn 可设为
Immediate,但需确保所有 Node 都能挂载同一路径
StatefulSet YAML 中三处硬性依赖缺一不可
漏掉任意一项,Pod 会卡在 Pending 或 ContainerCreating,kubectl logs 看不到明显错误,排查极其耗时。
- 必须定义一个 headless Service(
clusterIP: None),且serviceName字段要和 StatefulSet 的serviceName完全一致 —— 这是生成稳定 DNS 名(如mysql-0.mysql-headless.default.svc.cluster.local)的前提 -
volumeClaimTemplates.metadata.name(如data)必须与容器内volumeMounts.name严格匹配 -
spec.selector.matchLabels和template.metadata.labels必须完全一致,否则 StatefulSet 不认 Pod
MySQL 数据目录路径必须与 volumeMounts.mountPath 一致
镜像默认将数据写入 /var/lib/mysql,如果挂载路径不匹配,数据仍落在容器临时层,重启即丢。
- 确认 MySQL 镜像实际数据路径:
docker run --rm mysql:8.0 ls -ld /var/lib/mysql -
volumeMounts.mountPath必须精确等于该路径,不能是/var/lib/mysql/(尾部斜杠会导致挂载失败) - 若使用自定义 my.cnf,务必同步改
datadir,否则 MySQL 启动报错Can't open the mysql.plugin table
mysqld --initialize)必须发生在挂载完成后的容器内,且 /var/lib/mysql 目录初始为空 —— 如果宿主机目录已有残留文件,InnoDB 会拒绝启动或静默损坏。每次调试前,建议先 kubectl delete pvc data-volume-mysql-0 彻底清理。

















