使用 Envoy 启用速率限制
遵循中的指示说明在 Kubernetes 集群中安装 Istio。
部署 Bookinfo 示例应用程序。
Envoy 支持两种速率限制:全局和本地。全局速率使用全局 gRPC 速率限制服务为整个网格提供速率限制。 本地速率限制用于限制每个服务实例的请求速率。局部速率限制可以与全局速率限制一起使用,以减少负载全局速率限制服务。
在本任务中,您将配置 Envoy 以对服务的特定路径的流量进行速率限制同时使用全局和本地速率限制。
Envoy 可以用来为您的网格。 Envoy 中的全局速率限制使用 gRPC API 从速率限制服务请求配额。 下文使用的参考实现后端,是用 Go 语言编写并使用 Redis 作为缓存。
参考下面的 configmap ,对
/productpage
的限制速率为每分钟 1 次,其他所有请求的限制速率为每分钟 100 次。创建一个全局速率限制服务,它实现 Envoy 的速率限制服务协议。作为参考,可以在找到一个演示配置,它是基于 Envoy 提供的参考实现。
-
此 patch 将
envoy.filters.http.ratelimit
插入到HTTP_FILTER
链中。rate_limit_service
字段指定外部速率限制服务,在本例中为outbound|8081||ratelimit.default.svc.cluster.local
。$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: filter-ratelimit
namespace: istio-system
spec:
workloadSelector:
# select by label in the same namespace
labels:
istio: ingressgateway
configPatches:
# The Envoy config you want to modify
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
# Adds the Envoy Rate Limit Filter in HTTP filter chain.
value:
name: envoy.filters.http.ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
# domain can be anything! Match it to the ratelimter service config
domain: productpage-ratelimit
failure_mode_deny: true
timeout: 10s
rate_limit_service:
grpc_service:
envoy_grpc:
cluster_name: outbound|8081||ratelimit.default.svc.cluster.local
authority: ratelimit.default.svc.cluster.local
transport_api_version: V3
EOF
对定义限速路由配置的
ingressgateway
应用另一个EnvoyFilter
。对于来自名为*.80
的虚拟主机的任何路由,这增加了速率限制动作。$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: filter-ratelimit-svc
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: VIRTUAL_HOST
context: GATEWAY
routeConfiguration:
vhost:
name: ""
route:
action: ANY
patch:
# Applies the rate limit rules.
value:
rate_limits:
- actions: # any actions in here
- request_headers:
header_name: ":path"
descriptor_key: "PATH"
EOF
Envoy 支持 L4 连接和 HTTP 请求的本地速率限制。
这允许您在代理本身的实例级应用速率限制,而无需调用任何其他服务。
下面的 EnvoyFilter
为通过 productpage
服务的任何流量启用了本地速率限制。 HTTP_FILTER
patch 会插入 envoy.filters.http.local_ratelimit
到 HTTP 连接管理器过滤器链中。本地速率限制过滤器的令牌桶被配置为允许每分钟 10 个请求。该过滤器还配置为添加 x-local-rate-limit
响应头到被阻塞的请求。
在 中提到的统计数据默认是禁用的。您可以在部署期间使用以下注解启用它们:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: filter-local-ratelimit-svc
namespace: istio-system
spec:
workloadSelector:
labels:
app: productpage
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
value:
stat_prefix: http_local_rate_limiter
token_bucket:
max_tokens: 10
tokens_per_fill: 10
fill_interval: 60s
filter_enabled:
runtime_key: local_rate_limit_enabled
default_value:
numerator: 100
denominator: HUNDRED
filter_enforced:
runtime_key: local_rate_limit_enforced
default_value:
numerator: 100
denominator: HUNDRED
response_headers_to_add:
- append: false
header:
key: x-local-rate-limit
value: 'true'
EOF
上述配置对所有 vhosts/routes 都进行本地速率限制。或者,您可以将其限制为特定的路由。
本地 Envoy 过滤器,用于路由到虚拟主机 inbound|http|9080
。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
namespace: istio-system
spec:
workloadSelector:
labels:
app: productpage
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
value:
stat_prefix: http_local_rate_limiter
- applyTo: HTTP_ROUTE
match:
context: SIDECAR_INBOUND
routeConfiguration:
vhost:
name: "inbound|http|9080"
route:
action: ANY
patch:
operation: MERGE
value:
typed_per_filter_config:
envoy.filters.http.local_ratelimit:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
value:
stat_prefix: http_local_rate_limiter
token_bucket:
max_tokens: 10
tokens_per_fill: 10
fill_interval: 60s
filter_enabled:
runtime_key: local_rate_limit_enabled
default_value:
numerator: 100
denominator: HUNDRED
filter_enforced:
runtime_key: local_rate_limit_enforced
default_value:
numerator: 100
denominator: HUNDRED
response_headers_to_add:
- append: false
header:
key: x-local-rate-limit
value: 'true'
EOF
向 Bookinfo 示例发送通信流。在您的网站上访问 http://$GATEWAY_URL/productpage
浏览器或发出以下命令:
$GATEWAY_URL
是在 Bookinfo 示例中设置的值。
您将看到第一个请求通过,但随后的每个请求在一分钟内将得到 429 响应。
虽然入口网关的全局速率限制将对 productpage
服务的请求限制在每分钟 1 个请求,但 productpage
实例的本地速率限制允许每分钟 10 个请求。
为了确认这一点,使用下面的 curl
命令从 ratings
Pod 发送内部 productpage
请求:
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage -o /dev/null -w "%{http_code}\n"
429
您应该看到每个 productpage
实例的请求次数每分钟不超过 10 个。
$ kubectl delete envoyfilter filter-ratelimit -nistio-system
$ kubectl delete envoyfilter filter-ratelimit-svc -nistio-system
$ kubectl delete envoyfilter filter-local-ratelimit-svc -nistio-system
$ kubectl delete cm ratelimit-config