根本原因是operator未等待旧pod退出就启动新pod,导致pv或mysql.sock文件锁冲突;需检查partition、podmanagementpolicy、pvc独立性、prestop脚本及gtid配置等。

滚动升级时MySQL Pod反复重启失败,Operator日志报 Failed to acquire lock
根本原因是Operator在执行滚动升级时,未等待旧Pod完全退出就启动新Pod,导致多个实例同时尝试写入同一份PV或争抢mysql.sock文件锁。尤其当使用NFS或HostPath类存储时,文件锁语义不严格,容易触发冲突。
- 确认StatefulSet的
updateStrategy.rollingUpdate.partition是否设为合理值(如从最后1个Pod开始升级,设为2表示只升级序号≥2的Pod) - 检查MySQL Operator自定义资源(CR)中
spec.podManagementPolicy是否为OrderedReady(必须,否则并行启动会破坏主从同步顺序) - 确保PV绑定模式为
Retain且每个Pod有独立PVC——不能共用同一个volumeClaimTemplates名称但未加{{.Index}}模板变量 - 升级前手动执行
kubectl exec -it mysql-0 -- mysqladmin shutdown验证单实例能否干净退出;若卡住,说明mysqld进程未响应SIGTERM,需在容器lifecycle.preStop里加mysqladmin shutdown -u root -p$MYSQL_ROOT_PASSWORD
Operator升级后主从复制中断,SHOW SLAVE STATUS\G显示Seconds_Behind_Master: NULL
这是滚动升级期间主库切换未被Operator正确感知所致。多数MySQL Operator(如Oracle MySQL Operator、Presslabs的)默认依赖mysql-operator CR里的spec.replication.primary字段静态指定主节点,而滚动升级时该字段未自动更新。
- 改用基于GTID的复制:在CR中启用
spec.replication.gtid: true,并确保所有Pod启动时带--gtid-mode=ON --enforce-gtid-consistency=true - 禁用Operator的“固定主库”逻辑——有些Operator版本(如v0.14.0之前)硬编码主Pod为
mysql-0,升级时若mysql-0被重建,新Pod可能因binlog position不连续无法接续复制 - 观察
mysql-operatorPod日志中是否有reconciling primary role for mysql-1类信息;没有则说明Operator未触发主角色再选举,需升级Operator到支持自动failover的版本(如v0.17.0+) - 临时修复:升级完成后手动执行
kubectl patch mysqlcluster mycluster -p '{"spec":{"replication":{"primary":"mysql-1"}}}' --type=merge,再进新主库执行START SLAVE;
升级卡在Waiting for pod mysql-2 to be ready,但kubectl get pod显示Running
Operator判断Pod“就绪”不仅看Phase=Running,还会执行readinessProbe中的exec命令(如mysqladmin ping -u root -p$MYSQL_ROOT_PASSWORD)。常见问题是密码环境变量未注入或MySQL启动慢于probe超时。
- 检查Pod的
env字段是否包含MYSQL_ROOT_PASSWORD——某些Operator版本(如早期KubeDB)需显式在CR中配置spec.databaseSecret,否则密码为空导致mysqladmin认证失败 - 调大
readinessProbe.initialDelaySeconds(至少60秒),因为MySQL在挂载大容量PV后首次启动可能耗时超过30秒 - 将
readinessProbe.exec.command改为更宽松的检查:["sh", "-c", "mysqladmin ping -u root -p\"$MYSQL_ROOT_PASSWORD\" 2>/dev/null || exit 1"],避免stderr干扰 - 确认
securityContext.runAsUser与MySQL数据目录属主一致(通常为999),否则mysqladmin因权限拒绝无法访问socket文件
升级后客户端连接503,kubectl logs显示Operator反复报failed to sync MySQLCluster: context deadline exceeded
这通常是Operator控制器循环中调用Kubernetes API超时,而非MySQL本身问题。滚动升级期间大量Pod重建会触发密集的List/Watch事件,若Operator部署在资源紧张的节点上,或集群API Server负载高,就会持续超时。
- 给Operator Deployment加
resources.limits.memory: 512Mi和resources.requests.cpu: 200m——实测低于300m CPU时,在10节点集群上处理3副本MySQL升级易超时 - 在Operator CR中设置
spec.healthCheckPeriod: 30s(默认10s),降低健康检查频率,减少API压力 - 检查Operator使用的ServiceAccount是否绑定了足够RBAC权限——缺失
endpoints或events的list/watch权限会导致部分同步逻辑阻塞 - 升级前先暂停Operator:
kubectl scale deploy mysql-operator --replicas=0,等所有Pod进入Running状态后再恢复,避免升级过程与Operator reconcile竞争
滚动升级真正难的不是步骤,而是让Operator“理解”MySQL的状态迁移边界——它得知道什么时候该等主库刷盘完成,什么时候能安全切断从库IO线程。这些细节藏在Operator的Reconcile逻辑里,不看源码很难预判,所以升级前务必在测试环境跑通完整链路:从修改镜像版本→触发升级→观察主从延迟→验证应用读写。











