必须用statefulset+volumeclaimtemplates,因innodb禁止多实例共享存储;volumeclaimtemplates自动为每个pod创建独立pvc(如data-volume-mysql-0),确保数据隔离;需配合headless service、name严格匹配、waitforfirstconsumer等三要素缺一不可。

不能用 Deployment,必须用 StatefulSet + volumeClaimTemplates,否则 MySQL 启动就崩溃。
为什么 volumeClaimTemplates 是硬性要求
MySQL 的 InnoDB 引擎不允许多个实例并发写同一份数据文件。如果用 Deployment 挂一个静态 PVC,扩到 2 个副本时,mysql-0 和 mysql-1 会争抢同一个 PV,几秒内就触发文件系统损坏。
-
volumeClaimTemplates让 StatefulSet 控制器自动为每个 Pod 创建专属 PVC,命名规则固定为[template-name]-[pod-name](如data-volume-mysql-0) - 模板里的
name字段(如data-volume)必须和容器内volumeMounts.name完全一致,否则挂载静默失败,kubectl describe pod不报存储错误 - 填
selector或volumeName到模板里会被忽略,还可能触发校验失败
StorageClass 的 volumeBindingMode 必须是 WaitForFirstConsumer
云环境(阿里云 ESSD、AWS gp3、GCP pd-balanced)下,若 StorageClass 是默认的 Immediate 模式,PVC 会卡在 Pending 状态,kubectl describe pvc 只显示 “no persistent volumes available for this claim”,实际是可用区不匹配。
- 执行
kubectl describe sc <your-sc-name></your-sc-name>,确认VolumeBindingMode是WaitForFirstConsumer - 如果不是,不要改默认 SC,而是新建一个 SC,并在
volumeClaimTemplates中显式指定storageClassName - 本地 NFS 或 Longhorn 可用
Immediate,但 NFS 要求所有 Node 都能 mount 同一路径,且/etc/exports必须含no_root_squash,否则 MySQL 启动时chown /var/lib/mysql失败
Headless Service 缺失会导致 PVC 绑定静默失败
StatefulSet 依赖 Headless Service(clusterIP: None)生成稳定 DNS 名,而 volumeClaimTemplates 的 PVC 命名逻辑也隐式依赖该 Service 存在。缺了它,Pod 卡在 Pending 或 ContainerCreating,kubectl logs 和 describe pod 都看不到存储相关错误,只能查 kubectl get pvc 发现 PVC 一直 Pending。
- Headless Service 的
metadata.name必须和 StatefulSet 的serviceName字段**完全一致** - StatefulSet 的
spec.selector.matchLabels和template.metadata.labels必须完全一致,否则控制器不认 Pod -
volumeMounts.mountPath必须是 MySQL 镜像实际写数据的路径(通常是/var/lib/mysql),否则数据落在容器临时层,重启即丢
最容易被忽略的是三处硬性依赖同时满足:Headless Service 存在且 name 匹配、volumeClaimTemplates.name 与 volumeMounts.name 严格一致、StorageClass 的 volumeBindingMode 正确。漏掉任意一项,问题都藏得深,排查耗时远超部署本身。











