全部产品
Search
文档中心

服务网格 ASM:在流量管理中心配置本地限流

更新时间:Oct 23, 2024

在高流量冲击、潜在服务过载、资源耗尽或恶意攻击等情况下,您可以在流量管理中心配置本地限流,将流量维持在可控的阈值内,确保服务持续可用并维持性能稳定。本地限流通过Envoy代理实现,它采用令牌桶算法来控制向服务端的请求流量。此算法定期向令牌桶添加令牌,每个请求消耗一枚令牌。令牌耗尽时,系统将暂停接受新请求,有效预防过载情况发生。

前提条件

  • 已创建ASM实例,且ASM实例符合以下要求:

    • ASM商业版(专业版或旗舰版):版本需为1.14.3及以上。关于升级ASM实例的具体操作,请参见升级ASM实例

    • ASM标准版:仅支持Istio原生方式配置本地限流功能,且版本需为1.9及以上。不同Istio版本需参考相应版本文档,关于最新的Istio版本配置本地限流功能的具体操作,请参见Enabling Rate Limits using Envoy

  • 已为Kubernetes集群中的default命名空间开启自动注入。具体操作,请参见启用自动注入

  • 已部署httpbin和sleep示例服务,并且sleep服务可以正常访问httpbin服务。具体操作,请参见部署httpbin应用

场景一:对服务的特定端口进行限流

