不能用httpGet或tcpSocket是因为MySQL不监听HTTP端口,且tcpSocket仅检测端口连通性而无法验证SQL服务可用性;必须用exec执行mysqladmin ping来真实判断实例是否可服务。

livenessProbe 和 readinessProbe 必须用 exec 类型,不能用 httpGet 或 tcpSocket —— MySQL 官方镜像没暴露 HTTP 接口,也不响应 TCP 连接就认为“存活”。
为什么不能用 httpGet 或 tcpSocket?
很多初学者直接抄 Nginx 的探针写法,把 httpGet 指向 / 或改端口为 3306,结果探针永远失败:
• httpGet 会发起 HTTP 请求,MySQL 不监听任何 HTTP 端口,直接拒绝连接或超时;
• tcpSocket 虽能连上 3306 端口,但只检测端口通不通,无法判断 mysqld 进程是否真在响应 SQL 请求(比如卡在 recovery、权限初始化未完成、磁盘满导致拒绝新连接等);
• 只有 exec 执行 mysqladmin ping,才是真正验证 MySQL 实例是否可服务。
exec 探针怎么写才可靠?
核心是让容器内能执行 mysqladmin 并正确传参。注意三点:
• 镜像必须自带 mysqladmin(官方 mysql:8.0 / mysql:5.7 都有);
• 密码不能硬编码在命令里,要用环境变量注入;
• root 密码为空时要走不同分支(虽然生产严禁空密码,但测试环境常见)。
-
livenessProbe示例(重启触发点):exec: command: - sh - -c - "mysqladmin ping -u root -p${MYSQL_ROOT_PASSWORD} --silent" -
readinessProbe建议用同样命令,但initialDelaySeconds要比livenessProbe更长(比如 30s vs 120s),给 MySQL 充足的启动+恢复时间; - 务必加
--silent参数:避免输出多余文本干扰 exit code 判断; - 如果用了
Secret注入密码,确保env字段从valueFrom.secretKeyRef正确引用,否则${MYSQL_ROOT_PASSWORD}展开为空,命令失败。
参数调优容易踩哪些坑?
默认值往往不适合 MySQL:
-
initialDelaySeconds至少设为 60~120:MySQL 启动时可能要解压 InnoDB 表空间、重放 binlog、等待慢查询日志初始化,尤其挂了 PV 后首次启动更慢; -
timeoutSeconds不能低于 5:网络延迟 + 鉴权耗时 + 小概率锁表,短于 3 秒会导致误杀; -
failureThreshold建议设为 3~5:单次mysqladmin ping失败可能是瞬时 IO 峰值,连续失败才该动作; - 两个探针的
periodSeconds不建议设太密(如 5 秒),高频 ping 会增加 mysqld 负载,10~15 秒足够; - 别忽略
successThreshold:对readinessProbe设为 2,避免刚连上就切流量,给 mysqld 一点 warm-up 时间。
StatefulSet 场景下还要注意什么?
如果是用 StatefulSet 部署 MySQL(推荐),健康检查行为和 Deployment 一致,但额外要注意:
• PVC 挂载失败时,mysqladmin ping 会因无法访问 datadir 直接报错,此时 readiness 应快速失败,避免 Service 把流量导过去;
• 如果配置了主从,readinessProbe 可考虑加 mysql -e "SHOW SLAVE STATUS\G" | grep -q "Seconds_Behind_Master: 0" 判断从库同步延迟,但这会显著增加探针开销,慎用;
• livenessProbe 触发重启后,MySQL 会丢弃当前所有连接,应用层需处理连接中断重试逻辑。
真正起作用的健康检查,不是“让 Pod 变绿”,而是让 Kubernetes 在 MySQL 还没准备好时拦住流量、在它彻底卡死时果断重启。这些细节不调好,探针反而会成为故障放大器。


















