Kubernetes探针不依赖Golang,但Golang服务需自行实现符合语义的健康端点:/health仅检查HTTP就绪,/live可轻量检查核心依赖;须设Read/WriteTimeout、监听0.0.0.0、路径严格匹配、避免阻塞;YAML中initialDelaySeconds须覆盖启动耗时,timeoutSeconds≥handler处理时间且≤服务超时。

直接说结论:Kubernetes 的 livenessProbe 和 readinessProbe 本身不依赖 Golang,但如果你用 Golang 写 HTTP 服务,必须自己暴露符合 K8s 探针语义的健康端点——否则探针永远失败,Pod 反复重启。
为什么 /healthz 返回 200 还是被 K8s 杀掉?
常见错误是只实现一个返回 200 OK 的 /healthz,但没处理探针的请求头和超时逻辑。K8s 的 httpGet 探针默认不带 User-Agent,也不要求 CORS,但它严格校验状态码、响应时间、可连接性。
- 必须监听在
0.0.0.0:8080(或你指定的containerPort),不能只绑127.0.0.1 - 路径必须完全匹配
httpPath配置,比如配置了httpPath: /health,但 handler 注册的是/healthz→ 直接 404 - handler 不能有阻塞操作(如未设 timeout 的数据库连接),否则超过
timeoutSeconds(默认 1 秒)就判定失败 - Golang 默认
http.Server没设ReadTimeout/WriteTimeout,高负载下可能 hang 住,导致探针超时
用 net/http 写一个真正可用的健康端点
别用第三方 health check 库——多数库默认检查 DB 连接,而 readiness 应该只反映“能否接收流量”,liveness 才该检查核心依赖。先写最简可靠版本:
func main() {
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
// readiness:只检查自身 HTTP 服务是否就绪
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
})
<pre class="brush:php;toolbar:false;">http.HandleFunc("/live", func(w http.ResponseWriter, r *http.Request) {
// liveness:可加入轻量级依赖检查,如 Redis ping(带 context timeout)
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
// ... 检查关键依赖,失败则 WriteHeader(503)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "live"})
})
srv := &http.Server{
Addr: ":8080",
ReadTimeout: 5 * time.Second,
WriteTimeout: 5 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}
注意:/live 和 /health 是两个独立端点,对应 K8s 中不同的 probe 配置,不要混用。
K8s YAML 里 probe 参数怎么配才不翻车?
很多人把 initialDelaySeconds 设成 5,结果服务启动要 8 秒——Pod 直接被 kill。关键参数必须按实际启动耗时调整:
-
initialDelaySeconds:设为「应用完成初始化的最长时间」,Golang 二进制通常 2–3 秒,Web 框架加模板加载可能到 6 秒 -
periodSeconds:默认 10 秒太保守,HTTP 服务可缩到 3–5 秒;但别低于 2 秒,避免压垮服务 -
failureThreshold:默认 3 次失败才重启,对 liveness 建议保持 3,对 readiness 可设为 1(快速摘流量) -
timeoutSeconds:必须 ≥ Golang handler 的实际处理时间,且 ≤ReadTimeout(否则 K8s 先超时,服务还没响应)
示例片段:
livenessProbe:
httpGet:
path: /live
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
timeoutSeconds: 2
failureThreshold: 1
调试探针失败最有效的三步
别猜,直接进容器看真实行为:
- 进 Pod:
kubectl exec -it,然后用-- sh curl -v http://localhost:8080/health看状态码和耗时 - 查 K8s 事件:
kubectl describe pod,重点看 Events 区域的Liveness probe failed或Readiness probe failed后面的原始错误(比如Get \"http://10.244.1.3:8080/health\": dial tcp 10.244.1.3:8080: connect: connection refused就说明端口没监听对) - 开日志抓探针请求:
log.Println("HEALTH REQ:", r.Method, r.URL.Path, r.RemoteAddr),确认 K8s 确实发来了请求,且没被中间件拦截(比如 Gin 的Recovery()中间件可能吞掉 panic 导致 500)
最常被忽略的是:Golang 服务启动后,HTTP server 启动和路由注册之间存在微小时间窗口,initialDelaySeconds 必须覆盖这个间隙,否则第一次 probe 必然失败,而 failureThreshold=3 会让它多试两次才重启——这会掩盖真正问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











