在 kubernetes 中,ingress 负责转发、融断和限流。

我们以 Nginx ingress 为例,讨论一下这方面的问题。

一、Nginx ingress黑白名单

这个很简单了,丢进黑名单或者白名单,在入口前拦一刀。

我们只要在 annotations 声明即可:

image-20211129102114725

apiVersion: networking.k8s.io/v1beta1 
kind: Ingress 
metadata: 
name: www-com-ingress 
annotations: 
   kubernetes.io/ingress.class: nginx 
   nginx.ingress.kubernetes.io/ssl-redirect: "true" 
   nginx.ingress.kubernetes.io/block-cidrs: a.b.c.d/32 
   #nginx.ingress.kubernetes.io/whitelist-source-range: a.b.c.d/32 
spec: 
tls: 
- hosts: 
   - www.huabbao.com 
   secretName: www-huabbao-com-cert 
rules: 
- host: www.huabbao.com 
   http: 
     paths: 
     - path: / 
       backend: 
         serviceName: nginx-svc 

注意,多个ip的话,之间用逗号隔开(该值是逗号分隔的CIDR列表) :

nginx.ingress.kubernetes.io/whitelist-source-range: '58.246.36.130,180.167.74.98,114.85.176.38’ 

二、Nginx ingress限速

限速这个问题比较复杂,首先我们需要考虑到用户体验,如果很鲁棒性的强制限制客户端流量是10KB,那么如果一开始的加载页面如果较大,客户直接就离场了。所以首先要考虑要有初始字节量,这个量需要能让客户顺畅的打开首页。然后我们再设定请求速率,再考虑单个IP地址的并发连接量(并发量×速率=客户端实际速率),第四个再考虑每分钟或每秒的最大请求数。

以下注释定义按顺序排列,可以设置单个客户端IP地址打开的连接的限制,可用于缓解DDoS攻击。

  • 一、nginx.ingress.kubernetes.io/limit-rate-after:设置初始字节量,在此之后,进一步传输将受到limit-rate速率限制。
  • 二、nginx.ingress.kubernetes.io/limit-rate:每秒接受的请求速率(每秒字节数)。
  • 三、nginx.ingress.kubernetes.io/limit-connections:来自单个IP地址的并发连接数。(可以建立最大连接数)
  • 四、nginx.ingress.kubernetes.io/limit-rps:每秒可从给定IP接受的连接数。(每个源 IP 每个源 IP 每秒最大请求次数)
  • 五、nginx.ingress.kubernetes.io/limit-rpm:每分钟可从给定IP接受的连接数。(每个源 IP 每分钟最大请求次数)

可以指定 nginx.ingress.kubernetes.io/limit-whitelist 设置从速率限制中排除的客户端IP源范围,该值也是逗号分隔的CIDR列表。

如果在单个Ingress规则中设置了多个注释 limit-rpm,则 limit-rps 优先。

apiVersion: extensions/v1beta1 
kind: Ingress 
metadata: 
  name: my-ingress 
  annotations: 
    nginx.ingress.kubernetes.io/limit-rate-after: 500k
    nginx.ingress.kubernetes.io/limit-rate: 50k
    nginx.ingress.kubernetes.io/limit-connections: "3" 
    nginx.ingress.kubernetes.io/limit-rps: "1" 
    nginx.ingress.kubernetes.io/limit-rpm: "3" 
    nginx.ingress.kubernetes.io/limit-whitelist: "192.168.7.0/24" 
spec: 
  rules: 
  - host: my.test.com 
    http: 
      paths:  
      - path: / 
        backend: 
          serviceName: nginx 
          servicePort: 80 

解释一下:

首先设置了初始字节量是500k

然后初始字节量用完之后,限制用户传输速率是50k/s

随后并发连接设置为3,那么客户端如果同时打开3个连接,总速率是 50k×3=150k/s

第四步进一步设置了每秒最大请求次数是1,下面又设置每分钟最大请求次数是3。

第五步设置了 192.168.7.0/24 这段不受限速的影响

设置好以后压测试一下:

超限返回的代码是503

wrk -c 3 -t 3 -d 10 http://m.test.com --latency 


curl -v -H "Host: m.test.com" http://m.test.com
< HTTP/1.1 503 Service Temporarily Unavailable 
< Date: Wed, 28 Jul 2021 04:32:03 GMT 
< Content-Type: text/html 
< Content-Length: 190 
< Connection: keep-alive 
HTTP/1.1 503 Service Temporarily Unavailable