如何避免K8s服务的同一Pod收到多个并行请求?
K8s 单并发TensorFlow服务负载均衡优化方案
方案1:调整kube-proxy配置启用IPVS最少连接调度(集群层面改造成本最低)
K8s 默认 kube-proxy 的 iptables 模式仅支持轮询策略,无法感知Pod的忙闲状态。你可以将kube-proxy切换为IPVS模式,配置lc(最少活跃连接数)调度算法:
- 修改kube-proxy的ConfigMap
kube-system/kube-proxy,将mode字段设为ipvs,ipvs.scheduler字段设为lc - 重启所有kube-proxy Pod后配置生效
IPVS的lc策略会自动将新请求转发给当前活跃连接数最少的Pod,你的场景下每个Pod最多1个活跃连接,相当于只要存在空闲Pod,新请求就不会被发给正在处理请求的Pod,完全匹配你的需求。如果使用云厂商托管K8s,多数支持直接通过Service注解配置负载均衡策略,无需修改集群全局配置。
方案2:通过七层负载均衡配置单服务粒度的最少连接策略
如果不想修改集群全局的kube-proxy配置,可以通过七层Ingress或者服务网格实现针对单个服务的调度策略调整:
- 若使用Nginx Ingress,给对应Ingress资源添加注解:
nginx.ingress.kubernetes.io/load-balance: least_conn即可生效 - 若使用Istio等服务网格,修改对应服务的
DestinationRule,将负载均衡策略设为LEAST_CONN即可
方案3:应用侧兜底优化
如果暂时无法调整上层负载均衡策略,可以先调整Gunicorn配置做兜底:
- 将Gunicorn的
backlog参数设为1,超过1个等待请求会直接被拒绝,上游负载均衡收到拒绝后会自动重试转发到其他Pod,配合默认轮询策略也能大幅降低排队概率 - 注意要配合配置上游的最大重试次数,避免请求量过高时出现重试雪崩
你之前考虑的就绪探针方案不建议使用:就绪探针的最低检测周期通常在百毫秒级别,不仅会给kubelet和apiserver带来额外的高频检测压力,还存在检测时间差,很容易出现Pod已经开始处理请求但探针还没检测到、仍然有新请求转发过来的问题,完全不适合这种高动态的忙闲状态切换场景。
内容的提问来源于stack exchange,提问作者Tobias Hermann
相关产品推荐
相关产品推荐

