buffalo默认不提供健康检查端点,必须手动在servemux上注册/healthz和/readyz裸handler,否则kubernetes探针因404失败导致持续重启或流量中断;需避开middleware、匹配port与超时参数,并确保handler在app.serve()前注册。

Buffalo 默认不提供健康检查端点,必须手动添加 HTTP handler 才能配置 Kubernetes 的 livenessProbe 和 readinessProbe。 它没有内置 /healthz 或 /readyz 路由,直接套用标准探针配置会触发持续重启。
为什么 Buffalo 的默认路由不能直接用作探针
Buffalo 的 app.Routes() 生成的路由树不包含任何健康端点;buffalo dev 或 buffalo build 启动的服务监听所有注册 route,但不会自动暴露 GET /health 这类运维路径。Kubernetes 探针发请求过去,返回 404,probe 就失败。
-
livenessProbe失败 → Pod 被 kill 并重建 -
readinessProbe失败 → Endpoint 不加入 Service,流量被切断 - 两者都依赖一个稳定、低开销、不触发业务逻辑的 HTTP handler
如何在 Buffalo 中添加健康检查端点
最稳妥的方式是绕过 Buffalo 的 action 机制,直接在 app.go 的底层 http.ServeMux 上注册裸 handler。这样避免中间件(如 session、CSRF、auth)干扰,也防止因模板渲染或 DB 连接导致探针误判。
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
- 打开
app.go,找到app := buffalo.New(buffalo.Options{...})之后的位置 - 插入以下代码(Go 1.26+ 兼容):
app.ServeMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
app.ServeMux.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
// 可选:检查数据库连接、缓存、下游依赖
// 但建议只做轻量检查,否则 readiness probe 延迟升高
w.WriteHeader(http.StatusOK)
w.Write([]byte("ready"))
})
- 不要用
app.GET("/healthz", HealthHandler)—— 这会走完整 middleware 链,且可能因未初始化 context 报 panic - 确保该 handler 在
app.Serve()之前注册,否则不生效
Kubernetes Deployment 中的探针配置要点
探针路径、超时和阈值必须匹配你注册的 handler。尤其注意 initialDelaySeconds:Buffalo 启动慢(反射扫描 actions/ 目录),冷启动常超 10 秒。
-
livenessProbe示例(放在 container spec 下):
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
-
readinessProbe示例(同级):
readinessProbe:
httpGet:
path: /readyz
port: 3000
initialDelaySeconds: 12
periodSeconds: 5
timeoutSeconds: 2
successThreshold: 1
- Port 必须与容器
EXPOSE或containerPort一致(Buffalo 默认 3000,Gradio 类项目常用 7860) - 不要把
readinessProbe和 DB 连接检查绑死——微服务场景下,DB 短暂不可用不应让整个 Pod 脱离流量 - 如果用了
--api模式,确认没残留plugins.Static()或 favicon 中间件,它们可能拦截/healthz
容易被忽略的坑
Buffalo 的 app.ServeMux 是标准 http.ServeMux,但它在 app.Serve() 内部被封装进 http.Server 实例,且不暴露 Server.Handler 字段。这意味着你无法用 http.StripPrefix 或 http.NotFoundHandler 替换根 handler —— 所有探针路径必须显式注册,且不能依赖中间件链的“兜底”行为。
- 删掉
templates/和assets/后,仍要检查app.Use(plugins.Favicon())是否存在,它会劫持所有GET /favicon.ico,而某些探针客户端(如旧版 kubelet)会顺带请求该路径,导致 404 波动 - 若使用
buffalo build --static产出二进制,确保构建环境 GOOS=linux,否则 handler 注册逻辑在容器内可能因 syscall 差异静默失效 - Ingress Controller(如 Nginx)默认不透传
Connection: close,而 Buffalo 的探针 handler 若没显式w.Header().Set("Connection", "close"),可能被复用长连接卡住,造成 probe 超时










