【问题标题】:How to implement global rate limiting with Kubernetes NGINX ingress controller如何使用 Kubernetes NGINX 入口控制器实现全局速率限制
【发布时间】:2021-10-14 13:17:22
【问题描述】:

我希望对 Azure 上的生产部署实施全局速率限制,以确保我的应用程序不会由于无法控制的流量而变得不稳定(我不是在谈论 DDoS,而是大量的合法流量)。 Azure Web 应用程序防火墙仅支持基于 IP 的速率限制。

我在不增加系统中的跳数的情况下寻找替代方案。我发现的唯一解决方案是在 NGINX 中使用 limit_req_zone 指令。这并没有给出实际的全局速率限制,但它可用于对每个 pod 施加全局速率限制。以下 configmap 被挂载到 Kubernetes NGINX 入口控制器来实现这一点。

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-ingress-ingress-nginx-controller
  namespace: ingress-basic
data:
  http-snippet : |
     limit_req_zone test zone=static_string_rps:5m rate=10r/m ;
  location-snippet: |
          limit_req zone=static_string_rps burst=20 nodelay;
          limit_req_status 429;

static_string_rps 是一个常量字符串,因此所有请求都计入单个关键字下,该关键字提供每个 pod 的全局速率限制。

这似乎是一种实现全局速率限制的 hacky 方法。有没有更好的选择,Kubernetes NGINX 入口控制器是否正式支持这种方法?(他们的文档说他们支持为高级配置安装 configmap,但没有提到使用这种方法而不使用额外的 memcached pod 来同步计数器之间的豆荚)

https://www.nginx.com/blog/rate-limiting-nginx/#:~:text=One%20of%20the%20most%20useful,on%20a%20log%E2%80%91in%20formhttps://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#global-rate-limiting

【问题讨论】:

  • 我怀疑除了 NGINX 入口文档中提供的方法之外还有其他方法。如果要对合法流量实施速率限制,则需要存储一些信息以在流量超过给定阈值时拒绝流量。它可以是 IP、用户信息或其他内容。所以你必须使用一些存储解决方案,比如 Memcache。甚至不同的入口解决方案也使用这些方法。
  • 是的。我同意你的看法。您认为上述方法是否推荐用于生产?这可以创建每个 pod 全局速率限制
  • 我没有使用这个的真实例子,但我认为它应该是生产就绪的。您可以在 k8 松弛通道中询问正在使用的任何生产实现。
  • 谢谢@NitishkumarSingh。我试试看
  • 是的。当然。我确实有一篇博文。给我一些时间来总结一下答案

标签: nginx kubernetes kubernetes-ingress nginx-ingress rate-limiting


【解决方案1】:

根据 Kubernetes slack 社区的说法,任何需要全球协调以限制速率的东西都可能会出现严重的性能瓶颈,并会产生单点故障。因此,即使我们确实使用外部解决方案也会导致瓶颈,因此不建议这样做。(但是文档中没有提到)

根据他们的说法,使用limit_req_zone 是一种有效的方法,它得到了 Kubernetes NGINX Ingress 控制器社区的正式支持,这意味着它已经准备好生产。

如果你想应用全局速率限制,我建议你使用这个模块(虽然它不是精确的全局速率限制)。如果您的集群中有多个 Ingress,您可以使用以下方法对每个 Ingress 应用全局速率限制。

在您的 K8 NGINX Ingress 控制器所在的命名空间中部署以下 ConfigMap。这将使用键 static_string_ingress1static_string_ingress2 创建 2 个计数器。

NGINX 配置图

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-ingress-ingress-nginx-controller
  namespace: ingress-basic
data:
  http-snippet : |
     limit_req_zone test zone=static_string_ingress1:5m rate=10r/m ;
     limit_req_zone test zone=static_string_ingress2:5m rate=30r/m ;

入口资源 1

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress-1
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/affinity: cookie
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/configuration-snippet: |
      limit_req zone=static_string_ingress1 burst=5 nodelay;                                                   
      limit_req_status 429;  
spec:
  tls:
  - hosts:
    - test.com
  rules:
  - host: test.com
    http:
      paths:
      - path: /
        backend:
          serviceName: test-service
          servicePort: 9443

类似地,您可以通过将以下配置 sn-p 添加到入口资源 2 注释来为入口资源 2 添加单独的限制。

入口资源 2

annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      limit_req zone=static_string_ingress2 burst=20 nodelay;                                                   
      limit_req_status 429;  

请注意,键 static_string_ingress1static_string_ingress2 是静态字符串,所有通过相关入口的请求都将使用其中一个键进行计数,这将产生全局速率限制效果。

但是,这些计数由每个 NGINX Ingress 控制器 pod 单独维护。因此实际的速率限制为defined limit * No. of NGINX pods

此外,我在使用 limit_req_zone 模块计数时监控了 pod 内存和 CPU 使用情况,它并没有显着增加资源使用量。

有关此主题的更多信息,请参阅我写的这篇博文:https://faun.pub/global-rate-limiting-with-kubernetes-nginx-ingress-controller-fb0453447d65

请注意,此解释适用于 Kubernetes NGINX 入口控制器(https://github.com/kubernetes/ingress-nginx),不要与 Kubernetes 的 NGINX 控制器(https://github.com/nginxinc/kubernetes-ingress) 混淆

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-29
    • 2021-10-20
    • 2023-02-09
    • 2021-12-12
    • 2018-10-29
    • 1970-01-01
    • 2018-09-29
    • 2020-04-09
    相关资源
    最近更新 更多