文档

使用ASMGlobalRateLimiter对应用服务入口流量配置全局限流

限流是一种限制发送到服务端的请求数量的机制。它指定客户端在给定时间段内可以向服务端发送的最大请求数,通常表示为一段时间内的请求数,例如每分钟300个请求或每秒10个请求等。服务网格ASM自1.18.0.131版本起,支持针对入口网关和注入了Sidecar的应用服务的入口流量配置全局限流。本文介绍如何在ASM中使用ASMGlobalRateLimiter对应用服务入口流量配置全局限流。

前提条件

  • 已添加Kubernetes托管版集群到ASM实例,且ASM实例为1.18.0.131及以上。具体操作,请参见添加集群到ASM实例

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

  • 已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关

准备工作

您需要先在数据面集群中部署限流服务,才能使全局限流功能生效。部署限流服务和示例应用的步骤如下。

说明

Envoy代理实现限流主要有两种方式:全局限流、本地限流。本文仅介绍全局限流的配置方法。关于限流的相关概念以及如何配置本地限流,请参见在流量管理中心配置本地限流

步骤一:部署限流服务

  1. 使用以下内容,创建ratelimit-svc.yaml。

    展开查看ratelimit-svc.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: redis
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
      labels:
        app: redis
    spec:
      ports:
      - name: redis
        port: 6379
      selector:
        app: redis
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: redis
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
       metadata:
          labels:
            app: redis
            sidecar.istio.io/inject: "false"
       spec:
          containers:
          - image: redis:alpine
            imagePullPolicy: Always
            name: redis
            ports:
            - name: redis
              containerPort: 6379
          restartPolicy: Always
          serviceAccountName: redis
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ratelimit-config
    data:
      config.yaml: |
        {}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: ratelimit
      labels:
        app: ratelimit
    spec:
      ports:
      - name: http-port
        port: 8080
        targetPort: 8080
        protocol: TCP
      - name: grpc-port
        port: 8081
        targetPort: 8081
        protocol: TCP
      - name: http-debug
        port: 6070
        targetPort: 6070
        protocol: TCP
      selector:
        app: ratelimit
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ratelimit
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: ratelimit
      strategy:
        type: Recreate
      template:
        metadata:
          labels:
            app: ratelimit
            sidecar.istio.io/inject: "false"
        spec:
          containers:
            # Latest image from https://hub.docker.com/r/envoyproxy/ratelimit/tags
          - image: envoyproxy/ratelimit:e059638d 
            imagePullPolicy: Always
            name: ratelimit
            command: ["/bin/ratelimit"]
            env:
            - name: LOG_LEVEL
              value: debug
            - name: REDIS_SOCKET_TYPE
              value: tcp
            - name: REDIS_URL
              value: redis:6379
            - name: USE_STATSD
              value: "false"
            - name: RUNTIME_ROOT
              value: /data
            - name: RUNTIME_SUBDIRECTORY
              value: ratelimit
            - name: RUNTIME_WATCH_ROOT
              value: "false"
            - name: RUNTIME_IGNOREDOTFILES
              value: "true"
            ports:
            - containerPort: 8080
            - containerPort: 8081
            - containerPort: 6070
            volumeMounts:
            - name: config-volume
              # $RUNTIME_ROOT/$RUNTIME_SUBDIRECTORY/$RUNTIME_APPDIRECTORY/config.yaml
              mountPath: /data/ratelimit/config
          volumes:
          - name: config-volume
            configMap:
              name: ratelimit-config
  2. 在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中创建限流服务和限流服务依赖的Redis服务。

    kubectl apply -f ratelimit-svc.yaml

