就绪探针必须返回2xx(推荐200)才算真正就绪,需检查db连通性、redis可写性、grpc依赖服务响应等真实依赖,而非仅端口可达;非就绪时应返回503。

就绪探针返回什么才算真正就绪
就绪探针不是“进程活着就行”,而是“服务能安全收流量才行”。很多 Go 服务把 /readyz 写成硬编码返回 200 OK,结果 DB 还没连上、配置还没加载完,K8s 就把 Pod 加进 Service 的 Endpoints,请求一来直接 panic。
- 必须检查真实依赖:DB 连通性(
db.Ping())、Redis 是否可写、gRPC 依赖服务是否响应200+{"status":"up"} - 不能只看端口通不通——
TCPSocketAction对 Go HTTP 服务毫无意义,它只确认监听了,不确认业务就绪 - 避免在 handler 里做耗时同步操作(如重试连接),否则探针超时(
timeoutSeconds默认 1 秒)会反复失败,Pod 卡在NotReady - 推荐用
HTTPGetAction,返回码严格限定为2xx;非就绪状态统一返回503 Service Unavailable,别用500或404
Go 应用怎么动态控制 /readyz 返回值
静态返回 200 是死路一条。真正的就绪状态得是可变的——比如收到 SIGTERM 后立刻拒绝新流量,但允许正在处理的请求完成。
- 用一个全局布尔变量(如
var isShuttingDown bool)配合读写锁(sync.RWMutex)保护 -
/readyzhandler 先检查该变量,为true就直接w.WriteHeader(http.StatusServiceUnavailable) - 在
PreStop钩子里主动触发降级:curl -f http://localhost:8080/readyz?down=true,让探针下一周期就失败 - 别等
SIGTERMhandler 里再改状态——信号到达和探针轮询有时间差,可能漏掉几秒流量
Readiness Probe 配置参数怎么设才不翻车
参数设错比不设还危险。常见现象是 Pod 反复进出 Ready 状态,或者冷启动时被 K8s 杀掉重启。
-
initialDelaySeconds必须 ≥ 应用冷启动耗时(加载 config、建 DB 连接池、预热缓存等)+ 2~3 秒缓冲,别拍脑袋写5 -
timeoutSeconds至少设为5,尤其当/readyz里做了依赖探测(DB Ping 超时可能达数秒) -
periodSeconds推荐10,太小(如2)会导致 kubelet 频繁发请求,压垮应用或误判 -
failureThreshold设为1是合理选择——只要一次失败,就立刻从流量池踢出,别等三次
为什么不能用 PostStart 做预热或依赖检查
很多人想在容器启动后立刻调用 curl http://localhost:8080/warmup,结果 Pod 永远卡在 ContainerCreating。
-
PostStarthook 执行时,Go HTTP server 很可能还没ListenAndServe,localhost:8080根本不通 - K8s 网络栈(CNI)此时未必 ready,即使 server 起了,
curl也可能因 DNS 或路由未就绪而失败 - hook 失败 = Pod 启动失败,没有重试机制,整个滚动更新会卡住
- 正确做法:预热逻辑写进 Go 主流程,在
http.ListenAndServe之前完成;依赖检查放/readyz,由探针驱动
最常被忽略的一点:就绪探针不是“开关”,而是“状态镜像”。你得在 Go 代码里真实反映服务的可用性,而不是靠 K8s 配置去猜。状态变了,探针就得立刻感知——延迟哪怕 10 秒,都可能引发雪崩。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











