必须用StatefulSet+volumeClaimTemplates动态绑定PVC,因MySQL要求每个Pod独占ReadWriteOnce存储;Deployment挂静态PV会导致多Pod争用、调度失败或InnoDB崩溃,手动维护编号PVC难扩缩且易出错。

MySQL 在 Kubernetes 中必须用 StatefulSet + volumeClaimTemplates 绑定动态 PVC,不能用 Deployment 挂静态 PV 或手动创建一堆编号 PVC——否则轻则数据错乱,重则 InnoDB 崩溃。
为什么不能直接给 MySQL Pod 挂静态 PV
静态 PV 是“先有卷、后找人”,而 MySQL 要求每个实例独占一份存储、且不能被多个 Pod 同时挂载(accessModes: ReadWriteOnce)。如果用 Deployment 部署,Pod 重启或漂移到其他节点时,可能:
- 多个 Pod 尝试挂同一个 PV → 调度失败或文件系统损坏
- PV 所在节点不可用 → Pod 卡在 Pending 状态,无法启动
- 手动维护一堆 mysql-pv-0、mysql-pv-1 等 PV → 扩容/缩容时必须同步增删 PV 和 PVC,极易出错
StatefulSet 的 volumeClaimTemplates 怎么写才有效
这是唯一推荐的 MySQL 存储绑定方式。模板会为每个 Pod(如 mysql-0)自动生成专属 PVC(如 data-volume-mysql-0),并确保与 PV 动态绑定。关键点:
- volumeClaimTemplates 下的 name 必须和容器内 volumeMounts.name 完全一致
- storageClassName 必须存在且可用(kubectl get sc 可查),否则 PVC 卡在 Pending
- accessModes 只能设为 ["ReadWriteOnce"];MySQL 不支持 ReadWriteMany
- 不要写 volumeName 或 selector 字段——它们在模板里会被忽略,甚至触发校验失败
- resources.requests.storage 是唯一必须指定的容量字段,例如 10Gi
StorageClass 配置中容易被忽略的 volumebindingmode
尤其在云环境(阿里云、AWS、Azure)部署时,StorageClass 的 volumebindingmode 必须设为 WaitForFirstConsumer:
- 如果设成 Immediate,系统会提前创建 PV,但云盘只能挂载到特定可用区的节点
- 结果:PV 创建在杭州 A 区,而 Pod 被调度到杭州 B 区 → PVC 一直 Pending,MySQL 启不来
- Ceph 或 NFS 类 StorageClass 通常可设 Immediate,但务必确认后端存储是否支持跨节点并发挂载
- 查看当前配置:kubectl get sc -o yaml;修改命令:kubectl patch sc <code>your-sc-name -p '{"volumeBindingMode":"WaitForFirstConsumer"}'
NFS 或 Ceph 等外部存储的实际落地要点
用 NFS 或 Ceph 并不意味着“随便配好就能用”,仍有硬性约束:
- 所有 Kubernetes 节点(含 master)必须安装对应客户端:ceph-common 或 nfs-utils
- Ceph 场景下,/etc/ceph/ceph.conf 和 keyring 文件(如 /etc/ceph/ceph.client.admin.keyring)必须存在且权限正确(600)
- NFS 场景下,NFS 服务端的 /etc/exports 必须包含 no_root_squash,否则 MySQL 容器以 root 写入时会被降权,导致初始化失败
- 若用 NFS 动态供给器(如 nfs-client-provisioner),其 ServiceAccount 必须有 cluster-admin 权限,否则无法自动创建 PV
最常被跳过的一步:没验证 StorageClass 是否真能供给 PV。上线前务必跑一次 kubectl apply -f test-pvc.yaml(只含一个最小 PVC),等它变成 Bound 状态再部署 MySQL —— 否则所有后续操作都是空中楼阁。


















