You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Kubernetes与Gunicorn结合场景下的健康检查问题求助

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

火山引擎 最新活动