健康检查端点必须用http.HandleFunc注册而非http.Handle,因后者要求实现http.Handler接口,而裸函数不满足;正确写法是http.HandleFunc("/healthz", handler),且handler必须返回200状态码、无额外头或body。

健康检查端点必须用 http.HandlerFunc 而非 http.Handle 注册
很多 Go 新手直接写 http.Handle("/healthz", myHandler),结果 Kubernetes 探针返回 404。这是因为 http.Handle 要求 handler 实现 http.Handler 接口(即含 ServeHTTP 方法),而裸函数不是接口实现体。正确做法是传入函数字面量或显式转换:http.HandleFunc("/healthz", healthzHandler) —— 这个函数签名必须是 func(http.ResponseWriter, *http.Request)。
常见错误现象:Kubernetes 日志里持续报 Liveness probe failed: HTTP probe failed with statuscode: 404,但本地 curl http://localhost:8080/healthz 却能通 —— 很可能是因为路由注册方式不一致(比如用了 http.ServeMux 自定义 mux 但没传给 http.Server)。
- 始终用
http.HandleFunc注册简单健康端点 - 若需复用逻辑(如带日志、超时),封装成闭包:
http.HandleFunc("/healthz", withLogging(healthzHandler)) - 避免在 handler 内部调用
log.Fatal或 panic,这会 kill 整个 server
/healthz 响应必须返回 200 且无 body 或仅纯文本
Kubernetes 的 livenessProbe 和 readinessProbe 默认只检查 HTTP 状态码,不解析响应体。标准做法是返回空 body + 200 OK,或返回 OK(不含换行、空格、JSON、HTML)。任何额外头字段(如 Content-Type: application/json)或非 200 状态码都会被判定为失败。
使用场景:你可能想返回结构化信息供人工排查(如当前连接数、DB 连通性),但那属于 /livez 或自定义 debug 端点,不能混进 /healthz —— 否则探针行为不可靠。
- 最简实现:
w.WriteHeader(http.StatusOK),不调用w.Write - 若要加可读内容,只写纯文本:
w.Write([]byte("OK")),别用fmt.Fprintf(可能带空格或换行) - 禁止设置
Content-Length头(net/http会自动计算,手动设错会导致 connection reset)
HTTP server 必须显式设置 ReadTimeout 和 WriteTimeout
默认的 http.Server 没有超时控制,一旦 handler 阻塞(如 DB 查询卡住、外部 API 不响应),整个健康检查线程会 hang 住,Kubernetes 在几秒后就判定探针失败并重启 Pod。这不是 handler 逻辑问题,而是 server 配置缺失。
性能影响:超时值不能设得太短(比如 100ms),否则网络抖动时误判;也不宜过长(如 30s),会拖慢故障发现速度。Kubernetes 默认探针超时是 1 秒,所以 server 级超时建议设为 500–800ms。
- 必须用
&http.Server{Addr: ":8080", ReadTimeout: 800 * time.Millisecond, WriteTimeout: 800 * time.Millisecond} - 不要依赖
http.ListenAndServe,它用的是默认 server,无法设超时 - 启动时用
go server.ListenAndServe()并捕获http.ErrServerClosed,避免 panic 退出
多容器 Pod 中,livenessProbe 和 readinessProbe 的端口/路径要严格对齐
Golang 服务监听在 :8080,但 Kubernetes YAML 里写成了 port: 80 或路径写成 /health,这是最常被忽略的配置错位。Kubernetes 不会自动映射或纠错 —— 它只按声明去发 HTTP 请求。
容易踩的坑:用 envoy 或 istio-proxy sidecar 时,健康检查可能被拦截;此时要么把探针改成 exec 类型,要么确保 sidecar 允许 /healthz 流量直通应用容器(通过 traffic.sidecar.istio.io/includeInboundPorts 控制)。
- 检查 YAML 中
livenessProbe.httpGet.port是否等于容器ports.containerPort - 确认
httpGet.path和 Go 代码中http.HandleFunc的路径完全一致(区分大小写、尾部斜杠) - 用
kubectl port-forward pod/name 8080:8080本地验证,再 curl 对应路径
真正麻烦的从来不是写一个 200 响应,而是让这个响应在 CPU 飙高、网络分区、sidecar 注入、probe 频繁重试等真实场景下依然稳定返回 —— 所以超时控制、路径对齐、handler 隔离,比逻辑本身更关键。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











