使用 Envoy 启用速率限制

    1. 遵循中的指示说明在 Kubernetes 集群中安装 Istio。

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

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

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

    Envoy 可以用来为您的网格。 Envoy 中的全局速率限制使用 gRPC API 从速率限制服务请求配额。 下文使用的参考实现后端,是用 Go 语言编写并使用 Redis 作为缓存。

    1. 参考下面的 configmap ,对 /productpage 的限制速率为每分钟 1 次,其他所有请求的限制速率为每分钟 100 次。

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

    3. 此 patch 将 envoy.filters.http.ratelimit 插入到 HTTP_FILTER 链中。rate_limit_service 字段指定外部速率限制服务,在本例中为 outbound|8081||ratelimit.default.svc.cluster.local

      1. $ kubectl apply -f - <<EOF
      2. apiVersion: networking.istio.io/v1alpha3
      3. kind: EnvoyFilter
      4. metadata:
      5. name: filter-ratelimit
      6. namespace: istio-system
      7. spec:
      8. workloadSelector:
      9. # select by label in the same namespace
      10. labels:
      11. istio: ingressgateway
      12. configPatches:
      13. # The Envoy config you want to modify
      14. - applyTo: HTTP_FILTER
      15. match:
      16. context: GATEWAY
      17. listener:
      18. filterChain:
      19. filter:
      20. name: "envoy.filters.network.http_connection_manager"
      21. subFilter:
      22. name: "envoy.filters.http.router"
      23. patch:
      24. operation: INSERT_BEFORE
      25. # Adds the Envoy Rate Limit Filter in HTTP filter chain.
      26. value:
      27. name: envoy.filters.http.ratelimit
      28. typed_config:
      29. "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
      30. # domain can be anything! Match it to the ratelimter service config
      31. domain: productpage-ratelimit
      32. failure_mode_deny: true
      33. timeout: 10s
      34. rate_limit_service:
      35. grpc_service:
      36. envoy_grpc:
      37. cluster_name: outbound|8081||ratelimit.default.svc.cluster.local
      38. authority: ratelimit.default.svc.cluster.local
      39. transport_api_version: V3
      40. EOF
    4. 对定义限速路由配置的 ingressgateway 应用另一个 EnvoyFilter。对于来自名为 *.80 的虚拟主机的任何路由,这增加了速率限制动作

      1. $ kubectl apply -f - <<EOF
      2. apiVersion: networking.istio.io/v1alpha3
      3. kind: EnvoyFilter
      4. metadata:
      5. name: filter-ratelimit-svc
      6. namespace: istio-system
      7. spec:
      8. workloadSelector:
      9. labels:
      10. istio: ingressgateway
      11. configPatches:
      12. - applyTo: VIRTUAL_HOST
      13. context: GATEWAY
      14. routeConfiguration:
      15. vhost:
      16. name: ""
      17. route:
      18. action: ANY
      19. patch:
      20. # Applies the rate limit rules.
      21. value:
      22. rate_limits:
      23. - actions: # any actions in here
      24. - request_headers:
      25. header_name: ":path"
      26. descriptor_key: "PATH"
      27. EOF

    Envoy 支持 L4 连接和 HTTP 请求的本地速率限制

    这允许您在代理本身的实例级应用速率限制,而无需调用任何其他服务。

    下面的 EnvoyFilter 为通过 productpage 服务的任何流量启用了本地速率限制。 HTTP_FILTER patch 会插入 envoy.filters.http.local_ratelimit 到 HTTP 连接管理器过滤器链中。本地速率限制过滤器的令牌桶被配置为允许每分钟 10 个请求。该过滤器还配置为添加 x-local-rate-limit 响应头到被阻塞的请求。

    在 中提到的统计数据默认是禁用的。您可以在部署期间使用以下注解启用它们:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: EnvoyFilter
    4. metadata:
    5. name: filter-local-ratelimit-svc
    6. namespace: istio-system
    7. spec:
    8. workloadSelector:
    9. labels:
    10. app: productpage
    11. configPatches:
    12. - applyTo: HTTP_FILTER
    13. match:
    14. context: SIDECAR_INBOUND
    15. listener:
    16. filterChain:
    17. filter:
    18. name: "envoy.filters.network.http_connection_manager"
    19. patch:
    20. operation: INSERT_BEFORE
    21. value:
    22. name: envoy.filters.http.local_ratelimit
    23. typed_config:
    24. "@type": type.googleapis.com/udpa.type.v1.TypedStruct
    25. type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    26. value:
    27. stat_prefix: http_local_rate_limiter
    28. token_bucket:
    29. max_tokens: 10
    30. tokens_per_fill: 10
    31. fill_interval: 60s
    32. filter_enabled:
    33. runtime_key: local_rate_limit_enabled
    34. default_value:
    35. numerator: 100
    36. denominator: HUNDRED
    37. filter_enforced:
    38. runtime_key: local_rate_limit_enforced
    39. default_value:
    40. numerator: 100
    41. denominator: HUNDRED
    42. response_headers_to_add:
    43. - append: false
    44. header:
    45. key: x-local-rate-limit
    46. value: 'true'
    47. EOF

    上述配置对所有 vhosts/routes 都进行本地速率限制。或者,您可以将其限制为特定的路由。

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

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: EnvoyFilter
    4. namespace: istio-system
    5. spec:
    6. workloadSelector:
    7. labels:
    8. app: productpage
    9. configPatches:
    10. - applyTo: HTTP_FILTER
    11. match:
    12. context: SIDECAR_INBOUND
    13. listener:
    14. filterChain:
    15. filter:
    16. name: "envoy.filters.network.http_connection_manager"
    17. patch:
    18. operation: INSERT_BEFORE
    19. value:
    20. name: envoy.filters.http.local_ratelimit
    21. typed_config:
    22. "@type": type.googleapis.com/udpa.type.v1.TypedStruct
    23. type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    24. value:
    25. stat_prefix: http_local_rate_limiter
    26. - applyTo: HTTP_ROUTE
    27. match:
    28. context: SIDECAR_INBOUND
    29. routeConfiguration:
    30. vhost:
    31. name: "inbound|http|9080"
    32. route:
    33. action: ANY
    34. patch:
    35. operation: MERGE
    36. value:
    37. typed_per_filter_config:
    38. envoy.filters.http.local_ratelimit:
    39. "@type": type.googleapis.com/udpa.type.v1.TypedStruct
    40. type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
    41. value:
    42. stat_prefix: http_local_rate_limiter
    43. token_bucket:
    44. max_tokens: 10
    45. tokens_per_fill: 10
    46. fill_interval: 60s
    47. filter_enabled:
    48. runtime_key: local_rate_limit_enabled
    49. default_value:
    50. numerator: 100
    51. denominator: HUNDRED
    52. filter_enforced:
    53. runtime_key: local_rate_limit_enforced
    54. default_value:
    55. numerator: 100
    56. denominator: HUNDRED
    57. response_headers_to_add:
    58. - append: false
    59. header:
    60. key: x-local-rate-limit
    61. value: 'true'
    62. EOF

    向 Bookinfo 示例发送通信流。在您的网站上访问 http://$GATEWAY_URL/productpage 浏览器或发出以下命令:

    $GATEWAY_URL 是在 Bookinfo 示例中设置的值。

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

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

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

    1. $ 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"
    2. 429

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

    1. $ kubectl delete envoyfilter filter-ratelimit -nistio-system
    2. $ kubectl delete envoyfilter filter-ratelimit-svc -nistio-system
    3. $ kubectl delete envoyfilter filter-local-ratelimit-svc -nistio-system
    4. $ kubectl delete cm ratelimit-config