更新时间:2026-06-05 GMT+08:00
分享

通过Envoy Gateway配置限流

限流是一种用于控制客户端向服务端发送请求速率的防护机制。其核心目的是防止系统因突发流量过载,确保服务的稳定性和高可用性。通常表示为一段时间内的请求数,例如每分钟100个请求或每秒10个请求等。

Envoy代理实现限流主要有两种方式:本地(Local)限流和全局(Global)限流。两者核心区别在于统计范围:本地限流在每个Envoy实例上独立计数,而全局限流则在所有实例间共享计数。为了更直观地说明,假设集群中已部署一个有5个Envoy实例的网关,并且配置了100请求/分钟的限流策略,两者的最终效果会完全不同:

  • 本地限流:每个Envoy实例只能感知到达自身的流量,各自独立计数。因此,整个系统理论上最多可处理5 * 100 = 500请求/分钟。这会导致后端服务实际承受的总负载远超预期。
  • 全局限流:所有网关实例共享统一的流量计数。通过引入Redis作为中心化、高性能的分布式计数器,确保无论请求落在哪一个Envoy实例上,都能基于全局统一的配额进行扣减,从而实现精准的跨实例限流控制。因此,整个系统的总流量会被严格控制在100请求/分钟,无论后端有多少个实例在运行。

    Envoy Gateway插件支持全局限流功能,开启该功能之后会自动部署一个限流服务,该服务负责集中管理并动态提供全局的限流策略与实时流量数据,并基于限流策略对传入的请求进行限流。

本文提供Global级别和Local级别不同场景的配置示例。更多关于限流策略的完整参数说明,请参见BackendTrafficPolicy

注意事项

关闭全局限流功能前需要确保当前全局限流策略已删除,否则会导致访问路由异常。具体操作步骤请参见如何关闭全局限流功能

前提条件

  • 当前集群已安装Envoy Gateway插件,并且插件状态为运行中。
  • 集群中已创建后端应用及对应的Service。
    本文中后端应用为Nginx,Service名称为backend,Service端口为3000。您可以将以下YAML内容保存为backend.yaml,然后执行kubectl apply -f backend.yaml命令。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: backend
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: backend
          version: v1
      template:
        metadata:
          labels:
            app: backend
            version: v1
        spec:
          containers:
            - name: container-1
              image: nginx:latest
          imagePullSecrets:
            - name: default-secret
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: backend
      labels:
        app: backend
        version: v1
      namespace: default
    spec:
      selector:
        app: backend
        version: v1
      ports:
        - name: cce-service-0
          targetPort: 80
          port: 3000
          protocol: TCP
      type: ClusterIP

创建Global级别的限流策略

Envoy Gateway的全局限流依赖Redis作为计数器,实现多个Envoy网关实例的实时流量精确汇总与超限拦截。本文采用自建Redis服务的方式。

步骤一:部署Redis

  1. 请参见通过kubectl连接集群,使用kubectl连接集群。
  2. 创建redis-service.yaml。

    kind: Namespace
    apiVersion: v1
    metadata:
      name: redis-system
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: redis
      namespace: redis-system
      labels:
        app: redis
    spec:
      serviceName: "redis"
      replicas: 1
      selector:
        matchLabels:
          app: redis
      template:
        metadata:
          labels:
            app: redis
        spec:
          containers:
            - image: redis:latest
              name: redis
              ports:
                - containerPort: 6379
              resources:
                limits:
                  cpu: 1500m
                  memory: 512Mi
                requests:
                  cpu: 200m
                  memory: 256Mi
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: redis
      namespace: redis-system
      labels:
        app: redis
    spec:
      ports:
        - name: redis
          port: 6379
          protocol: TCP
          targetPort: 6379
      selector:
        app: redis

  3. 部署Redis服务。

    kubectl apply -f redis-service.yaml

步骤二:开启插件全局限流功能

  1. 登录CCE控制台,单击集群名称进入集群。
  2. 在左侧导航栏中选择“插件中心”,在右侧找到Envoy Gateway插件,单击“编辑”
  3. 开启全局限流功能并配置Redis服务地址。

    本文使用集群内Redis地址:redis.redis-system.svc.cluster.local:6379

  4. 单击“确定”,完成插件升级。

步骤三:创建Gateway和HTTPRoute

创建Gateway和HTTPRoute资源,后续的限流规则将会应用到该路由规则上。

  1. 创建ratelimit.yaml。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: my-gateway              #Gateway名称
      namespace: default
    spec:
      gatewayClassName: envoy-gateway  #GatewayClass名称 
      listeners:
        - name: http                                     
          protocol: HTTP               #协议
          port: 80                     #监听端口
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute                #资源类型为HTTPRoute
    metadata:
      name: ratelimit                #HTTPRoute名称
      namespace: default
    spec:
      parentRefs:
        - name: my-gateway  #Gateway名称
      hostnames:
        - "www.example.com"    #域名
      rules:
        - backendRefs:
            - group: ""
              kind: Service
              name: backend       #已创建的service名称
              port: 3000          #service的端口
              weight: 1

  2. 部署Gateway和HTTPRoute资源。

    kubectl apply -f ratelimit.yaml

