在面临高流量冲击、服务过载、资源耗尽或恶意攻击的情况下,通过对入口网关的特定路由配置全局限流,可以实现对流量的精准控制,从而保护后端服务的稳定性,降低成本并提升用户体验。
前提条件
已添加Kubernetes托管版集群到ASM实例,且ASM实例为1.18.0.131及以上。具体操作,请参见添加集群到ASM实例。
已为Kubernetes集群中的default命名空间开启自动注入。具体操作,请参见启用自动注入。
已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关。
准备工作
一、部署限流服务
使用以下内容,创建ratelimit-svc.yaml。
在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中创建限流服务和限流服务依赖的Redis服务。
关于如何通过kubectl连接集群,请参考获取集群KubeConfig并通过kubectl工具连接集群。
kubectl apply -f ratelimit-svc.yaml
二、部署bookinfo示例应用
从Github的Istio项目库中下载bookinfo应用的YAML文件bookinfo.yaml。
在ACK集群对应的KubeConfig环境下,执行以下命令,将bookinfo应用部署到ASM实例的集群中。
kubectl apply -f bookinfo.yaml
使用以下内容,创建bookinfo-gateway.yaml。
在ASM实例对应的KubeConfig环境下,执行以下命令,创建入口网关ingressgateway对bookinfo应用的路由规则。
该路由规则的名称
为productpage-route-name1
,匹配请求域名bf2.example.com
。关于如何通过kubectl连接ASM实例,请参考通过控制面kubectl访问Istio资源。kubectl apply -f bookinfo-gateway.yaml
场景一:对入口网关的特定路由配置全局限流
对bf2.example.com:80
这个域名和端口组合下的productpage-route-name1路由配置限流规则。productpage-route-name1是准备工作中创建的虚拟服务booinfo中的一条路由项,匹配了请求的/productpage
、/static
、/login
、/logout
等路径并将匹配的请求转发到productpage服务。配置限流规则后,发往上述路径的请求都将收到流量速率的限制。
使用以下内容,创建global-ratelimit-gw.yaml。
部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明。
字段
说明
workloadSelector
用于匹配限流生效的工作负载。本示例全局限流生效于ingressgateway入口网关,设置为
istio: ingressgateway
。isGateway
是否作用于网关。本示例中设定为
true
。rateLimitService
限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
需要生效的限流配置参数。其中
unit
表示限流检测的时间单位,quota
表示单位时间内允许的请求总量。本示例配置
unit
为MINUTE
、quota
为1
,表示匹配路由上每分钟只能发送一个请求,超出的请求将被限流。vhost
限流匹配的域名和路由项配置。其中
name
、port
需要分别和应用于网关的虚拟服务中的域名以及入口网关端口匹配,route.name_match
中填写的路由名称需要与虚拟服务中路由项的名称一致。在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于网关上
productpage-route-name1
路由项的全局限流规则。kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
将上一步预期输出的ASMGlobalRateLimiter资源中
status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。
kubectl apply -f ratelimit-config.yaml
执行以下命令,连续访问bookinfo应用两次。
请将
<ASM网关IP>
替换为实际网关IP。关于如何获取网关IP,请参见获取入口网关地址。curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
第二次访问bookinfo应用的预期输出如下:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 48 < date: Thu, 26 Oct 2023 04:10:11 GMT < server: istio-envoy < content-length: 0 < * Connection #0 to host 116.62.XXX.XXX left intact
在全局限流配置中,限制1分钟之内只能有一次访问bookinfo应用的请求。当连续两次访问bookinfo应用时,可以看到第一条请求成功,第二条请求被限流,表明对入口网关的特定路由配置全局限流成功。
场景二:对入口网关的域名和端口组合配置全局限流
对bf2.example.com:80
这个域名和端口组合配置全局限流规则。配置限流规则后,发往该域名和端口组合的请求都将受到流量速率的限制。
使用以下内容,创建global-ratelimit-gw.yaml。
部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明。
字段
说明
workloadSelector
用于匹配限流生效的工作负载。本示例全局限流生效于ingressgateway入口网关,设置为
istio: ingressgateway
。isGateway
是否作用于网关。本示例中设定为
true
。rateLimitService
限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
需要生效的限流配置参数。其中
unit
表示限流检测的时间单位,quota
表示单位时间内允许的请求总量。本示例配置
unit
为MINUTE
、quota
为1
,表示匹配路由上每分钟只能发送一个请求,超出的请求将被限流。vhost
限流匹配的域名和路由项配置。其中
name
、port
需要分别和应用于网关的虚拟服务中的域名以及入口网关端口匹配。在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于网关上
productpage-route-name1
路由项的全局限流规则。kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
将上一步预期输出的ASMGlobalRateLimiter资源中
status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。
kubectl apply -f ratelimit-config.yaml
执行以下命令,连续访问bookinfo应用两次。
请将
<ASM网关IP>
替换为实际网关IP。关于如何获取网关IP,请参见获取入口网关地址。curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
第二次访问bookinfo应用的预期输出如下:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 48 < date: Thu, 26 Oct 2023 04:10:11 GMT < server: istio-envoy < content-length: 0 < * Connection #0 to host 116.62.XXX.XXX left intact
在全局限流配置中,对于
bf2.example.com:80
这一域名端口组合,限制1分钟之内只能有一次请求访问。当连续两次访问该域名端口组合时,可以看到第一条请求成功,第二条请求被限流,表明对入口网关域名端口组合的全局限流配置成功。
场景三:在入口网关特定虚拟服务路由上,针对包含特定请求头和查询参数的请求配置限流规则
此场景需要ASM实例版本为1.19.0及以上。关于升级版本的具体操作,请参见升级ASM实例。
对bf2.example.com:80
这个域名和端口组合下的productpage-route-name1路由配置限流规则,同时指定限流规则只生效在带有ratelimit: "true"
请求头、且请求路径上带有查询参数ratelimit=enabled
的请求上,该路由上的其他请求不受限流规则影响。匹配请求的/productpage
、/static
、/login
、/logout
等路径并将匹配的请求转发到productpage服务。配置限流规则后,发往上述路径的请求都将收到流量速率的限制。
使用以下内容,创建global-ratelimit-gw.yaml。
部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明。
字段
说明
workloadSelector
用于匹配限流生效的工作负载。本示例全局限流生效于ingressgateway入口网关,设置为
istio: ingressgateway
。isGateway
是否作用于网关。本示例中设定为
true
。rateLimitService
限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
在虚拟服务路由上生效的限流配置参数。其中
unit
表示限流检测的时间单位,quota
表示单位时间内允许的请求总量。本示例配置unit
为SECOND
、quota
为100000
,表示匹配路由上每秒允许发送100000个请求。此设定约等于没有配置限流,只希望满足指定条件的请求被限流,其余请求不需要触发限流。vhost
限流匹配的域名和路由项配置。其中
name
、port
需要分别和应用于网关的虚拟服务中的域名以及入口网关端口匹配,route.name_match
中填写的路由名称需要与虚拟服务中路由项的名称一致。limit_overrides
限流阈值覆盖配置。可通过该字段针对特定的请求指定单独的限流阈值。在本示例中:
limit_overrides
中的request_match
字段被设定为精确匹配含有ratelimit: "true"
请求头、且请求路径上带有查询参数ratelimit=enabled
的请求。limit_overrides
中的limit
字段配置unit
为MINUTE
、quota
为1
,表示对于满足request_match
指定的条件的请求,每分钟只允许发送一个。
在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于网关上
productpage-route-name1
路由项的全局限流规则。kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
将上一步预期输出的ASMGlobalRateLimiter资源中
status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。
kubectl apply -f ratelimit-config.yaml
执行以下命令,连续访问bookinfo应用两次。
请将
<ASM网关IP>
替换为实际网关IP。关于如何获取网关IP,请参见获取入口网关地址。curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
第二次访问bookinfo应用的预期输出如下:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 48 < date: Thu, 26 Oct 2023 04:10:11 GMT < server: istio-envoy < content-length: 0 < * Connection #0 to host 116.62.XXX.XXX left intact
在全局限流配置中,限制对于含有
ratelimit: "true"
请求头、且请求路径上带有查询参数ratelimit=enabled
的请求,1分钟之内只能有一次访问bookinfo应用的请求。当携带上述的请求头和请求查询参数连续两次访问bookinfo应用时,可以看到第一条请求成功,第二条请求被限流,表明对入口网关的匹配特定请求的全局限流配置成功。执行以下命令,请求中不携带
ratelimit: "true"
请求头和查询参数ratelimit=enabled
,再次访问bookinfo应用。curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
可以看到bookinfo应用正常访问,没有出现429状态码,说明路由上的其他请求没有受到全局限流影响。
场景四:在入口网关特定虚拟服务路由上,针对特定客户端的IP地址进行限流
对bf2.example.com:80
这个域名和端口组合下的productpage-route-name1虚拟服务路由配置限流规则,同时指定限流规则只生效在来自特定客户端IP地址的请求上,该路由上的其他请求不受限流规则影响。
使用以下内容,创建global-ratelimit-gw.yaml。
部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明。
字段
说明
workloadSelector
用于匹配限流生效的工作负载。本示例全局限流生效于ingressgateway入口网关,设置为
istio: ingressgateway
。isGateway
是否作用于网关。本示例中设定为
true
。rateLimitService
限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:
host: ratelimit.default.svc.cluster.local port: 8081 timeout: seconds: 5
limit
在虚拟服务路由上生效的限流配置参数。其中
unit
表示限流检测的时间单位,quota
表示单位时间内允许的请求总量。本示例配置
unit
为SECOND
、quota
为100000
,表示匹配路由上每秒允许发送100000个请求。此设定约等于没有配置限流,只希望满足指定条件的请求被限流,其余请求不需要触发限流。vhost
限流匹配的域名和路由项配置。其中
name
、port
需要分别和应用于网关的虚拟服务中的域名以及入口网关端口匹配,route.name_match
中填写的路由名称需要与虚拟服务中路由项的名称一致。limit_overrides
限流阈值覆盖配置。可通过该字段针对特定的请求指定单独的限流阈值。在本示例中:
request_match
字段中,通过remote_address.address
匹配请求的客户端源IP,通过remote_addess.v4_prefix_mask_len
匹配客户端源IP的地址范围子网掩码(可选)。limit_overrides
字段中的limit
字段配置unit
为MINUTE
、quota
为1
,表示对于满足request_match
指定的条件的请求,每分钟只允许发送一个。
在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于网关上
productpage-route-name1
路由项的全局限流规则。kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
将上一步预期输出的ASMGlobalRateLimiter资源中
status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。ASMGlobalRateLimiter中
status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。
kubectl apply -f ratelimit-config.yaml
执行以下命令,连续访问bookinfo应用两次。
请将
<ASM网关IP>
替换为实际网关IP。关于如何获取网关IP,请参见获取入口网关地址。curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
第二次访问bookinfo应用的预期输出如下:
< HTTP/1.1 429 Too Many Requests < x-envoy-ratelimited: true < x-ratelimit-limit: 1, 1;w=60 < x-ratelimit-remaining: 0 < x-ratelimit-reset: 48 < date: Thu, 26 Oct 2023 04:10:11 GMT < server: istio-envoy < content-length: 0 < * Connection #0 to host 116.62.XXX.XXX left intact
在全局限流配置中,限制来自特定IP地址(或地址范围)的请求,1分钟之内只能有一次访问bookinfo应用的请求。当使用特定IP地址的客户端访问网关时,可以看到第一条请求成功,第二条请求被限流,表明对入口网关的全局限流配置成功。
执行以下命令,使用不同IP地址的客户端,再次访问bookinfo应用。
curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
可以看到bookinfo应用正常访问,没有出现429状态码,说明路由上的其他请求没有受到全局限流影响。
相关文档
如果您想要使用不依赖限流服务、资源消耗更低的限流方式,可以使用ASM本地限流。具体操作,请参见在ASM中配置本地限流。
如果您需要对注入Sidecar的应用服务的入口流量进行控制和限制时,可以配置全局限流。具体操作,请参见对应用服务入口流量配置全局限流。