ingress-nginx如何仅在自定义健康检查URL正常时执行限流
ingress-nginx 自定义健康检查通过后才启用限流的实现方案
ingress-nginx 没有提供开箱即用的对应配置项,但可以通过组合内置的Nginx原生能力实现,不需要修改控制器源码,目前生产可用的方案有两种:
方案一:Nginx原生配置片段实现(性能最优,推荐)
核心逻辑是先通过主动健康检查探测自定义健康检查接口的状态,用变量标记后端健康状态,再将限流规则的触发条件和该状态变量绑定,仅当健康状态标记为正常时才执行限流逻辑。
- 首先配置全局Nginx片段(可以通过ingress-nginx ConfigMap的
http-snippet键添加,若仅需对单个服务生效,可挪到对应Ingress的server-snippet注解中):
# 配置集群内DNS解析地址,替换为你集群实际的DNS服务地址 resolver kube-dns.kube-system.svc.cluster.local valid=10s; # 定义指向你业务后端的upstream,用于主动健康检查 upstream biz_backend { server 你的业务服务名.业务命名空间.svc.cluster.local:服务端口; keepalive 32; } # 定义限流规则的启用开关:仅当后端健康时才绑定限流标识 map $backend_healthy $limit_binder { default ""; 1 $binary_remote_addr; } # 初始化限流共享内存,速率、内存大小根据业务需求调整 limit_req_zone $limit_binder zone=biz_per_ip_limit:20m rate=50r/s; # 配置主动健康检查规则:每5秒探测一次自定义健康路径,连续2次成功判定为健康,连续1次失败判定为异常 match health_status_ok { status 200-399; } health_check interval=5s fails=1 passes=2 uri=/你的自定义健康检查路径 match=health_status_ok;
- 在对应业务Ingress的注解中添加configuration片段,绑定限流逻辑:
annotations: nginx.ingress.kubernetes.io/configuration-snippet: | set $backend_healthy 0; # 主动健康检查返回正常状态码时,标记后端为健康 if ($upstream_health_check_status ~ "^2[0-9]{2}$") { set $backend_healthy 1; } # 仅健康状态下生效限流,burst值根据业务容忍的突发流量调整 limit_req zone=biz_per_ip_limit burst=100 nodelay; limit_req_status 429;
注意事项
- 健康检查间隔建议不小于3秒,避免给后端造成额外的探测压力
- 多副本场景下可在
health_check指令后添加threshold=N参数,指定至少N个副本健康检查通过才判定为服务正常、开启限流 - 不要直接使用ingress-nginx自带的
limit-rps/limit-connections注解,这类注解是全局强制生效,没有预留状态判断的入口
方案二:外部辅助服务判定(适合无ConfigMap修改权限的场景)
如果没有权限修改ingress-nginx全局配置,可以用轻量辅助服务实现状态判定:
- 部署一个内存占用极低的辅助服务(可以用openresty写几十行代码实现,或者直接用sidecar容器),定期轮询业务服务的自定义健康检查接口,在内存中维护健康状态标记
- 给业务Ingress配置外部鉴权规则,将鉴权地址指向该辅助服务:健康状态正常时辅助服务返回200状态码,ingress-nginx正常执行配置好的限流规则;健康状态异常时辅助服务返回特殊状态码,通过ingress的错误页配置跳过限流逻辑直接转发请求
- 该方案的缺点是每次请求会多一次本地网络跳转,性能比原生配置方案低8%~15%,适合权限受限的测试、小流量集群使用
内容的提问来源于stack exchange,提问作者Sam Alex
相关产品推荐
相关产品推荐