对httpbin服务的8000端口进行限流。配置限流规则后,发往httpbin服务8000端口的所有请求都将受到流量速率限制。

  1. 创建本地限流规则。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择流量管理中心 > 限流防护,然后单击创建

    3. 创建页面,按需进行以下配置,然后单击确定

      配置区域

      配置项

      说明

      限流基本信息

      命名空间

      本地限流配置的命名空间,需要配置为限流生效的工作负载所在的命名空间。本示例选择default

      名称

      本地限流配置的自定义名称。本示例填写httpbin

      生效工作负载类型

      限流生效的工作负载类型,支持应用服务生效网关生效。本示例选择应用服务生效

      关联工作负载

      需要填写一系列标签键值对,以选中具体工作负载。本示例填写标签名app标签值httpbin。

      限流规则列表

      服务Service端口

      填写服务的Kubernetes Service中声明的端口号,需要为HTTP端口。本示例填写httpbin服务的HTTP端口8000

      限流配置

      指定本地限流令牌桶算法的检测时间窗口长度与时间窗口内允许的请求数量。在时间窗口内发送的请求数量超过该允许的数量则会对请求进行限流。本示例配置如下:

      • 限流检测时间窗口填写60秒

      • 时间窗口内允许请求数量填写10

      以上配置表示发往此服务的工作负载的请求不得在60秒内连续发送10个以上。

      image

      以上配置对应的本地限流配置YAML如下。

      展开查看本地限流配置YAML

      apiVersion: istio.alibabacloud.com/v1beta1
      kind: ASMLocalRateLimiter
      metadata:
        name: httpbin
        namespace: default
      spec:
        configs:
          - limit:
              fill_interval:
                seconds: 60
              quota: 10
            match:
              vhost:
                name: '*'
                port: 8000
                route:
                  header_match:
                    - invert_match: false
                      name: ':path'
                      prefix_match: /
        isGateway: false
        workloadSelector:
          labels:
            app: httpbin

  2. 验证本地限流规则。

    1. 执行以下命令,进入sleep环境开启bash。

      kubectl exec -it deploy/sleep -- sh
    2. 执行以下命令,发送10个请求。

      for i in $(seq 1 10); do curl -v http://httpbin:8000/headers; done
    3. 执行以下命令,发送第11个请求。

      curl -v http://httpbin:8000/headers

      预期输出:

      *   Trying 172.16.245.130:8000...
      * Connected to httpbin (172.16.245.130) port 8000
      > GET /headers HTTP/1.1
      > Host: httpbin:8000
      > User-Agent: curl/8.5.0
      > Accept: */*
      >
      < HTTP/1.1 429 Too Many Requests
      < x-local-rate-limit: true
      < content-length: 18
      < content-type: text/plain
      < date: Tue, 26 Dec 2023 08:02:58 GMT
      < server: envoy
      < x-envoy-upstream-service-time: 2

      由预期输出得到,返回HTTP 429的状态码。请求已被限流。

场景二:在服务特定端口上,针对发往指定路径的请求进行限流

对httpbin服务的8000端口进行限流,并限制限流只在访问/headers路径的请求上生效。配置限流规则后,发往httpbin服务8000端口且访问路径/headers的所有请求都将受到流量速率限制。

  1. 创建本地限流规则。

    1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

    2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择流量管理中心 > 限流防护,然后单击创建

    3. 创建页面,按需进行以下配置,然后单击确定

      配置区域

      配置项

      说明

      限流基本信息

      命名空间

      本地限流配置的命名空间,需要配置为限流生效的工作负载的所在命名空间。本示例选择default

      名称

      本地限流配置的自定义名称。本示例填写httpbin

      生效工作负载类型

      限流生效的工作负载类型,支持应用服务生效网关生效。本示例选择应用服务生效

      关联工作负载

      需要填写一系列标签键值对,以选中具体工作负载。本示例填写标签名app标签值httpbin。

      限流规则列表

      服务Service端口

      填写服务的Kubernetes Service中声明的端口号,需要为HTTP端口。本示例填写httpbin服务的HTTP端口8000

      匹配请求属性

      填写生效限流配置的具体请求匹配规则。本示例配置如下:

      • 匹配属性选择请求路径

      • 匹配方法选择前缀匹配

      • 匹配内容填写/headers

      限流配置

      指定本地限流令牌桶算法的检测时间窗口长度与时间窗口内允许的请求数量。在时间窗口内发送的请求数量超过该允许的数量则会对请求进行限流。本示例配置如下:

      • 限流检测时间窗口填写60秒

      • 时间窗口内允许请求数量填写10

      以上配置表示发往此服务的工作负载的请求不得在60秒内连续发送10个以上。

      image

  2. 验证本地限流规则。

    1. 执行以下命令,进入sleep环境开启bash。

      kubectl exec -it deploy/sleep -- sh
    2. 执行以下命令,发送10个请求。

      for i in $(seq 1 10); do curl -v http://httpbin:8000/headers; done
    3. 执行以下命令,发送第11个请求。

      curl -v http://httpbin:8000/headers

      预期输出:

      *   Trying 172.16.245.130:8000...
      * Connected to httpbin (172.16.245.130) port 8000
      > GET /headers HTTP/1.1
      > Host: httpbin:8000
      > User-Agent: curl/8.5.0
      > Accept: */*
      >
      < HTTP/1.1 429 Too Many Requests
      < x-local-rate-limit: true
      < content-length: 18
      < content-type: text/plain
      < date: Tue, 26 Dec 2023 08:02:58 GMT
      < server: envoy
      < x-envoy-upstream-service-time: 2

      由预期输出得到,返回HTTP 429的状态码。请求已被限流。

    4. 执行以下命令,向httpbin服务的/get路径发送请求。

      curl -v http://httpbin:8000/get

      预期输出:

      *   Trying 192.168.243.21:8000...
      * Connected to httpbin (192.168.243.21) port 8000 (#0)
      > GET /get HTTP/1.1
      > Host: httpbin:8000
      > User-Agent: curl/8.1.2
      > Accept: */*
      >
      < HTTP/1.1 200 OK
      < server: envoy
      < date: Thu, 11 Jan 2024 03:46:11 GMT
      < content-type: application/json
      < content-length: 431
      < access-control-allow-origin: *
      < access-control-allow-credentials: true
      < x-envoy-upstream-service-time: 1
      <
      {
        "args": {},
        "headers": {
          "Accept": "*/*",
          "Host": "httpbin:8000",
          "User-Agent": "curl/8.1.2",
          "X-Envoy-Attempt-Count": "1",
          "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=be10819991ba1a354a89e68b3bed1553c12a4fba8b65fbe0f16299d552680b29;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep"
        },
        "origin": "127.0.0.6",
        "url": "http://httpbin:8000/get"
      }

      由预期输出得到,返回200状态码。发往httpbin服务的其他路径的请求并未受到限流规则影响。

相关操作

查看本地限流相关指标

本地限流功能会产生以下指标:

Metric

描述

envoy_http_local_rate_limiter_http_local_rate_limit_enabled

触发限流的请求总数。

envoy_http_local_rate_limiter_http_local_rate_limit_ok

来自令牌桶的限流响应总数。

envoy_http_local_rate_limiter_http_local_rate_limit_rate_limited

没有令牌的请求总数(但不一定强制执行限流)。

envoy_http_local_rate_limiter_http_local_rate_limit_enforced

最终收到限流响应的总数(例如返回429)。

