statefulset是唯一能可靠支撑mysql主从集群的控制器,因其提供稳定网络标识、有序启停和pv自动绑定;必须配合headless service(clusterip: none)实现pod独立寻址,否则从库将因负载均衡连错实例或解析失败。

StatefulSet 是唯一能可靠支撑 MySQL 主从集群的控制器,用 Deployment 或 ReplicaSet 部署 MySQL 一定会在 Pod 重建后丢数据、断复制、连错实例——这不是配置问题,是模型不匹配。
为什么必须用 Headless Service 配合 StatefulSet
StatefulSet 的每个 Pod(如 mysql-0)需要被独立寻址,而普通 ClusterIP Service 会做负载均衡,把所有请求随机转发到任意后端 Pod,导致从库无法稳定连接主库。
-
Headless Service必须设置clusterIP: None,这样 CoreDNS 才会为每个 Pod 解析出独立的 A 记录,比如mysql-0.mysql.default.svc.cluster.local - Service 的
metadata.name必须和 StatefulSet 的serviceName字段完全一致(大小写、连字符都不能错) - 常见错误现象:
mysql-0启动后反复CrashLoopBackOff,日志里出现Can't find hostname mysql-0或getaddrinfo failed,90% 是因为 Service 没设成 headless,或 DNS 域名拼错 - 验证方法:
kubectl exec -it mysql-0 -- nslookup mysql-0.mysql.default.svc.cluster.local,应返回唯一 IP;若返回多个 IP 或报NXDOMAIN,说明 DNS 未生效
InitContainer 如何初始化主从拓扑
StatefulSet 自身不处理 MySQL 实例间的角色协调。你需要靠 InitContainer 在容器启动前完成身份识别、配置生成和主节点就绪等待——否则多个 Pod 同时尝试写入同一数据目录,或从节点在主节点未启动时就开始连接,都会导致崩溃。
- InitContainer 运行脚本,检查当前 Pod 序号:
hostname为mysql-0则设为 master,其余为 slave - 向 ConfigMap 挂载的模板生成
/etc/mysql/conf.d/replication.cnf,包含server-id、read_only=1等差异化配置 - 用
nc -z mysql-0.mysql-headless 3306轮询等待主节点mysqld就绪(注意加 timeout 和重试,避免卡死) - 主节点需提前初始化数据目录并启动
mysqld;从节点首次同步前,若启用 GTID,需执行SET GLOBAL gtid_purged = ''(前提是主库已RESET MASTER)
PVC 绑定失败导致 Pod 卡在 Pending 怎么办
云厂商的默认 StorageClass(如 AWS EBS、Azure Disk、阿里云 cloud_efficiency)通常绑定到单可用区(AZ),而 StatefulSet 的调度器可能将新 Pod 调度到其他节点,造成 PVC 无法绑定。
- StorageClass 中必须设置
volumeBindingMode: WaitForFirstConsumer,确保调度器先选定 Node,再创建 PV,避免跨节点挂载失败 - PVC 的
accessModes只能是ReadWriteOnce,且resources.requests.storage建议显式指定(如20Gi),防止底层存储池超售 - 生产环境禁用
nfs-client或hostPath:前者不保证fsync落盘,易致 binlog 或 InnoDB redo 日志损坏;后者仅限单节点测试 - 推荐使用 CSI 驱动:
aws-ebs-csi-driver(AWS)、gce-pd-csi-driver(GCP)、longhorn.io(本地集群)
主库崩溃重建后从库复制中断怎么办
新 mysql-0 的 binlog position 和 GTID 已重置,旧从库直接 CHANGE MASTER TO 会报 Could not find first log file name in binary log index file。
- 不要依赖自动重连;
readinessProbe无法替代逻辑就绪判断,必须在 entrypoint 脚本中用mysqladmin ping -h mysql-0.mysql.default.svc.cluster.local轮询主库 - 主库重建后,从库需人工介入:要么用备份恢复 +
START SLAVE,要么执行RESET SLAVE ALL后重新CHANGE MASTER TO并指定新gtid_purged - 更稳妥的做法是引入租约机制(如 etcd 或 consul)防脑裂,避免多主写入;这点常被忽略,但却是生产环境高可用的隐性门槛











