使用 Envoy 启用速率限制

此任务向您展示如何使用Envoy的本地速率限制来动态地将流量限制到Istio服务。 在本任务中,您将通过允许的入口网关为productpage服务应用全局速率限制在服务的所有实例中,每分钟1次请求。 此外,您将为每个项目应用一个本地费率限制每个productpage实例将允许每分钟10个请求。 通过这种方式,您将确保productpageService通过入口网关每分钟最多处理一个请求,但是每个productpage实例可以处理 每分钟最多10个请求,允许任何网内通信。

开始之前

  1. 在Kubernetes集群中安装Istio Installation Guide

  2. 部署Bookinfo示例应用程序。

限制速率

Envoy支持两种速率限制:全局和本地。全局速率使用全局gRPC速率限制服务为整个网格提供速率限制。 本地速率限制用于限制每个服务实例的请求速率。局部速率限制可以与全局速率限制一起使用,以减少负载全局速率限制服务。

在本任务中,您将配置Envoy以对服务的特定路径的流量进行速率限制同时使用全局和本地速率限制。

全局速率

Envoy可以用来为您的网格设置全局速率限制。 Envoy中的全局速率限制使用gRPC API从速率限制服务请求配额。在下面使用Redis写的后端参考实现的API。

  1. 使用下面的configmap来配置引用实现以1分钟一个请求的速度对路径/productpage的限制请求进行评估,其他所有请求以一分钟100个请求的速度评估。

    apiVersion: v1 kind: ConfigMap metadata: name: ratelimit-config data: config.yaml: | domain: productpage-ratelimit descriptors: - key: PATH value: "/productpage" rate_limit: unit: minute requests_per_unit: 1 - key: PATH rate_limit: unit: minute requests_per_unit: 100

  2. 创建一个全局速率限制服务,它实现Envoy的速率限制服务协议。作为参考,可以在这里找到一个演示配置,它是基于Envoy提供的参考实现

  3. ingressgateway应用EnvoyFilter以使Envoy的全球速率限制过滤器启用全球速率限制

第一个patch插入envoy.filters.http.ratelimit全球Envoy过滤器的过滤器到HTTP_FILTERrate_limit_service字段指定外部速率限制服务,在本例中为rate_limit_cluster

`第二个patch定义了rate_limit_cluster`,它提供了外部速率限制服务的端点位置。

``` $ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: filter-ratelimit namespace: istio-system spec: workloadSelector:

  1. # select by label in the same namespace
  2. labels:
  3. istio: ingressgateway

configPatches:

  1. # The Envoy config you want to modify
  2. - applyTo: HTTP_FILTER
  3. match:
  4. context: GATEWAY
  5. listener:
  6. filterChain:
  7. filter:
  8. name: "envoy.filters.network.http_connection_manager"
  9. subFilter:
  10. name: "envoy.filters.http.router"
  11. patch:
  12. operation: INSERT_BEFORE
  13. # Adds the Envoy Rate Limit Filter in HTTP filter chain.
  14. value:
  15. name: envoy.filters.http.ratelimit
  16. typed_config:
  17. "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
  18. # domain can be anything! Match it to the ratelimter service config
  19. domain: productpage-ratelimit
  20. failure_mode_deny: true
  21. timeout: 10s
  22. rate_limit_service:
  23. grpc_service:
  24. envoy_grpc:
  25. cluster_name: rate_limit_cluster
  26. transport_api_version: V3
  27. - applyTo: CLUSTER
  28. match:
  29. cluster:
  30. service: ratelimit.default.svc.cluster.local
  31. patch:
  32. operation: ADD
  33. # Adds the rate limit service cluster for rate limit service defined in step 1.
  34. value:
  35. name: rate_limit_cluster
  36. type: STRICT_DNS
  37. connect_timeout: 10s
  38. lb_policy: ROUND_ROBIN
  39. http2_protocol_options: {}
  40. load_assignment:
  41. cluster_name: rate_limit_cluster
  42. endpoints:
  43. - lb_endpoints:
  44. - endpoint:
  45. address:
  46. socket_address:
  47. address: ratelimit.default.svc.cluster.local
  48. port_value: 8081

EOF `

  1. 对定义限速路由配置的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 match: context: GATEWAY routeConfiguration: vhost: name: "" route: action: ANY patch: operation: MERGE # 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_FILTERpatch会插入envoy.filters.httpLocal_ratelimit本地Envoy过滤器 进入HTTP连接管理器过滤器链。本地速率限制过滤器的令牌桶配置为允许10请求每分。该过滤器还配置为添加x-local-rate-limit。对被阻塞的请求的响应头。

Envoy速率限制页面中提到的统计数据默认是禁用的。您可以在部署期间使用以下注释启用它们:

template: metadata: annotations: proxy.istio.io/config: |- proxyStatsMatcher: inclusionRegexps: - ".*http_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都进行本地速率限制。或者,您可以将其限制为特定的路由。

下面的EnvoyFilterproductpage服务的80端口的任何流量启用了本地速率限制。与前面的配置不同,HTTP_FILTERpatch中不包含token_buckettoken_bucket被定义在第二个(HTTP_ROUTE)patch中,其中包含envoy.filters.http.local_ratelimittyped_per_filter_config

本地Envoy过滤器,用于路由到虚拟主机inbound|http|9080

$ 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 - 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浏览器或发出以下命令:

$ curl "http://$GATEWAY_URL/productpage"

$GATEWAY_URL is the value set in the Bookinfo example.

您将看到第一个请求通过,但随后的每个请求在一分钟内将得到429响应。

验证本地速率

虽然入口网关的全局速率限制将对productpage服务的请求限制在1请求每分,productpage实例的本地速率限制允许10请求每分。

为了确认这一点,从ratingspod发送内部productpage请求,使用下面的curl命令:

$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title>

您应该看到每个productpage实例的请求次数不超过10请求每分。