就绪探针应返回503(依赖不可用)或200(全部就绪),存活探针应返回500(进程异常)或200(正常);路径建议/readyz和/healthz;需用context控制超时,避免阻塞;K8s探针参数须匹配服务启动与恢复节奏,且健康检查应独立端口部署。

HTTP 健康检查端点该返回什么状态码
就绪(readiness)和存活(liveness)探针在 K8s 中本质就是对 HTTP 端点的 GET 请求,K8s 只看 HTTP 状态码是否在 200–399 范围内。但实际部署中,很多人直接返回 200 OK 即使数据库连不上——这会让 K8s 认为服务“健康”,继续转发流量,结果请求全失败。
正确做法是:就绪探针应检查依赖服务(如 DB、Redis、下游 API),任一不可用就返回 503 Service Unavailable;存活探针只检查自身进程是否卡死(如 goroutine 泄漏、死锁),一般只做轻量级内存/panic 检查,失败时返回 500 Internal Server Error。
- 就绪端点路径建议用
/readyz,存活用/healthz(K8s 社区惯例,工具链兼容性好) - 避免在
/healthz中查数据库——它不该有外部依赖,否则一次 DB 故障会触发所有 Pod 重启 - 返回体内容不重要,但建议加简单 JSON 标识,比如
{"status":"ok"},方便人工 curl 验证
Go HTTP handler 怎么写才不阻塞且可取消
默认的 http.HandleFunc 不感知上下文超时,如果健康检查里调了带网络 IO 的依赖(比如 ping MySQL),又没设超时,整个探针会卡住,K8s 默认 1 秒超时后反复重试,可能压垮服务。
必须用 http.ServeMux 或 http.HandlerFunc 显式接收 context.Context,并在依赖调用中传入带超时的子 context。
立即学习“go语言免费学习笔记(深入)”;
- 用
ctx, cancel := context.WithTimeout(r.Context(), 500*time.Millisecond)控制单次检查上限 - DB 连接检查别用
db.Ping(),改用db.PingContext(ctx)(Go 1.8+) - 不要在 handler 里启动 goroutine 异步检查——探针是同步请求,goroutine 无法影响返回状态
func readinessHandler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 300*time.Millisecond)
defer cancel()
if err := db.PingContext(ctx); err != nil {
http.Error(w, "db unreachable", http.StatusServiceUnavailable)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
K8s 探针配置参数怎么设才不误杀 Pod
参数配错比代码写错更危险:太激进会导致滚动更新失败,太宽松会让故障 Pod 长期留在服务列表里。
关键不是“设多大”,而是匹配你的服务冷启动时间和依赖恢复节奏。例如,PostgreSQL 启动慢,initialDelaySeconds 就不能设成 5。
-
initialDelaySeconds:从容器启动到首次探针开始的秒数,Go 服务建议设10–15(覆盖编译型二进制加载、DB 连接池 warmup) -
periodSeconds和timeoutSeconds要满足timeoutSeconds < periodSeconds,否则并发探针会堆积;常见组合是periodSeconds: 10,timeoutSeconds: 2 -
failureThreshold对就绪探针建议设1(快速摘流),对存活探针建议3–5(避免偶发网络抖动触发重启)
为什么 /metrics 和 /healthz 不能共用同一个端口暴露给 K8s
不是技术限制,是安全与职责分离问题。Prometheus 抓取 /metrics 是长期、高频、可能带认证的拉取行为;而 K8s kubelet 对 /healthz 是短连接、无认证、每秒级轮询。把它们混在一起,容易因指标采集卡顿拖慢健康检查,或让探针请求意外触发 metrics 收集逻辑(比如某些库的 metrics endpoint 会主动打点)。
更隐蔽的风险是:如果你用 net/http/pprof 或其他调试端点也挂载在同一 mux 下,K8s 探针可能无意中触发 pprof 的 CPU profile,导致性能抖动。
- 生产环境强烈建议用两个独立
http.Server:一个走:8080(业务 + metrics),一个走:8081(仅/healthz和/readyz) - 在 K8s YAML 中,
livenessProbe和readinessProbe的port字段明确指向8081,避免混淆 - 别为了“省端口”把健康检查塞进反向代理后——proxy 的连接复用、缓冲策略可能干扰探针超时判断
200 后,K8s 仍需等待 minReadySeconds(Deployment 配置)才将 Pod 加入 Service endpoints。这个值如果设得比应用真正能处理请求的时间还短,第一批流量进来照样 5xx。