步骤二:部署Bookinfo示例应用

  1. Github的Istio项目库中下载Bookinfo应用的YAML文件bookinfo.yaml。

  2. 在ACK集群对应的KubeConfig环境下,执行以下命令,将Bookinfo应用部署到ASM实例的集群中。

    kubectl apply -f bookinfo.yaml
  3. 使用以下内容,创建bookinfo-gateway.yaml。

    展开查看bookinfo-gateway.yaml

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: bookinfo-gateway
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - bf2.example.com
          port:
            name: http
            number: 80
            protocol: http
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: bookinfo
      namespace: default
    spec:
      gateways:
        - bookinfo-gateway
      hosts:
        - bf2.example.com
      http:
        - match:
            - uri:
                exact: /productpage
            - uri:
                prefix: /static
            - uri:
                exact: /login
            - uri:
                exact: /logout
            - uri:
                prefix: /api/v1/products
          name: productpage-route-name1
          route:
            - destination:
                host: productpage
                port:
                  number: 9080
  4. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建入口网关ingressgateway对Bookinfo应用的路由规则。

    该路由规则匹配请求域名bf2.example.com,且具有名称productpage-route-name1

    kubectl apply -f bookinfo-gateway.yaml

步骤三:部署httpbin和sleep示例服务

  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. 在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中创建httpbin服务。

    kubectl apply -f httpbin.yaml
  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. 在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中创建sleep服务。

    kubectl apply -f sleep.yaml

