必须用statefulset部署mysql,因其提供稳定网络标识(如mysql-0)、有序启停(先主后从)和独占pvc绑定,避免数据丢失或写冲突;需搭配headless service、secret和configmap,禁用deployment。

mysql 在 Kubernetes 上不是“装个镜像就能跑”的无状态服务,它必须绑定持久化存储、控制启动顺序、隔离网络标识——否则 Pod 重启后数据就丢了,或者两个实例抢着写同一份磁盘。
用 StatefulSet 而不是 Deployment 部署 mysql
Deployment 适合无状态服务,但 mysql 是有状态的:每个实例需要固定名称(如 mysql-0)、固定存储卷、固定 DNS 名(mysql-0.mysql-headless.default.svc.cluster.local),这些只有 StatefulSet 能保证。
常见错误是直接套用 Deployment YAML,结果 Pod 重建后挂载了空 PVC,或多个副本同时往同一 PV 写数据导致崩溃。
必须搭配 Headless Service(clusterIP: None)才能让每个 Pod 拥有独立可解析的 DNS 记录。
PersistentVolume 和 PersistentVolumeClaim 必须配对且不可跨节点复用
MySQL 数据目录(/var/lib/mysql)必须挂载到独占的 PV,不能用 hostPath 或 emptyDir——它们随 Pod 消失而清空,也不支持多节点调度。
生产环境别用 Local PV,它绑死节点,一旦节点宕机,Pod 就无法在别处重建;优先选支持动态供给的存储类(如 AWS EBS、GCP PD、Ceph RBD)。
检查 PVC 是否 Bound:kubectl get pvc -n your-namespace,状态不是 Bound 就说明 PV 没配好或 StorageClass 不匹配。
初始化密码和配置必须通过 Secret + ConfigMap 注入
MYSQL_ROOT_PASSWORD 这类敏感信息绝不能硬编码在 Deployment 或 StatefulSet 的 env 字段里——它会出现在 kubectl get deploy -o yaml 输出中。
正确做法是创建 Secret:kubectl create secret generic mysql-secret --from-literal=MYSQL_ROOT_PASSWORD=your_strong_password -n your-namespace,再在容器 env 中引用:valueFrom: {secretKeyRef: {name: mysql-secret, key: MYSQL_ROOT_PASSWORD}}。
MySQL 配置(如 my.cnf)用 ConfigMap 挂载到 /etc/mysql/conf.d/,避免镜像内配置被覆盖;特别注意 innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 这类影响数据安全的参数,不要依赖默认值。
连接地址别写 Pod IP,要用 Service DNS 名
Pod IP 是临时的,每次重启都变;mysql 的客户端(比如 Spring Boot 应用)必须连 Service 的 ClusterIP 或 Headless Service 的 DNS 名。
如果只部署单实例,用普通 ClusterIP Service:mysql.default.svc.cluster.local:3306;
如果是主从架构,读写分离需额外建两个 Service:一个指向主节点(带 selector: role=master),一个指向所有从节点(role=slave);
千万别在应用里写死 10.244.x.x 这种 Pod IP,Kubernetes 网络模型不保证它稳定。
mysql 就起不来——不是 CrashLoopBackOff 就是日志里报 Can't start server : Bind on unix socket: Permission denied 或 Table 'mysql.plugin' doesn't exist。调试时先 kubectl logs mysql-0 -n your-namespace,再 kubectl describe pod mysql-0 看 Events,最后确认 PVC 是否真正 Bound 到 PV。











