Kratos默认不内置/healthz端点,因其设计遵循“显式优于隐式”,所有HTTP路由须开发者手动注册,避免语义冲突与隐式行为风险;必须在初始化阶段显式注册轻量、无副作用的健康检查handler,并严格区分liveness(进程级存活)与readiness(依赖级就绪)探针语义及实现。

Kratos 框架本身不内置健康检查端点,必须手动注册;Kube 探针配置错误是导致 Pod 频繁重启或流量 503 的最常见原因。
为什么 Kratos 默认没有 /healthz?
Kratos 是一个面向云原生的 Go 微服务框架,设计上强调“显式优于隐式”。它不会自动暴露任何 HTTP 端点(包括健康检查),所有路由需开发者自行注册。这避免了默认行为与业务语义冲突——比如你用 /healthz 做 liveness,但框架却悄悄把它当成 readiness 用,或者返回了 200 却没校验数据库连接。
常见错误现象:curl http://pod-ip:8000/healthz 返回 404,但 livenessProbe 已配置为该路径,结果容器启动后立刻被 Kubelet 重启。
- 必须在
main.go或服务初始化阶段显式注册 handler,例如:http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{"status":"ok"}`)) }) - 不要复用
/metrics或/debug/pprof路径做健康检查——它们响应慢、权限敏感,且可能被 Prometheus 抓取干扰 probe 判断 - 若使用 Kratos 的
transport/http.NewServer,应通过server.Handle("/healthz", healthHandler)注册,而非直接操作http.DefaultServeMux,避免与 gRPC 或其他 transport 冲突
livenessProbe 和 readinessProbe 能共用一个 handler 吗?
技术上可以,但语义上强烈不建议。二者失败后果完全不同:livenessProbe 失败会触发容器重启,readinessProbe 失败只会摘流量。共用 handler 容易让一次短暂依赖抖动(如 DB 连接超时)既导致流量中断,又引发无意义重启。
典型误配:readinessProbe 和 livenessProbe 都指向 /healthz,而该 handler 检查了数据库、Redis、下游 gRPC 服务——任意一个临时不可用,就同时触发摘流 + 重启。
-
livenessProbe应只检查进程级存活:例如原子变量atomic.LoadInt32(&isRunning)或简单内存分配,响应时间必须远小于timeoutSeconds -
readinessProbe才应检查完整依赖链:DBPingContext、RedisPing、关键下游grpc_health_v1.HealthClient.Check,并设置合理超时(建议 ≤timeoutSeconds - 1s) - Startup Probe 存在时,
livenessProbe可完全禁用(设initialDelaySeconds极大),由 startup 探针接管启动期判断
Kubernetes 探针参数踩坑清单
几乎所有 “CrashLoopBackOff” 或 “Endpoints 为空” 问题,都源于这几个参数值和实际应用行为不匹配。
常见错误现象:kubectl get pods 显示 RESTARTS 持续增长,或 kubectl get endpoints my-service 中 SUBSETS 为空,但容器日志显示服务已正常启动。
-
initialDelaySeconds设置过短:Kratos 应用加载配置、初始化 gRPC client、连接 etcd 可能耗时 8–15s。若设为3,Kubelet 在应用还没完成 init 就开始探测,必然失败 → 重启循环。建议:startupProbe 存在时设 0;否则 liveness 至少 20s,readiness 至少 10s -
failureThreshold设为 1:网络抖动或 GC STW 导致单次 probe 超时即摘流/重启。应设为 ≥3,配合periodSeconds形成容忍窗口(如periodSeconds: 10,failureThreshold: 3≈ 允许连续 30s 不可用) -
timeoutSeconds大于periodSeconds:Kubelet 不会等待超时结束就发起下一次 probe,造成并发 probe 积压,CPU 升高甚至 handler 阻塞。必须满足timeoutSeconds
如何验证探针是否生效?
别只看 Pod 状态。真正要确认的是 Kubelet 是否按预期执行了探测,并得到正确响应。
核心验证动作:kubectl describe pod 查看 Events 区域,重点找类似以下内容:
Normal Scheduled 2m10s default-scheduler Successfully assigned default/myapp-7c8d9b6f4d-xyz12 to node-01 Normal Pulling 2m8s kubelet Pulling image "myrepo/myapp:v1.2" Normal Pulled 1m55s kubelet Successfully pulled image "myrepo/myapp:v1.2" Normal Created 1m54s kubelet Created container myapp-container Normal Started 1m53s kubelet Started container myapp-container Warning Unhealthy 1m20s kubelet Liveness probe failed: HTTP probe failed with statuscode: 503 Normal Killing 1m20s kubelet Container myapp-container failed liveness probe, will be restarted
如果没看到 Unhealthy 或 Killing 事件,说明 probe 根本没触发(路径错、端口错、或 initialDelaySeconds 还没到);如果频繁出现 Unhealthy,则需结合应用日志确认 handler 是否真返回了非 2xx 状态码,或是否因超时被 Kubelet 主动中断。
最容易被忽略的一点:Kubelet 的 probe 请求**不携带 Host 头、不走 Ingress、不经过 Service**,是直接访问 Pod IP + containerPort。所以你在 Ingress 或 Service 层做的重定向、鉴权、Header 注入,对 probe 完全无效——必须确保容器内服务能直接响应 GET /healthz。











