必须同时配置livenessprobe和readinessprobe且不可共用端点;前者判断是否重启(轻量心跳,不查依赖),后者判断是否导流(检查db/消费者等就绪状态),二者探针路径、频率、阈值须独立设置。

直接结论:必须同时配置 livenessProbe 和 readinessProbe,且不能共用同一端点或相同逻辑;否则会掩盖“进程存活但业务卡死”的真实故障。
为什么不能只用 livenessProbe 或只用 readinessProbe
只配 livenessProbe 会导致 Kubernetes 在业务卡死时反复重启容器,但问题根源(如 goroutine 阻塞、连接池耗尽)并未修复,反而加剧抖动;只配 readinessProbe 则会让故障 Pod 一直留在服务中——它不接收新流量,但已建立的长连接、后台任务、消息消费仍在运行,可能造成数据重复、丢失或静默失败。
常见错误现象:READY 状态长期为 0/1 却无重启,或 RESTARTS 数持续上涨但服务看似“在线”。
-
livenessProbe的目标是“是否该杀掉并重建”,关注进程级/资源级崩溃(如 OOM、死锁、goroutine 泄漏) -
readinessProbe的目标是“是否该转发流量”,关注业务级就绪(如 DB 连通、配置加载完成、消费者 goroutine 启动成功) - 两者检查频率、超时、失败阈值应独立设置:
readinessProbe可更敏感(periodSeconds: 3),livenessProbe应更保守(periodSeconds: 10,避免误杀)
httpGet 探针路径和响应码必须区分语义
不要让 /healthz 同时承担存活与就绪判断。Go 服务中典型做法是:
针对 Kubernetes 仪表板和 Web UI 的浏览器自动化。适用于与 Kubernetes Dashboard、Grafana、ArgoCD UI 或其他 Web 界面交互。需要设置 MCP_BROWSER_ENABLED=true。
-
readinessProbe.httpGet.path: /readyz:检查内部状态,例如返回{"status":"ok","db_connected":true,"consumer_running":true},HTTP 状态码必须是200;任何依赖未就绪(如 Kafka 连接失败)就返回503 -
livenessProbe.httpGet.path: /healthz:只做轻量心跳,例如仅检查http.Server是否还在 accept 连接,不查下游依赖,返回200即可 - 避免在
/healthz中调用数据库或远程 API——这会让存活探针变成单点故障放大器
示例片段(YAML):
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 10
periodSeconds: 3
timeoutSeconds: 2
failureThreshold: 2
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
initialDelaySeconds 不是“启动时间预估”,而是最小安全等待窗口
这个参数不是让你填“我的服务平均启动要 12 秒”,而是填“从容器启动到第一个健康端点能稳定响应所需的最短时间”。填小了会导致探针在 handler 还没注册、mux 路由未初始化时就开始发请求,直接返回 404 或连接拒绝,触发误判。
- 对 Go net/http 服务,
initialDelaySeconds至少要比http.ListenAndServe启动耗时多 2–3 秒(考虑 TLS 握手、日志初始化等) - 如果服务有异步初始化(如后台 goroutine 加载缓存),这个延迟必须覆盖最慢路径——否则
readinessProbe会提前通过,流量进来时缓存为空,打垮下游 - 不要依赖
sleep或init()做同步等待;应在 handler 内部做状态检查(如原子变量标记“初始化完成”)
exec 探针在 Go 服务中几乎总是次选
虽然 YAML 支持 exec 类型探针,但在 Go 服务中用 cat /tmp/healthy 或 ps aux | grep myapp 是危险的:
-
ps检查只能确认进程存在,无法反映 goroutine panic 后未退出、或协程卡在 channel send 上 - 文件写入方式需额外同步机制(如信号量、flock),否则出现竞态:主 goroutine 写完文件后立即 panic,探针读到“健康”但实际已崩
- Kubernetes 执行
exec是 fork 新进程,频繁调用会增加节点负载,尤其在高密度部署场景 - 除非服务完全无网络能力(如离线批处理),否则优先用内置 HTTP 端点——它天然支持结构化响应、可观测性埋点、以及 Prometheus 直接抓取
真正容易被忽略的是:健康端点本身必须是幂等、无副作用、低开销的。一个 /readyz handler 里执行 DB.Ping() + Redis.Ping() + HTTP.Get("downstream"),等于把所有依赖的 P99 延迟叠加到每次探针上,极易触发 timeoutSeconds 超时。应该只查必要链路,并缓存最近一次结果(带 TTL)。










