K8s liveness probe 必须返回200且不依赖外部服务,推荐裸路由返回极简响应;/health 不应连DB或复用业务接口;liveness仅检查进程存活,readiness才检查DB等依赖。

返回 200 就够了吗?K8s liveness probe 的 HTTP 状态码陷阱
不是所有 200 都能被 K8s 接受为“健康”。liveness probe 默认只认 200–399,但很多框架(比如 FastAPI)默认把 422 Unprocessable Entity 或 503 Service Unavailable 当作业务错误返回——这会让 K8s 误判为容器不健康,直接重启。
- 必须确保健康检查端点在**任何依赖正常时返回
200**,且 body 为空或极简(避免序列化失败) - 不要复用业务接口做探针,比如
/api/v1/users;它可能因 DB 连接池满、下游超时等返回500,但数据库本身可能只是临时抖动,不该触发重启 - FastAPI 中别用
@app.get("/health", response_model=HealthResponse)—— 如果HealthResponse的字段校验失败(如 datetime 格式不对),会隐式转成422 - 推荐写法:裸 route + 原生
return Response(status_code=200)(Starlette)或return {"status": "ok"}(FastAPI),不走 Pydantic 验证
要不要连数据库?/health 的依赖范围怎么划
连 DB 是最常见也最容易翻车的决定。K8s 的 liveness probe 设计初衷是判断“进程是否卡死”,不是“服务是否全链路可用”。过度检查反而让容器在短暂 DB 波动时被反复杀死。
- 基础版(推荐默认):只检查 Python 进程存活 + 关键内存结构(如
threading.active_count()不异常暴涨)、必要配置加载成功 - 进阶版(仅当 DB 故障必然导致服务不可恢复时):加轻量级 DB ping,比如 PostgreSQL 用
SELECT 1,MySQL 用PING,**超时必须设短(≤1s)且忽略连接拒绝错误** - 绝对不要在这里调外部 API、读大文件、查 Redis keys —— 这些该交给 readiness probe 或单独的监控系统
- 示例(Flask):
@app.route('/health')<br>def health():<br> try:<br> db.session.execute('SELECT 1').fetchone()<br> return {'status': 'ok'}, 200<br> except Exception:<br> return {'status': 'db_unreachable'}, 503→ 错!这个503会触发重启。应改为return {'status': 'ok'}, 200,只记录日志
Python Web 框架里怎么写才不踩坑(FastAPI / Flask / Django)
不同框架对中间件、异常处理器、响应包装的处理差异很大,同一个 /health 路由在不同框架下行为可能完全不同。
- FastAPI:
@app.get("/health", include_in_schema=False)必加,避免 Swagger 自动生成文档时带入验证逻辑;禁用response_model,直接return JSONResponse(content={"status": "ok"}, status_code=200) - Flask:绕过所有
@app.errorhandler,用make_response构造原始响应,避免被全局异常拦截器转成500 - Django:别用
JsonResponse(它可能触发 CSRF 中间件);改用HttpResponse("ok", status=200, content_type="text/plain"),最稳妥 - 所有框架都要关掉该路由的日志输出(如 Flask 的
app.logger.disabled = True),否则每 10 秒打一条日志,撑爆日志盘
Probe 配置参数怎么配才不误杀(livenessProbe vs readinessProbe)
K8s 探针不是越严越好,参数错配比没写探针更危险。重点看 initialDelaySeconds 和 failureThreshold。
立即学习“Python免费学习笔记(深入)”;
-
livenessProbe:建议initialDelaySeconds: 30(给 Python 应用冷启动留足时间),periodSeconds: 10,failureThreshold: 3(连续 3 次失败才重启)。别设timeoutSeconds: 1—— GIL 或 GC 暂停可能让单次响应卡住 2 秒 -
readinessProbe才该检查 DB/Redis:它只控制流量接入,不杀容器。可设更激进的参数,比如periodSeconds: 5,failureThreshold: 2 - 两个 probe 的 endpoint **必须不同**(如
/healthzvs/readyz),否则 readiness 失败会间接导致 liveness 也失败 - 别信 “用 exec 探针执行 python -c 'import sys; print(1)’” —— 容器里未必装了 python,且 exec 开销远高于 HTTP
真正的难点不在写那几行代码,而在于想清楚:这个探针到底要回答哪个问题——是“Python 进程还在跑吗”,还是“我能安全地把用户请求发过来吗”。混淆这两者,后面所有配置都会偏航。


