您可以通过配置Sidecar代理的proxyStatsMatcher使Sidecar代理上报相关指标,然后使用Prometheus采集并查看限流相关指标。

  1. 通过proxyStatsMatcher配置Sidecar代理上报限流指标。

    在配置proxyStatsMatcher时,选中正则匹配,配置为.*http_local_rate_limit.*;或者直接单击添加本地限流指标。具体操作,请参见proxyStatsMatcher

  2. 重新部署httpbin服务。具体操作,请参见重新部署工作负载

  3. 参照上文场景一场景二,完成本地限流配置及请求访问。

  4. 执行以下命令,查看httpbin服务的本地限流相关指标。

    kubectl exec -it deploy/httpbin -c istio-proxy -- curl localhost:15020/stats/prometheus|grep http_local_rate_limit

    预期输出:

    envoy_http_local_rate_limiter_http_local_rate_limit_enabled{} 37
    
    envoy_http_local_rate_limiter_http_local_rate_limit_enforced{} 17
    
    envoy_http_local_rate_limiter_http_local_rate_limit_ok{} 20
    
    envoy_http_local_rate_limiter_http_local_rate_limit_rate_limited{} 17

配置本地限流指标采集和告警

配置完成上报本地限流功能指标后,您可以配置采集相关指标到Prometheus,并基于关键指标配置告警规则,实现熔断发生时的及时告警。以下以可观测监控Prometheus版为例说明如何配置本地限流指标采集和告警。

  1. 在可观测监控Prometheus版中,为数据面集群接入阿里云ASM组件或升级至最新版,以保证可观测监控Prometheus版可以采集到暴露的本地限流指标。关于接入组件的具体操作,请参见接入组件管理。(如果您已经集成自建Prometheus实现网格监控来采集服务网格指标,则无需做额外操作。)

  2. 创建针对本地限流的告警规则。具体操作,请参见通过自定义PromQL创建Prometheus告警规则。配置告警规则的关键参数的填写示例如下,其余参数可参考上述文档根据实际需求填写。

    参数

    示例

    说明

    自定义PromQL语句

    (sum by(namespace, pod_name) (increase(envoy_http_local_rate_limiter_http_local_rate_limit_enforced[1m]))) > 0

    示例PromQL通过increase查询最近1分钟之内被限流的请求数量,并根据触发限流的pod所在命名空间以及pod名称进行分组。当1分钟内被限流的请求数量大于0时触发告警。

    告警内容

    发生本地限流!命名空间:{{$labels.namespace}},触发限流的pod:{{$labels.pod_name}}。当前1分钟内被限流的请求数量:{{ $value }}

    用户收到的告警信息。示例的告警信息向用户展示了触发限流的pod所在命名空间以及pod名称,以及最近1分钟内被限流的请求数量

FAQ

为什么针对服务配置本地限流后没有生效?

服务没有使用HTTP协议进行通信、或者协议没有被服务网格正确识别

本地限流仅支持HTTP协议,在对服务配置限流规则之前,您需要确保服务正在使用HTTP协议,或其它基于HTTP协议构建的应用层协议(如gRPC、dubbo3)进行通信。

在服务本身使用HTTP协议通信的基础上,您还需要规范定义服务的协议类型,以保证服务网格可以正确识别服务所采用的应用层协议。具体操作,请参见如何规范定义服务的协议类型

使用Sidecar CRD修改了服务入向流量配置导致限流不生效

服务网格默认会根据Service定义中的端口声明,自动为Sidecar代理配置入向流量监听器。本地限流和全局限流功能都基于这一默认设置实现。

当您需要使集群中监听localhost的应用被其它Pod访问时,可能会使用Sidecar CRD来修改服务默认的入向流量配置。具体操作,请参见如何使集群中监听localhost的应用被其它Pod访问

在这种情况下,由于默认监听器被修改,在本地限流中直接指定服务Service端口将无法让限流生效。此时需要将本地限流中的服务Service端口配置为Sidecar CRD中指定的实际入向端口。

以本文中对httpbin服务的8000端口进行限流为例,若针对httpbin服务配置了以下的Sidecar CRD:

apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
  name: localhost-access
  namespace: default
spec:
  ingress:
    - defaultEndpoint: '127.0.0.1:80'
      port:
        name: http
        number: 80
        protocol: HTTP
  workloadSelector:
    labels:
      app: httpbin

此时创建本地限流规则时服务Service端口应该填写为80,而不是8000。

相关文档