Kubernetes与Gunicorn结合场景下的健康检查问题求助
哎,这个场景我之前维护高并发FastAPI服务的时候真的踩过一模一样的坑!当时pod动不动就被K8s误重启,排查了好久才摸清楚门路,给你分享几个亲测有效的解决办法:
给Gunicorn配个专门的健康检查“专属worker”
你现在3个worker全用来扛业务请求了,峰值时期连健康检查的请求都挤不进去。那咱们单独搞一个只处理健康检查的轻量进程,比如直接用uvicorn跑你的FastAPI app,但只监听本地的一个端口(比如127.0.0.1:8001),而且这个进程不处理任何业务接口,只保留健康检查的/healthz或者/ready接口。然后把K8s的健康检查目标改成这个本地端口,这样不管业务worker多忙,健康请求都能被这个专属进程秒响应。调优Gunicorn的并发参数
针对异步worker,你可以试试调大--worker-connections参数(默认可能是100),比如设成--worker-connections=1000,让每个worker能同时处理更多并发请求,减少worker被占满的概率。另外把--backlog参数调大,比如--backlog=2048,这样请求等待队列更长,健康检查的请求不至于直接被拒绝。调整K8s健康检查的触发逻辑
别让K8s一两次检测失败就重启pod,太激进了。可以把failureThreshold调大(比如设成5),periodSeconds设成10,给服务一点缓冲时间;同时把timeoutSeconds延长到3-5秒,让健康请求有足够时间等到worker响应。另外建议把liveness和readiness检查分开:readiness检查失败时,K8s只会把pod从服务端点中移除,不会直接重启,等服务恢复后再自动加回来;只有liveness检查连续失败才触发重启,这样能大幅减少误杀。把健康检查接口做极简处理
一定要确保你的健康检查接口没有任何额外逻辑——别查数据库、别调用其他服务、别做任何计算,就直接返回200 OK。比如写个最简单的接口:@app.get("/healthz") async def liveness_check(): return {"status": "alive"}这样接口响应时间毫秒级,哪怕worker只是暂时有空隙,也能快速处理完这个请求。
我当时是结合了第一个和第三个方案,给服务加了个专属的健康检查进程,同时调松了K8s的健康检查阈值,之后就再也没出现过因为健康检查失败被误重启的情况了。
备注:内容来源于stack exchange,提问作者Saw




