首页 > 解决方案 > 为 Nginx Ingress 中的特定位置设置 limit_req

问题描述

我正在尝试为limit_reqKubernetes ingress-nginx 中的特定路径设置速率限制选项,以防止强制身份验证。

我已经limit_req_zone使用 ConfigMap 定义:

http-snippet: |
      limit_req_zone $the_real_ip zone=authentication_ratelimit:10m rate=1r/s;

接下来,我使用注释来添加自定义位置块:

nginx.ingress.kubernetes.io/configuration-snippet: |
  location ~* "^/authenticate$" {
    limit_req zone=authentication_ratelimit nodelay;
    more_set_headers "x-test: matched";
  }

这会产生 nginx.conf:

server {
# - - 8< - -

  location / {
    # - - 8< - -

    location ~* "^/authenticate$" {
      limit_req zone=authentication_ratelimit nodelay;
      more_set_headers "x-test: matched";
    }

    proxy_pass http://upstream_balancer;

    proxy_redirect                          off;
}

结果是/authenticate始终返回 HTTP 503(带有 x-test 标头)。来自入口访问日志的消息:

<ip> - [<ip>] - - [04/Jan/2019:15:22:07 +0000] "POST /authenticate HTTP/2.0" 503 197 "-" "curl/7.54.0" 172 0.000 [-] - - - - 1a63c9825c9795be1378b2547e29992d

proxy_pass我怀疑这可能是因为嵌套位置块和(但这只是一个疯狂的猜测)之间的冲突。

我尝试了哪些其他选择?

问题是为什么自定义位置块以 503 响应?我该如何调试呢?增加 nginx 日志记录级别会提供有关 503 的更多详细信息吗?或更一般的问题:我可以在 ingress-nginx 中注入自定义位置块吗?

标签: nginxkuberneteskubernetes-ingressnginx-ingress

解决方案


这可以通过使用 map 来完成,并且不考虑具有空键值的请求这一事实。

http-snippets: |
  map $uri $with_limit_req {
    default 0;
    "~*^/authenticate$" 1;
  }
  map $with_limit_req $auth_limit_req_key {
    default '';
    '1'     $binary_remote_addr; # the limit key
  }
  limit_req_zone $auth_limit_req_key zone=authentication_ratelimit:10m rate=1r/s;

并使用注释添加自定义位置块:

nginx.ingress.kubernetes.io/configuration-snippet: |
  limit_req zone=authentication_ratelimit nodelay;

或者,如果您使用来自 nginxinc 的入口

nginx.org/location-snippets:
  limit_req zone=authentication_ratelimit nodelay;

在这种情况下,检查请求是否需要在地图级别进行速率限制处理。

我的意见是:最好限制应用程序级别的请求,就像您对入口级别进行速率限制一样,这取决于入口 pod 的数量。


推荐阅读