必须用statefulset的volumeclaimtemplates而非deployment+静态pvc,因其为每个pod自动生成专属pvc(如mysql-data-mysql-0),确保readwriteonce模式下innodb数据隔离;静态pvc无法自动扩缩且易复用导致数据损坏。

PVC 必须绑定到 ReadWriteOnce 模式的存储卷,且不能复用——MySQL 5.7 的 InnoDB 数据目录不支持多 Pod 并发写入,否则直接损坏数据文件。
为什么不能用 Deployment + 静态 PVC
Deployment 创建的多个 Pod 会尝试挂载同一个 PVC,而 MySQL 进程启动时会校验 ibdata1 文件锁和 auto.cnf 的 server-uuid。一旦两个 Pod 同时读写同一份数据,InnoDB 崩溃是必然结果,日志里常见 InnoDB: Unable to lock ./ibdata1 error 或 mysqld: Can't start server: Bind on unix socket。
- 静态创建的
PVC(如mysql-pvc-0)无法随 Pod 数量自动扩缩,StatefulSet 扩容时不会生成新 PVC - 手动维护一堆编号 PVC(
mysql-data-0、mysql-data-1…)极易出错,命名/容量/StorageClass 不一致就会卡在Pending - Deployment 无序重启时,Pod 可能调度到不同节点,但本地 PV 的
nodeAffinity会强制绑定原节点,导致调度失败或挂载超时
必须用 StatefulSet 的 volumeClaimTemplates
volumeClaimTemplates 是唯一安全方式:它为每个 Pod 自动生成专属 PVC,名称格式固定为 [template-name]-[pod-name](如 mysql-data-mysql-0),并严格匹配 volumeMounts.name。
- 模板中只写
resources.requests.storage和accessModes,其他字段如selector、volumeName会被忽略或报错 -
storageClassName必须存在且可用;执行kubectl get sc确认,再用kubectl describe sc <name></name>检查VolumeBindingMode - 云环境(阿里云ESSD、AWS gp3)必须设为
WaitForFirstConsumer,否则 PV 提前创建在错误可用区,PVC 卡Pending - 本地 NFS 或 Longhorn 可设
Immediate,但 NFS 要求所有 Node 都能 mount 同一路径,且accessModes支持ReadWriteOnce(NFS 默认支持 RWO/RWX)
StorageClass 配置的关键陷阱
哪怕 volumeClaimTemplates 写对了,如果 StorageClass 配置错,PVC 依然无法 Bound。
- 云盘类 CSI 驱动(如
alicloud-disk-essd)若VolumeBindingMode是Immediate,PV 会在 PVC 创建时立即分配,但可能落在与 Pod 调度目标不一致的可用区 → 调度失败 - 本地盘
StorageClass必须带volumeBindingMode: WaitForFirstConsumer和provisioner: kubernetes.io/no-provisioner,否则无法延迟绑定 - 不要修改默认
StorageClass,而是新建一个(如mysql-sc),并在 StatefulSet 中显式引用:storageClassName: mysql-sc - 检查 PV 是否就绪:
kubectl get pv看状态是否为Available或Bound;若为Failed,常因路径不存在或权限不足(如/var/lib/mysql目录未 chown 1001:1001)
挂载路径和权限的实际约束
MySQL 容器以非 root 用户(通常是 mysql,uid 1001)运行,/var/lib/mysql 目录必须属主正确,否则启动失败报 Can't start server: bind on unix socket 或 Permission denied。
- 本地 PV 的
hostPath或local.path对应宿主机目录,需提前执行:chown -R 1001:1001 /path/to/mysql/data - NFS 共享目录需开启
no_root_squash,否则 root 用户映射为 nobody,MySQL 进程无法写入 - 务必在容器内验证挂载点权限:
kubectl exec -it mysql-0 -- ls -ld /var/lib/mysql,输出应含drwxr-xr-x 1 mysql mysql - ConfigMap 挂载的
my.cnf必须放在/etc/mysql/conf.d/或/etc/my.cnf,且不能覆盖 MySQL 启动必需的默认配置段
真正麻烦的不是写 YAML,而是 StorageClass 的 VolumeBindingMode 和宿主机目录权限这两处——前者决定 PVC 能否成功 Bound,后者决定 MySQL 进程能否真正写入数据。漏掉任一环节,Pod 就会卡在 Init:CrashLoopBackOff 或 Running 但无法提供服务。











