必须暴露/readyz端点并同步检查DB、Redis、gRPC等真实依赖,任一失败返回503;用atomic控制就绪状态,所有探测带context超时且总耗时≤900ms;YAML中path、port、超时需与代码严格一致。

必须暴露 /readyz(或 /health)端点,且该端点要同步检查真实依赖;否则 readinessProbe 会一直失败,Service 始终 0 endpoints。
Go 代码里怎么写一个真正有效的就绪端点
就绪不是“进程没挂”,而是“能干活”。/readyz 必须同步调用关键依赖的轻量探测,任一失败就返回 503 Service Unavailable,不能只返回 200 OK。
- 用
atomic.Value或atomic.LoadInt32(&isReady)控制初始就绪状态,主服务初始化完成后才置为 true - DB 检查用
db.PingContext(ctx, 2*time.Second),不是db.Exec或长查询 - Redis 用
client.Ping(ctx).Err(),gRPC 用conn.GetState() == connectivity.Ready - 所有检查必须带 context 超时,总耗时严格 ≤
timeoutSeconds - 1(K8s 默认 timeout 是 1s,所以你最多只能花 900ms) - 响应体建议带具体失败项:
{"redis": "connection refused", "db": "timeout"},方便定位
Deployment YAML 里 readinessProbe 怎么配才不白写
YAML 配置和 Go 端点必须严丝合缝,路径、端口、超时三者错一个,探针就永远 failure。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
-
httpGet.path必须和 Go 里注册的完全一致(/readyz≠/ready,大小写敏感) -
httpGet.port必须等于容器内containerPort,不能靠环境变量推导——Go 代码写http.ListenAndServe(":8080", mux),YAML 就得写containerPort: 8080 -
initialDelaySeconds至少设为实测冷启动时间 + 3s(比如初始化 DB 连接池要 6s,这里至少填 9) -
timeoutSeconds: 3(别用默认 1),periodSeconds: 5,failureThreshold: 3,避免网络抖动误摘流量 - 别和
livenessProbe共用同一个路径——liveness用/healthz,readiness用/readyz
常见踩坑:为什么 curl 返回 200 却一直 NotReady
Kubernetes 不看响应体,只认状态码 + TCP 连通性 + 超时。很多问题藏在底层细节里。
立即学习“go语言免费学习笔记(深入)”;
- 忘记调
w.WriteHeader(http.StatusOK),只写w.Write([]byte("ok"))→ 探针收到 0 状态码,直接判失败 - 健康端点注册在 Gin 的
r.Use(authMiddleware)之后 → 所有请求被拦截,返回 401 或 404 - 用
http.ListenAndServe启动健康 server,但没加go关键字 → 主 goroutine 阻塞,整个服务卡死 - 每次探针都 new 一个
redis.Client→ fd 耗尽,后续所有连接失败 - 健康 handler 和业务路由共用同一个
http.ServeMux或gin.Engine→ 业务 panic 导致健康接口也 panic
最易被忽略的一点:就绪状态不是静态的。服务运行中依赖可能掉线,/readyz 必须实时反映这一变化——不是启动时检查一次就完事,而是每次请求都重新评估。

















