在面临高流量冲击、服务过载、资源耗尽或恶意攻击的情况下,通过对入口网关的特定路由配置全局限流,可以实现对流量的精准控制,从而保护后端服务的稳定性,降低成本并提升用户体验。
前提条件
已添加Kubernetes托管版集群到ASM实例,且ASM实例版本为1.18.0.131及以上。具体操作,请参见添加集群到ASM实例。
已为Kubernetes集群中的default
命名空间开启自动注入。具体操作,请参见启用自动注入。
已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关。
准备工作
部署限流服务
使用以下内容,创建ratelimit-svc.yaml。
展开查看ratelimit-svc.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: redis
---
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app: redis
spec:
ports:
- name: redis
port: 6379
selector:
app: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
sidecar.istio.io/inject: "false"
spec:
containers:
- image: registry-cn-hangzhou.ack.aliyuncs.com/dev/redis:alpine
imagePullPolicy: Always
name: redis
ports:
- name: redis
containerPort: 6379
restartPolicy: Always
serviceAccountName: redis
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
{}
---
apiVersion: v1
kind: Service
metadata:
name: ratelimit
labels:
app: ratelimit
spec:
ports:
- name: http-port
port: 8080
targetPort: 8080
protocol: TCP
- name: grpc-port
port: 8081
targetPort: 8081
protocol: TCP
- name: http-debug
port: 6070
targetPort: 6070
protocol: TCP
selector:
app: ratelimit
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratelimit
spec:
replicas: 1
selector:
matchLabels:
app: ratelimit
strategy:
type: Recreate
template:
metadata:
labels:
app: ratelimit
sidecar.istio.io/inject: "false"
spec:
containers:
# Latest image from https://hub.docker.com/r/envoyproxy/ratelimit/tags
- image: registry-cn-hangzhou.ack.aliyuncs.com/dev/envoyproxy/ratelimit:e059638d
imagePullPolicy: Always
name: ratelimit
command: ["/bin/ratelimit"]
env:
- name: LOG_LEVEL
value: debug
- name: REDIS_SOCKET_TYPE
value: tcp
- name: REDIS_URL
value: redis.default.svc.cluster.local:6379
- name: USE_STATSD
value: "false"
- name: RUNTIME_ROOT
value: /data
- name: RUNTIME_SUBDIRECTORY
value: ratelimit
- name: RUNTIME_WATCH_ROOT
value: "false"
- name: RUNTIME_IGNOREDOTFILES
value: "true"
ports:
- containerPort: 8080
- containerPort: 8081
- containerPort: 6070
volumeMounts:
- name: config-volume
# $RUNTIME_ROOT/$RUNTIME_SUBDIRECTORY/$RUNTIME_APPDIRECTORY/config.yaml
mountPath: /data/ratelimit/config
volumes:
- name: config-volume
configMap:
name: ratelimit-config
在ACK集群对应的kubeconfig环境下,执行以下命令,在集群中创建限流服务和限流服务依赖的Redis服务。
关于如何通过kubectl连接集群,请参考获取集群kubeconfig并通过kubectl工具连接集群。
kubectl apply -f ratelimit-svc.yaml
部署bookinfo示例应用
使用以下内容创建bookinfo.yaml。
展开查看YAML内容
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
service: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-details
labels:
account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
app: details
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: details
version: v1
template:
metadata:
labels:
app: details
version: v1
spec:
serviceAccountName: bookinfo-details
containers:
- name: details
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-details-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
app: ratings
service: ratings
spec:
ports:
- port: 9080
name: http
selector:
app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-ratings
labels:
account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratings-v1
labels:
app: ratings
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: ratings
version: v1
template:
metadata:
labels:
app: ratings
version: v1
spec:
serviceAccountName: bookinfo-ratings
containers:
- name: ratings
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-ratings-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
app: reviews
service: reviews
spec:
ports:
- port: 9080
name: http
selector:
app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
labels:
account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
app: reviews
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v1
template:
metadata:
labels:
app: reviews
version: v1
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-reviews-v1:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v2
labels:
app: reviews
version: v2
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v2
template:
metadata:
labels:
app: reviews
version: v2
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-reviews-v2:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v3
labels:
app: reviews
version: v3
spec:
replicas: 1
selector:
matchLabels:
app: reviews
version: v3
template:
metadata:
labels:
app: reviews
version: v3
spec:
serviceAccountName: bookinfo-reviews
containers:
- name: reviews
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-reviews-v3:1.20.1
imagePullPolicy: IfNotPresent
env:
- name: LOG_DIR
value: "/tmp/logs"
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
- name: wlp-output
mountPath: /opt/ibm/wlp/output
volumes:
- name: wlp-output
emptyDir: {}
- name: tmp
emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
labels:
account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
app: productpage
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: productpage
version: v1
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9080"
prometheus.io/path: "/metrics"
labels:
app: productpage
version: v1
spec:
serviceAccountName: bookinfo-productpage
containers:
- name: productpage
image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/examples-bookinfo-productpage-v1:1.20.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
---
在ACK集群对应的kubeconfig环境下,执行以下命令,将bookinfo应用部署到ASM实例的集群中。
kubectl apply -f bookinfo.yaml
使用以下内容,创建bookinfo-gateway.yaml。
展开查看bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: bookinfo-gateway
namespace: default
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- bf2.example.com
port:
name: http
number: 80
protocol: http
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: bookinfo
namespace: default
spec:
gateways:
- bookinfo-gateway
hosts:
- bf2.example.com
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
name: productpage-route-name1
route:
- destination:
host: productpage
port:
number: 9080
在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。
展开查看global-ratelimit-gw.yaml
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
rateLimitService: # 准备工作中部署的限流服务的配置。
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
isGateway: true
configs:
- name: productpage
limit:
unit: MINUTE
quota: 1
match:
vhost:
name: bf2.example.com # 该名称需要和VirtualService下的域名一致。
port: 80 # 该端口号需要和ASM网关端口匹配。
route:
name_match: productpage-route-name1 # 该名称需要和VirtualService下的路由规则一致。
部分字段说明如下。关于字段的更多信息,请参见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
展开查看预期输出
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
configs:
- limit:
quota: 1
unit: MINUTE
match:
vhost:
name: bf2.example.com
port: 80
route:
name_match: productpage-route-name1
name: productpage
isGateway: true
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
workloadSelector:
labels:
app: istio-ingressgateway
status:
config.yaml: |
descriptors:
- key: generic_key
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[597770312]
domain: ratelimit.default.svc.cluster.local
message: ok
status: successful
将上一步预期输出的ASMGlobalRateLimiter资源中status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。
ASMGlobalRateLimiter中status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。
展开查看ratelimit-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
descriptors:
- key: generic_key
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[597770312]
domain: ratelimit.default.svc.cluster.local
在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。
展开查看global-ratelimit-gw.yaml
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
rateLimitService: # 准备工作中部署的限流服务的配置。
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
isGateway: true
configs:
- name: productpage
limit:
unit: MINUTE
quota: 1
match:
vhost:
name: bf2.example.com # 该名称需要和VirtualService下的域名一致。
port: 80 # 该端口号需要和ASM网关端口匹配。
部分字段说明如下。关于字段的更多信息,请参见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
展开查看预期输出
apiVersion: istio.alibabacloud.com/v1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
configs:
- limit:
quota: 1
unit: MINUTE
match:
vhost:
name: bf2.example.com
port: 80
name: productpage
isGateway: true
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
workloadSelector:
labels:
istio: ingressgateway
status:
config.yaml: |
descriptors:
- key: generic_key
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[2100900480]
domain: ratelimit.default.svc.cluster.local
message: ok
status: successful
将上一步预期输出的ASMGlobalRateLimiter资源中status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。
ASMGlobalRateLimiter中status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。
展开查看ratelimit-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
descriptors:
- key: generic_key
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[2100900480]
domain: ratelimit.default.svc.cluster.local
在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。
展开查看global-ratelimit-gw.yaml
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
workloadSelector:
labels:
app: istio-ingressgateway
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
isGateway: true
configs:
- name: productpage
limit:
unit: SECOND
quota: 100000
match:
vhost:
name: bf2.example.com
port: 80
route:
name_match: productpage-route-name1 # 该名称需要和virtualservice下的route name一致。
limit_overrides:
- request_match:
header_match:
- name: ratelimit
exact_match: "true"
query_match:
- name: ratelimit
exact_match: "enabled"
limit:
unit: MINUTE
quota: 1
部分字段说明如下。关于字段的更多信息,请参见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
| 限流阈值覆盖配置。可通过该字段针对特定的请求指定单独的限流阈值。在本示例中: |
在ASM实例对应的kubeconfig环境下,执行以下命令,创建生效于网关上productpage-route-name1
路由项的全局限流规则。
kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
展开查看预期输出
apiVersion: istio.alibabacloud.com/v1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
configs:
- limit:
quota: 100000
unit: SECOND
limit_overrides:
- limit:
quota: 1
unit: MINUTE
request_match:
header_match:
- exact_match: "true"
name: ratelimit
query_match:
- exact_match: enabled
name: ratelimit
match:
vhost:
name: bf2.example.com
port: 80
route:
name_match: productpage-route-name1
name: productpage
isGateway: true
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
workloadSelector:
labels:
app: istio-ingressgateway
status:
config.yaml: |
descriptors:
- descriptors:
- descriptors:
- key: query_match
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[1102463266]
key: header_match
value: RateLimit[global-test.istio-system]-Id[1102463266]
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[1102463266]
domain: ratelimit.default.svc.cluster.local
message: ok
status: successful
将上一步预期输出的ASMGlobalRateLimiter资源中status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。
ASMGlobalRateLimiter中status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。
展开查看ratelimit-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
descriptors:
- descriptors:
- descriptors:
- key: query_match
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: RateLimit[global-test.istio-system]-Id[1102463266]
key: header_match
value: RateLimit[global-test.istio-system]-Id[1102463266]
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[1102463266]
domain: ratelimit.default.svc.cluster.local
在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地址进行限流
说明 此场景需要ASM实例版本为1.19.0及以上。关于升级版本的具体操作,请参见升级ASM实例。
要在ASM入口网关上配置针对特定客户端IP地址进行限流,需要首先保证ASM入口网关的外部流量策略设定为Local。关于创建入口网关的具体操作和配置项说明,请参见创建入口网关。
您可以在网关的访问日志中,通过downstream_remote_address
字段获取发往网关的请求的客户端IP地址。在此示例中,请根据您需要限流的实际客户端IP地址进行配置。
对bf2.example.com:80
这个域名和端口组合下的productpage-route-name1虚拟服务路由配置限流规则,同时指定限流规则只生效在来自特定客户端IP地址的请求上,该路由上的其他请求不受限流规则影响。
使用以下内容,创建global-ratelimit-gw.yaml。
展开查看global-ratelimit-gw.yaml
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
workloadSelector:
labels:
app: istio-ingressgateway
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
isGateway: true
configs:
- name: productpage
limit:
unit: SECOND
quota: 100000
match:
vhost:
name: bf2.example.com
port: 80
route:
name_match: productpage-route-name1 # 该名称需要和virtualservice下的route name一致。
limit_overrides:
- request_match:
remote_address:
address: xxx.xxx.xxx.xxx #客户端IP地址。
v4_prefix_mask_len: xx #客户端IP范围子网掩码。
limit:
unit: MINUTE
quota: 1
部分字段说明如下。关于字段的更多信息,请参见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
| 限流阈值覆盖配置。可通过该字段针对特定的请求指定单独的限流阈值。在本示例中: |
在ASM实例对应的kubeconfig环境下,执行以下命令,创建生效于网关上productpage-route-name1
路由项的全局限流规则。
kubectl apply -f global-ratelimit-gw.yaml
执行以下命令,获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml
展开查看预期输出
apiVersion: istio.alibabacloud.com/v1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
configs:
- limit:
quota: 100000
unit: SECOND
limit_overrides:
- limit:
quota: 1
unit: MINUTE
request_match:
remote_address:
address: 106.11.XX.XX
v4_prefix_mask_len: 24
match:
vhost:
name: bf2.example.com
port: 80
route:
name_match: productpage-route-name1
name: productpage
isGateway: true
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
workloadSelector:
labels:
app: istio-ingressgateway
status:
config.yaml: |
descriptors:
- descriptors:
- key: masked_remote_address
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: xxxxxx
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[1102463266]
domain: ratelimit.default.svc.cluster.local
message: ok
status: successful
将上一步预期输出的ASMGlobalRateLimiter资源中status
字段的config.yaml
内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。
ASMGlobalRateLimiter中status
字段下的config.yaml
字段中的字符串内容,需原样粘贴至ConfigMap中data
中的同名config.yaml
字段中。
展开查看ratelimit-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
descriptors:
- descriptors:
- key: masked_remote_address
rate_limit:
requests_per_unit: 1
unit: MINUTE
value: xxxxxx
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[1102463266]
domain: ratelimit.default.svc.cluster.local
在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状态码,说明路由上的其他请求没有受到全局限流影响。
场景五:在入口网关特定虚拟服务路由上,针对不同的客户端IP地址分别限流
说明 本场景需要ASM实例版本为1.25.0及以上。关于升级版本的具体操作,请参见升级ASM实例。
本场景需要保证ASM入口网关的外部流量策略设定为Local
。关于创建入口网关的具体操作和配置项说明,请参见创建入口网关。
您可以在网关的访问日志中,通过downstream_remote_address
字段获取发往网关的请求的客户端IP地址。在此示例中,请根据您需要限流的实际客户端IP地址进行配置。
本场景将对bf2.example.com:80
这个域名和端口组合下的productpage-route-name1虚拟服务路由配置限流规则,指定限流规则对每个不同的客户端IP地址分别进行限流,每个客户端IP每分钟只能请求一次。
创建global-ratelimit-gw.yaml。
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMGlobalRateLimiter
metadata:
name: global-test
namespace: istio-system
spec:
workloadSelector:
labels:
app: istio-ingressgateway
rateLimitService:
host: ratelimit.default.svc.cluster.local
port: 8081
timeout:
seconds: 5
isGateway: true
configs:
- name: productpage
limit:
unit: SECOND
quota: 100000
target_services:
- name: bookinfo
namespace: default
kind: VirtualService
port: 80
section_name: productpage-route-name1
limit_overrides:
- request_match:
remote_address:
distinct: true # 指定针对客户端IP地址分别进行限流
limit:
unit: MINUTE
quota: 1
部分字段说明如下。关于字段的更多信息,请参见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个请求。此设定约等于没有配置限流,只希望满足指定条件的请求被限流,其余请求不需要触发限流。 |
limit_overrides
| 限流阈值覆盖配置。可通过该字段针对特定的请求指定单独的限流阈值。在本示例中: |
target_services
| 限流项匹配的虚拟服务路由配置。其中: kind 指定了限流规则生效目标为虚拟服务路由。
namespace 和name 指定了虚拟服务的命名空间和名称。
port 指定了限流规则仅在80端口的流量路由上生效。
section_name 指定了限流规则在虚拟服务的名为productpage-route-name1 的路由项上生效。
|
部署全局限流规则。
kubectl apply -f global-ratelimit-gw.yaml
获取调谐完成的全局限流规则配置内容。
kubectl get asmglobalratelimiter global-test -n istio-system -o yaml |grep status: -A 50
预期输出:
status:
config.yaml: |
descriptors:
- descriptors:
- key: remote_address
rate_limit:
requests_per_unit: 1
unit: MINUTE
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[537612397]
domain: ratelimit.default.svc.cluster.local
message: ok
status: successful
将上一步输出的内容更新到准备工作的ConfigMap中data
中的同名config.yaml
字段中。
kubectl edit ConfigMap ratelimit-config
更新后内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: ratelimit-config
data:
config.yaml: |
descriptors:
- descriptors:
- key: remote_address
rate_limit:
requests_per_unit: 1
unit: MINUTE
key: generic_key
rate_limit:
requests_per_unit: 100000
unit: SECOND
value: RateLimit[global-test.istio-system]-Id[537612397]
domain: ratelimit.default.svc.cluster.local
分别从不同的客户端连续访问bookinfo应用两次。
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -H 'host: bf2.example.com' http://$GATEWAY_URL:80/productpage -v
curl -H 'host: bf2.example.com' http://$GATEWAY_URL:80/productpage -v
第二次访问的预期输出:
< 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 Jul 2025 04:10:11 GMT
< server: istio-envoy
< content-length: 0
<
* Connection #0 to host 116.62.XXX.XXX left intact
可以看到,第二条请求被限流,表明对入口网关的全局限流配置成功。