404根本原因是路径、端口或中间件不匹配:Pod监听端口与Service targetPort不一致;Ingress默认探针路径为/healthz而应用只实现/health;或健康端点未走框架路由被中间件拦截。

直接返回 404,基本就是路径没对上、端口没对齐、或被中间件吞掉了——K8s 的 kubelet 不会猜你写了啥,它只按配置硬 GET,错一点就 404。
为什么 /health 返回 404,但 curl 本地却能通
常见现象:你在本地 curl http://localhost:8080/health 能拿到 200,但 K8s 的 livenessProbe 却持续报 404。根本原因通常是:
- Pod 内监听端口和 Service 的
targetPort不一致(比如代码监听:8080,但 Service 写了targetPort: 80或没写) - Ingress Controller 默认探测路径是
/healthz,而你只实现了/health,没对齐 - 用了框架路由(如 Gin),但注册方式错了:
http.HandleFunc("/health", ...)绕过了框架,导致路径未被注册进路由表 - 健康端点被中间件拦截(比如鉴权中间件对所有路径生效,
/health也被重定向或返回 401)
Gin/Echo/Fiber 中注册健康端点的正确姿势
别用 http.HandleFunc,必须走框架原生路由,否则中间件、上下文、日志全失效,K8s 探针也看不到这个路径。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- Gin:用
r.GET("/health", healthHandler),不是http.HandleFunc("/health", ...) - Echo:用
e.GET("/health", healthHandler),handler 签名必须是func(echo.Context) error - Fiber:用
app.Get("/health", healthHandler),handler 签名是func(*fiber.Ctx) error - 所有 handler 内部禁止调用
panic、log.Fatal或阻塞操作;必须显式写状态码:c.Status(http.StatusOK).JSON(map[string]string{"status": "ok"})
如何验证健康端点是否真被 K8s 看到
别只信本地 curl,要模拟 kubelet 的视角:
- 进 Pod 执行:
curl -v http://localhost:8080/health(确认进程自身响应正常) - 从同 namespace 的另一个 Pod 执行:
curl -v http://(确认 Service + targetPort 连通性):8080/health - 查 Ingress Controller 日志:
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep health,看它实际请求的是哪个路径 - 检查 Probe 配置是否带了 pathType 和 rewrite-target:如果 Ingress 注解写了
nginx.ingress.kubernetes.io/rewrite-target: /$2,而你的 Go 路由注册的是/health,那实际收到的请求可能是/health/或空路径,得按重写后路径注册
最容易被忽略的三个硬伤
这些点不排查,改十遍代码也没用:
-
Service的targetPort必须和 Go 进程ListenAndServe的端口完全一致(数字或字符串都行,但不能错位) - Ingress Controller 默认健康探测路径是
/healthz或/,不是你随便写的/actuator/health—— 要么改 Ingress 配置,要么在 Go 里同时暴露/healthz - 健康端点路由必须独立注册,不能套在
/api/v1前缀下再靠中间件做路径拼接,kubelet 不会执行 JS 或解析重定向
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










