在流量管理中心配置本地限流

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

前提条件

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

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

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

  • 已添加集群到ASM实例。具体操作,请参见添加集群到ASM实例

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

准备工作

部署httpbin和sleep示例服务,并验证sleep服务能否正常访问httpbin服务。

  1. 使用以下内容,创建httpbin.yaml

    展开查看httpbin.yaml

    ##################################################################################################
    # httpbin Service示例。
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
  2. 执行以下命令,创建httpbin应用。

    kubectl apply -f httpbin.yaml -n default
  3. 使用以下内容,创建sleep.yaml

    展开查看sleep.yaml

    ##################################################################################################
    # Sleep Service示例。
    ##################################################################################################
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "infinity"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  4. 执行以下命令,创建sleep应用。

    kubectl apply -f sleep.yaml -n default
  5. 执行以下命令,进入sleep环境开启bash。

    kubectl exec -it deploy/sleep -- sh
  6. 执行以下命令,向httpbin服务发送请求。

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

    预期输出:

    HTTP/1.1 200 OK
    server: envoy
    date: Tue, 26 Dec 2023 07:23:49 GMT
    content-type: application/json
    content-length: 353
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 1

    返回200 OK,表明访问成功。

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

对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无状态工作负载。具体操作,请参见重新部署工作负载

    新创建的httpbin Pod中的Sidecar代理将可以上报限流相关指标。

  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

相关文档