必须用statefulset配合volumeclaimtemplates,因deployment+静态pvc会导致多pod共享同一pvc,引发innodb崩溃;volumeclaimtemplates可自动为每个pod生成独立命名(如data-volume-mysql-0)且专属绑定的pvc,确保数据隔离与持久化。

不能用 Deployment + 静态 PVC 给 MySQL 做持久化——它会导致多个 Pod 挂同一个 PVC,InnoDB 直接崩溃。必须用 StatefulSet 配合 volumeClaimTemplates,这是唯一安全可行的路径。
为什么 volumeClaimTemplates 是硬性要求
MySQL 实例之间绝不能共享存储卷。静态 PVC(比如手动写死 mysql-pvc-0、mysql-pvc-1)看似能分配独立存储,但扩缩容时完全无法自动管理:加一个副本得手写新 PVC、删一个还得手动清理,极易遗漏或命名错位。
-
volumeClaimTemplates由 StatefulSet 控制器原生驱动,Podmysql-0启动时自动创建并绑定data-volume-mysql-0,名字和生命周期严格一一对应 - 模板中
name字段(如data-volume)必须与容器内volumeMounts.name完全一致,否则挂载失败且无明确报错 - 模板里只允许写
accessModes、resources.requests.storage、storageClassName;填selector或volumeName会被忽略,还可能触发校验失败
StorageClass 的 volumebindingmode 必须设为 WaitForFirstConsumer
云环境(阿里云 ESSD、AWS gp3、GCP pd-balanced)下,若 StorageClass 的 volumeBindingMode 是默认的 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 并在 StatefulSet 的
volumeClaimTemplates中显式指定storageClassName - 本地 NFS 或 Longhorn 可用
Immediate,但 NFS 要求所有 Node 都能mount同一路径,且/etc/exports必须含no_root_squash,否则 MySQL 启动时chown数据目录失败
Headless Service 缺失会导致 PVC 绑定静默失败
StatefulSet 依赖 Headless Service(clusterIP: None)生成稳定 DNS 名,而 volumeClaimTemplates 的 PVC 命名逻辑([template-name]-[pod-name])也隐式依赖该 Service 存在。缺了它,Pod 卡在 Pending 或 ContainerCreating,kubectl logs 和 describe pod 都看不到存储相关错误,只能查 kubectl get pvc 发现 PVC 一直 Pending。
- Headless Service 的
metadata.name必须和 StatefulSet 的serviceName字段**完全一致** - Service 的
selector必须精确匹配 StatefulSet Pod 的标签(如app: mysql),漏一个 label 就不会关联上 - 不要复用已有 Service 名——哪怕它也是 headless,StatefulSet 会拒绝绑定,报错类似 “service xxx not found”
最常被跳过的其实是三者联动:Headless Service 名称对不上、volumeClaimTemplates.name 和 volumeMounts.name 不一致、storageClassName 在集群中不存在或 WaitForFirstConsumer 配置错误。这三个点任意一个出问题,PVC 就不会绑定,MySQL Pod 就起不来,而且日志里几乎不报存储层错误——得一层层核对对象状态,不是看 Events 就能发现的。











