健康检查接口必须返回200且响应体为空或极简,Kubernetes的livenessProbe和readinessProbe仅依赖HTTP状态码判断,不解析响应体;返回200即通过,非2xx则触发重启或摘流量,避免JSON响应、耗时操作、中间件拦截及监听localhost等常见错误。

健康检查接口必须返回 200 且响应体为空或极简
Kubernetes 的 livenessProbe 和 readinessProbe 默认只看 HTTP 状态码,不解析响应体。只要返回 200 OK,就认为检查通过;返回非 2xx(如 503、404)即触发重启或摘流量。常见错误是返回 200 但带 JSON(如 {"status":"ok"}),这虽不影响探测逻辑,却增加不必要的网络开销和 GC 压力。
实操建议:
- 用
http.HandleFunc注册路径(如/healthz),直接调用w.WriteHeader(http.StatusOK),不调用w.Write;或仅写空字节:w.Write(nil) - 避免在 handler 中做耗时操作(如 DB 连接池 ping、HTTP 外部调用),否则会拖慢 kubelet 探测节奏,导致误判
- 若需区分 liveness/readiness 语义,应拆成两个独立端点(如
/healthz和/readyz),不要靠 query 参数判断——kubelet 不支持传参
不要依赖日志或 panic 来“暴露”健康问题
有人习惯在 probe handler 里加 log.Println("checking db...") 或故意 panic("db down"),指望靠日志或崩溃让运维发现异常。这是错的:Kubernetes 不读日志判断健康,panic 会导致进程退出,触发容器重启,反而掩盖了真实故障点(比如 DB 暂时抖动本该等恢复,而非立刻杀进程)。
实操建议:
- probe handler 内只做轻量级同步检查(如
db.Stats().OpenConnections > 0),失败时返回http.StatusServiceUnavailable(503) - 把 DB 连通性、依赖服务连通性等检查结果缓存到内存变量中,由后台 goroutine 定期刷新(如每 10 秒 ping 一次),handler 只读缓存——避免每次 probe 都建连接
- 对不可控外部依赖(如第三方 API),设置超时(
context.WithTimeout)并捕获context.DeadlineExceeded,返回 503 而非 panic
HTTP server 必须绑定 0.0.0.0 且监听 probe 配置的端口
本地开发时习惯绑 localhost:8080,但容器内 kubelet 是从宿主机网络命名空间发起请求,目标 IP 是 Pod IP(如 10.244.1.3),不是 127.0.0.1。若 server 只监听 127.0.0.1,probe 会一直超时,日志里看到的是 connection refused。
实操建议:
- 启动 server 时明确用
":8080"(即0.0.0.0:8080),不要写"localhost:8080"或"127.0.0.1:8080" - 在 Deployment 的
containers[].ports[]中声明该端口,并确保livenessProbe.httpGet.port与之一致(可填数字或 name,但 name 必须匹配 port 名) - 若用
http.Get在本地测试 probe 路径,记得用curl http://,而不是:8080/healthz curl http://localhost:8080/healthz
Probe 超时、重试、初始延迟必须与 Go HTTP server 启动时间对齐
Go 程序启动后,HTTP server 并非瞬间就绪——要加载配置、初始化 DB 连接池、注册路由等。若 initialDelaySeconds 设太小(如 1 秒),而 server 实际 3 秒才真正 ListenAndServe,kubelet 就会连续失败几次后杀掉容器,形成 CrashLoopBackOff。
实操建议:
- 在 main 函数中,server 启动前打一条日志(如
log.Println("HTTP server starting on :8080")),再调用http.ListenAndServe;观察 pod logs 确认启动耗时 -
initialDelaySeconds至少设为启动耗时 + 2 秒缓冲;timeoutSeconds建议 ≤ 1,因为 kubelet 默认等待 1 秒就判定超时 - 避免在 handler 里做阻塞操作,否则单次 probe 耗时可能远超
timeoutSeconds,导致反复失败
最易被忽略的一点:probe 路径必须是纯粹的 HTTP handler,不能依赖中间件(如 auth middleware)或路由框架的全局拦截逻辑——除非你确认所有 probe 请求都绕过了鉴权。Kubernetes 不带任何 header 或 cookie 发起 probe,一旦中间件返回 401/403,就等于直接宣告服务不健康。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











