statefulset是唯一可行选择,因其提供稳定pod名(如mysql-0)、固定dns解析、专属pvc绑定、有序启停及volumeclaimtemplates支持;deployment无序随机、共享存储、无独立网络标识,必然导致pvc错绑、数据错乱、gtid复制中断。

必须用 StatefulSet,不能用 Deployment;否则 Pod 重建后 PVC 可能错绑、数据错乱、GTID 复制中断。
为什么 StatefulSet 是唯一可行选择
MySQL 的每个实例需要独立身份、固定 DNS 名(如 mysql-0.mysql.default.svc.cluster.local)、专属存储卷和有序启停。这些特性 Deployment 全都不支持:
-
Deployment的 Pod 名是随机哈希值,重启后无法保证绑定原PVC - 所有副本共享同一组标签,
Service无法区分主从角色 - 没有序号控制,主从初始化顺序无法保障,
CHANGE REPLICATION SOURCE会失败 - 不支持
volumeClaimTemplates,无法为每个 Pod 自动生成专属PVC
volumeClaimTemplates 必须与 serviceName 配合使用
StatefulSet 中的 volumeClaimTemplates 不是“随便起名”,它依赖 serviceName 字段生成可解析的 Headless Service,进而让每个 Pod 获得稳定 DNS 名称。漏掉或写错会导致:
-
PVC创建失败,Pod 卡在Pending状态,报错:no persistent volumes available for this claim - Pod 启动后无法挂载
/var/lib/mysql,MySQL 进程直接退出,日志里反复出现Can't start server: Bind on unix socket - 主从同步时
source_host解析失败,SHOW REPLICA STATUS\G显示IO_Running: No,错误信息为error connecting to master
正确写法示例(关键字段对齐):
spec:
serviceName: mysql # 必须与 Headless Service 的 metadata.name 一致
volumeClaimTemplates:
- metadata:
name: data # 该名字将用于生成 PVC 名:data-mysql-0、data-mysql-1...
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
storageClassName: mysql-sc
ConfigMap 配置需按 Pod 序号差异化加载
MySQL 主从不能共用同一份 my.cnf。StatefulSet 没有内置“按序号选配置”机制,必须靠启动脚本或 InitContainer 判断当前 Pod 名(如 mysql-0 是主,mysql-1 是从),再软链接对应配置:
- ConfigMap 中应分拆
master.cnf和slave.cnf,避免server-id冲突 - 容器启动前必须运行 InitContainer,用
hostname判断序号,并执行:ln -sf /etc/mysql/conf.d/master.cnf /etc/mysql/my.cnf - 若跳过这步,所有 Pod 加载相同
server-id=1,GTID 复制会拒绝连接,报错:Replica has more GTIDs than the source - MySQL 8.0 默认启用
require_row_format,从库read_only=1必须显式设置,否则 DML 会意外成功
探针配置容易忽略 MySQL 8.0 的认证变更
MySQL 8.0 默认使用 caching_sha2_password 插件,而旧版探针命令(如 mysqladmin ping)可能因认证失败返回非零码,导致误判为宕机:
-
livenessProbe建议改用exec+mysql客户端,并指定插件:mysql --default-auth=mysql_native_password -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1" -
readinessProbe若检查从库状态,必须加SELECT @@replica_io_running, @@replica_sql_running,不能只查连接性 - 未设
initialDelaySeconds或设得太小(如5s),MySQL 还没完成初始化就触发探针,Pod 反复重启 - 资源限制过低(如
memory: 256Mi)会导致 InnoDB 缓冲池初始化失败,日志出现:InnoDB: Cannot allocate memory for the buffer pool
最常被跳过的一步:没有验证每个 PVC 是否真正绑定到不同 PV。尤其用本地存储时,多个 PVC 可能被调度到同一节点并复用同一个 PV,导致主从数据目录物理混用——此时即使配置全对,复制也会静默失败。