场景一:对服务的特定端口配置全局限流

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

  1. 使用以下内容,创建global-ratelimit-svc.yaml。

    展开查看global-ratelimit-svc.yaml

    apiVersion: istio.alibabacloud.com/v1beta1
    kind: ASMGlobalRateLimiter
    metadata:
      name: global-svc-test
      namespace: default
    spec:
      workloadSelector:
        labels:
          app: httpbin
      rateLimitService:
        host: ratelimit.default.svc.cluster.local
        port: 8081
        timeout:
          seconds: 5
      isGateway: false
      configs:
      - name: httpbin
        limit:
          unit: MINUTE
          quota: 1
        match:
          vhost:
            name: '*'
            port: 8000

    部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明

    字段

    说明

    workloadSelector

    用于匹配限流生效的工作负载。本场景中全局限流生效于httpbin服务的工作负载,设置为app: httpbin

    isGateway

    是否作用于网关。本示例中设定为false

    rateLimitService

    限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:

        host: ratelimit.default.svc.cluster.local
        port: 8081
        timeout:
          seconds: 5

    limit

    需要生效的限流配置参数。其中unit表示限流检测的时间单位,quota表示单位时间内允许的请求总量。

    本示例配置unitMINUTEquota1,表示匹配路由上每分钟只能发送一个请求,超出的请求将被限流。

    vhost

    限流匹配的域名和路由项配置。在生效于应用服务时,name需要填写为'*'port需要填写为服务的Service端口。

  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于应用服务httpbin入口流量的全局限流规则。

    kubectl apply -f global-ratelimit-svc.yaml
  3. 执行以下命令,获取调谐完成的全局限流规则配置内容。

    kubectl get asmglobalratelimiter global-svc-test -o yaml

    展开查看预期输出

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMGlobalRateLimiter
    metadata:
      name: global-svc-test
      namespace: default
    spec:
      configs:
      - limit:
          quota: 1
          unit: MINUTE
        match:
          vhost:
            name: '*'
            port: 8000
        name: httpbin
      isGateway: false
      rateLimitService:
        host: ratelimit.default.svc.cluster.local
        port: 8081
        timeout:
          seconds: 5
      workloadSelector:
        labels:
          app: httpbin
    status:
      config.yaml: |
        descriptors:
        - key: generic_key
          rate_limit:
            requests_per_unit: 1
            unit: MINUTE
          value: RateLimit[global-svc-test.default]-Id[3833670472]
        domain: ratelimit.default.svc.cluster.local
      message: ok
      status: successful
  4. 将上一步预期输出的ASMGlobalRateLimiter资源中status字段的config.yaml内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。

    ASMGlobalRateLimiter中status字段下的config.yaml字段中的字符串内容,需原样粘贴至ConfigMap中data中的同名config.yaml字段中。

    展开查看ratelimit-config.yaml

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ratelimit-config
    data:
      config.yaml: |
        descriptors:
        - key: header_match
          rate_limit:
            requests_per_unit: 1
            unit: MINUTE
          value: RateLimit[global-svc-test.default]-Id[1492204717]
        domain: ratelimit.default.svc.cluster.local
  5. 在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。

    kubectl apply -f ratelimit-config.yaml
  6. 执行以下命令,进入sleep应用开启bash。

    kubectl exec -it deploy/sleep -- sh
  7. 执行以下命令,连续访问httpbin服务两次。

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

    预期输出:

    < HTTP/1.1 429
    < x-envoy-ratelimited: true
    < x-ratelimit-limit: 1, 1;w=60
    < x-ratelimit-remaining: 0
    < x-ratelimit-reset: 5
    < date: Thu, 26 Oct 2023 04:23:54 GMT
    < server: envoy
    < content-length: 0
    < x-envoy-upstream-service-time: 2
    < 
    * Connection #0 to host httpbin left intact

    在全局限流配置中,限制1分钟之内只能有一次访问httpbin服务的请求。当连续两次访问httpbin服务时,可以看到第二条请求被限流,表明对注入Sidecar的应用服务入口流量配置全局限流成功。

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

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

  1. 根据ASM版本,按需选择以下内容,创建global-ratelimit-svc.yaml。

    • ASM版本为1.19.0以下:

      展开查看YAML

      apiVersion: istio.alibabacloud.com/v1beta1
      kind: ASMGlobalRateLimiter
      metadata:
        name: global-svc-test
        namespace: default
      spec:
        workloadSelector:
          labels:
            app: httpbin
        rateLimitService:
          host: ratelimit.default.svc.cluster.local
          port: 8081
          timeout:
            seconds: 5
        isGateway: false
        configs:
        - name: httpbin
          limit:
            unit: MINUTE
            quota: 1
          match:
            vhost:
              name: '*'
              port: 8000
              route:
                header_match:
                - name: ":path"
                  prefix_match: "/headers"
    • ASM版本为1.19.0及以上:

      展开查看YAML

      apiVersion: istio.alibabacloud.com/v1beta1
      kind: ASMGlobalRateLimiter
      metadata:
        name: global-svc-test
        namespace: default
      spec:
        workloadSelector:
          labels:
            app: httpbin
        rateLimitService:
          host: ratelimit.default.svc.cluster.local
          port: 8081
          timeout:
            seconds: 5
        isGateway: false
        configs:
        - name: httpbin
          limit:
            unit: SECOND
            quota: 100000
          match:
            vhost:
              name: '*'
              port: 8000
          limit_overrides:
          - request_match:
              header_match:
              - name: ":path"
                prefix_match: "/headers"
            limit:
              unit: MINUTE
              quota: 1

      部分字段说明如下。关于字段的更多信息,请参见ASMGlobalRateLimiter CRD说明

      字段

      说明

      workloadSelector

      用于匹配限流生效的工作负载。本场景中全局限流生效于httpbin服务的工作负载,设置为app: httpbin

      isGateway

      是否作用于网关。本示例设定为false

      rateLimitService

      限流服务的域名、端口和连接超时设置。根据准备工作中部署的限流服务,配置如下:

          host: ratelimit.default.svc.cluster.local
          port: 8081
          timeout:
            seconds: 5

      limit

      需要生效的限流配置参数。其中unit表示限流检测的时间单位,quota表示单位时间内允许的请求总量。

      本示例配置unitMINUTEquota1,表示匹配路由上每分钟只能发送一个请求,超出的请求将被限流。

      在ASM实例为1.19.0及以上版本,限流配置参数为每秒100000个请求,约等于没有限流,因为针对满足特定条件请求的限流生效在limit_overrides字段中。

      vhost

      限流匹配的域名和路由项配置。在生效于应用服务时,name需要填写为'*'port需要填写为服务的Service端口。

      • 在ASM实例为1.19.0以下版本,您还可以在route中配置针对请求的Header匹配规则。本示例中匹配名为:path的特殊Header,即匹配请求的路径,语义为匹配所有路径以/开头的请求。

      • 在ASM实例为1.19.0及以上版本,在route中配置针对请求的Header匹配规则被移动到limit_overrides字段中。

      limit_overrides

      限流覆盖配置,仅支持ASM实例为1.19.0及以上版本。支持匹配请求的不同属性,并对匹配到的特定请求应用单独的限流配置。在本示例中,limit_overrides字段里指定了匹配特殊的Header :path,即匹配请求的路径,语义为匹配所有路径以/headers开头的请求。

  2. 在ASM实例对应的KubeConfig环境下,执行以下命令,创建生效于应用服务httpbin入口流量的全局限流规则。

    kubectl apply -f global-ratelimit-svc.yaml
  3. 执行以下命令,获取调谐完成的全局限流规则配置内容。

    kubectl get asmglobalratelimiter global-svc-test -o yaml

    展开查看预期输出

    apiVersion: istio.alibabacloud.com/v1
    kind: ASMGlobalRateLimiter
    metadata:
      name: global-svc-test
      namespace: default
    spec:
      configs:
      - limit:
          quota: 100000
          unit: SECOND
        limit_overrides:
        - limit:
            quota: 1
            unit: MINUTE
          request_match:
            header_match:
            - name: :path
              prefix_match: /headers
        match:
          vhost:
            name: '*'
            port: 8000
        name: httpbin
      isGateway: false
      rateLimitService:
        host: ratelimit.default.svc.cluster.local
        port: 8081
        timeout:
          seconds: 5
      workloadSelector:
        labels:
          app: httpbin
    status:
      config.yaml: |
        descriptors:
        - descriptors:
          - key: header_match
            rate_limit:
              requests_per_unit: 1
              unit: MINUTE
            value: RateLimit[global-svc-test.default]-Id[2613586978]
          key: generic_key
          rate_limit:
            requests_per_unit: 100000
            unit: SECOND
          value: RateLimit[global-svc-test.default]-Id[2613586978]
        domain: ratelimit.default.svc.cluster.local
      message: ok
      status: successful
  4. 将上一步预期输出的ASMGlobalRateLimiter资源中status字段的config.yaml内容,粘贴至ratelimit-config.yaml,生成全局限流服务配置。

    ASMGlobalRateLimiter中status字段下的config.yaml字段中的字符串内容,需原样粘贴至ConfigMap中data中的同名config.yaml字段中。

    展开查看ratelimit-config.yaml

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: ratelimit-config
    data:
      config.yaml: |
        descriptors:
        - descriptors:
          - key: header_match
            rate_limit:
              requests_per_unit: 1
              unit: MINUTE
            value: RateLimit[global-svc-test.default]-Id[2613586978]
          key: generic_key
          rate_limit:
            requests_per_unit: 100000
            unit: SECOND
          value: RateLimit[global-svc-test.default]-Id[2613586978]
        domain: ratelimit.default.svc.cluster.local
  5. 在ACK集群对应的KubeConfig环境下,执行以下命令,在集群中更新全局限流服务配置。

    kubectl apply -f ratelimit-config.yaml
  6. 执行以下命令,进入sleep应用开启bash。

    kubectl exec -it deploy/sleep -- sh
  7. 执行以下命令,连续访问httpbin服务的/headers路径两次。

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

    预期输出:

    < HTTP/1.1 429 Too Many Requests
    < x-envoy-ratelimited: true
    < x-ratelimit-limit: 1, 1;w=60
    < x-ratelimit-remaining: 0
    < x-ratelimit-reset: 5
    < date: Thu, 26 Oct 2023 04:23:54 GMT
    < server: envoy
    < content-length: 0
    < x-envoy-upstream-service-time: 2
    < 
    * Connection #0 to host httpbin left intact

    在全局限流配置中,限制在/headers路径上,1分钟之内只能有一次访问httpbin服务的请求。当连续两次访问httpbin服务的/headers路径时,可以看到第二条请求被限流,表明对注入Sidecar的应用服务入口流量配置全局限流成功。

  8. 执行以下命令,访问httpbin服务的/get路径。

    curl httpbin:8000/get -v

    展开查看预期输出

    *   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 06:25:09 GMT
    < content-type: application/json
    < content-length: 431
    < access-control-allow-origin: *
    < access-control-allow-credentials: true
    < x-envoy-upstream-service-time: 7
    <
    {
      "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"
    }
    * Connection #0 to host httpbin left intact

    可以看到发往httpbin服务其它路径的请求并未受到全局限流配置的影响,仍然可以正常访问。

相关文档

  • 本页导读 (1)
文档反馈