步骤四:创建限流策略(BackendTrafficPolicy)

  • 场景一:限制访问频率
  • 场景二:对指定用户进行限流
  • 场景三:对除某个用户外的其他用户进行限流
  • 场景四:根据客户端IP进行限流(仅CCE Turbo集群使用独享ELB场景支持)

创建Local级别的限流策略

Local级别的限流策略不依赖Redis,每个Envoy实例只能感知到达自身的流量,各自独立计数。

步骤一:创建Gateway和HTTPRoute

创建Gateway和HTTPRoute资源,后续的限流规则将会应用到该路由规则上。

  1. 创建ratelimit.yaml。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: my-gateway              #Gateway名称
      namespace: default
    spec:
      gatewayClassName: envoy-gateway  #GatewayClass名称 
      listeners:
        - name: http                                     
          protocol: HTTP               #协议
          port: 80                     #监听端口
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute                #资源类型为HTTPRoute
    metadata:
      name: ratelimit                #HTTPRoute名称
      namespace: default
    spec:
      parentRefs:
        - name: my-gateway  #Gateway名称
      hostnames:
        - "www.example.com"    #域名
      rules:
        - backendRefs:
            - group: ""
              kind: Service
              name: backend       #已创建的service名称
              port: 3000          #service的端口
              weight: 1

  2. 部署Gateway和HTTPRoute资源。

    kubectl apply -f ratelimit.yaml

步骤二:创建限流策略(BackendTrafficPolicy)

Local级别的限流策略支持的场景和Global级别一致,以限制访问频率为例,配置Local限流规则,限制请求为每分钟3次。

  1. 创建backendtrafficpolicy.yaml。

    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: BackendTrafficPolicy
    metadata:
      name: multiple-rules-example
      namespace: default
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: ratelimit  # 限流的HTTPRoute名称
      rateLimit:
        type: Local  # Local级别的限流策略
        local: # 此处与Global级别限流策略存在差异
          rules:
            # 限流规则:限制访问频率,每分钟3次
            - limit:
                requests: 3
                unit: Minute

  2. 部署限流规则。

    kubectl apply -f backendtrafficpolicy.yaml

  3. 修改Envoy实例个数。

    1. 登录CCE控制台,单击集群名称进入集群。
    2. 在左侧导航栏中选择“插件中心”,在右侧找到Envoy Gateway插件,单击“编辑”
    3. 修改envoy组件个数为2。

    4. 单击“确定”,完成插件升级。

  4. 测试请求限流情况。

    for i in {1..8}; do curl -I --header "Host: www.example.com"  http://xx.xx.xx.xx/ ; sleep 1; done

    预期输出如下:

    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:34 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 2
    x-ratelimit-reset: 0
    
    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:35 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 2
    x-ratelimit-reset: 0
    
    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:36 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 1
    x-ratelimit-reset: 0
    
    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:37 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 1
    x-ratelimit-reset: 0
    
    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:38 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 0
    x-ratelimit-reset: 15
    
    HTTP/1.1 200 OK
    server: nginx/1.23.2
    date: Sat, 30 May 2026 08:40:39 GMT
    content-type: text/html
    content-length: 615
    last-modified: Wed, 19 Oct 2022 07:56:21 GMT
    etag: "634fada5-267"
    accept-ranges: bytes
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 0
    x-ratelimit-reset: 15
    
    HTTP/1.1 429 Too Many Requests
    content-length: 18
    content-type: text/plain
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 0
    x-ratelimit-reset: 13
    date: Sat, 30 May 2026 08:40:40 GMT
    
    HTTP/1.1 429 Too Many Requests
    content-length: 18
    content-type: text/plain
    x-ratelimit-limit: 3
    x-ratelimit-remaining: 0
    x-ratelimit-reset: 13
    date: Sat, 30 May 2026 08:40:41 GMT

    前6次请求返回了200,第7、8次请求返回429,说明2个实例每个实例每分钟可以访问3次,一共6次,本地限流规则生效。

常见问题

如何关闭全局限流功能

关闭全局限流功能前需要确保当前全局限流策略已删除,或全部修改为本地级别的限流策略。具体操作步骤如下:

  1. 查询Global级别的限流策略。
    kubectl get backendtrafficpolicy -A -o jsonpath='{range .items[?(@.spec.rateLimit.type=="Global")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'
  2. 删除限流策略或修改成本地级别的限流策略。
    将限流策略修改为本地级别的示例如下:
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: BackendTrafficPolicy
    metadata:
      name: multiple-rules-example
      namespace: default
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: ratelimit 
      rateLimit:
        type: Global # 修改成Local
        global:      #修改成local
          rules: 
            - limit:
                requests: 3
                unit: Minute
  3. 重新执行步骤1,再次检查是否修改完成。

相关文档