为Nginx Ingress中的特定位置设置limit_req

时间:2019-01-04 16:07:55

标签: nginx kubernetes kubernetes-ingress nginx-ingress

我正在尝试为Kubernetes ingress-nginx中的特定路径设置速率限制选项limit_req,以防止强行认证。

我已经使用ConfigMap定义了limit_req_zone

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之间的冲突引起的(但这只是一个疯狂的猜测)。

我还尝试了哪些其他选择?

  • 使用server-snippet注释代替configuration-snippet-/authenticate返回404,因为未配置proxy_pass
  • 使用nginx.ingress.kubernetes.io/limit-rpm注释-强制对整个应用程序进行速率限制,这不是我想要的。

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

2 个答案:

答案 0 :(得分:2)

这可以通过使用地图以及Requests with an empty key value are not accounted.

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;

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

我的观点是:最好将应用程序级别的请求限制为好像您对入口级别进行了速率限制一样,这取决于入口容器的数量。

答案 1 :(得分:0)

听起来可能很有趣,但是您可以尝试仅创建如下注释:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-with-annotations
  annotations:
    nginx.org/server-snippets: |
      limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
      location ~* "^/authenticate$" {
         limit_req zone=mylimit burst=10 nodelay;
         more_set_headers "x-test: matched";
      }

因为,看起来您好像忘记了limit_req_zone的定义,才开始在指令位置中使用它。我使用了有关limit_req

的官方文档