就绪探针必须检查真实依赖连通性,不能仅返回200;pod显示ready但持续503,主因是/readyz未验证db、redis等关键依赖,需用context超时串行调用pingcontext()等轻量检查,失败即返503。

就绪探针必须检查依赖连通性,不能只返回200
Pod显示READY 1/1但请求持续503,大概率是readinessProbe配置太轻——比如只访问/health并返回{"status":"ok"}。Gin进程起来了,路由注册了,HTTP能通,但PostgreSQL连接池没建好、Redis还没连上,流量一进来就炸。
真实就绪状态必须同步验证关键依赖:
-
db.PingContext(ctx, timeout):超时建议 ≤3s,用context.WithTimeout包装 -
redis.Client.Ping(ctx):避免阻塞 probe,失败立即返回http.StatusServiceUnavailable - 不要在
/readyz里查Consul服务列表或调其他微服务接口——这些该走单独的/healthz?deep=true或监控告警链路 - 所有检查必须串行执行,任意一项失败即终止,不重试、不降级
Gin里怎么写一个可组合的/readyz handler
硬编码一堆Ping()会让逻辑耦合、难测试、没法按环境开关检查项。推荐用接口抽象:
type ReadinessChecker interface {
Name() string
Check() error
}
func NewDBChecker(db *sql.DB) ReadinessChecker {
return &dbChecker{db: db}
}
func (c *dbChecker) Check() error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
return c.db.PingContext(ctx)
}
注册时聚合多个检查器:
func readinessHandler(checkers []ReadinessChecker) gin.HandlerFunc {
return func(c *gin.Context) {
for _, chk := range checkers {
if err := chk.Check(); err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"error": chk.Name(), "detail": err.Error()})
return
}
}
c.JSON(http.StatusOK, gin.H{"status": "ready"})
}
}
// 使用
r.GET("/readyz", readinessHandler([]ReadinessChecker{
NewDBChecker(db),
NewRedisChecker(redisClient),
}))
存活探针别设太短,也别用TCP探针
livenessProbe设成periodSeconds: 5是高危操作。Gin应用偶尔GC停顿、慢SQL、或临时网络抖动,都可能让probe失败,触发无意义重启,形成雪崩循环。
更糟的是用tcpSocket探针——它只确认端口开着,完全不管Gin路由是否加载、中间件是否就位、甚至gin.Engine有没有初始化完。
- 改用
httpGet探针,路径设为轻量/healthz(仅检查进程和路由基础可用) -
initialDelaySeconds至少30秒,给冷启动留足时间 -
periodSeconds建议15–30秒,配合failureThreshold: 3防误判 - 这个端点里**不要**做任何依赖检查,否则和
/readyz语义冲突
Kubernetes YAML里探针配置容易漏的关键字段
YAML看着简单,但少配一个字段就可能导致探针失效或行为异常:
-
timeoutSeconds默认1秒,对带DB检查的/readyz远远不够——必须显式设为4(略大于检查超时总和) -
successThreshold默认1,但startupProbe场景下建议保持1;readinessProbe不用改 -
failureThreshold默认3,对livenessProbe够用,但readinessProbe建议调高到5,避免Pod刚上线就被踢出Endpoint - 别忘了
initialDelaySeconds——Gin应用冷启动常需10–20秒,设太小等于没配
最易被忽略的是:就绪探针通过后,Kubernetes不会立刻把Pod加进Endpoint,而是等endpoints资源同步完成,这过程可能有秒级延迟。如果滚动更新压测时发现新Pod“上线即503”,先kubectl get endpoints -o wide确认它是否真进了列表。











