使用 EnvoyFilter 实现数据平面可扩展性

您可以使用 EnvoyFilter API 扩展 Cloud Service Mesh 中的数据平面功能,而这些功能无法通过使用其他 Istio API 实现。借助 EnvoyFilter API,您可以自定义从应用于工作负载的其他政策生成的 Envoy 配置,例如向 HTTP 过滤条件链添加过滤条件。

重要注意事项

  • 请注意,API 表面与内部实现细节相关联,因此在使用此功能时必须格外小心,因为配置不正确可能会导致网格不稳定。只有在其他 Istio API 不符合您的需求时,才使用 EnvoyFilter API。
  • EnvoyFilter API 受支持,但对哪些字段和扩展程序可用于可靠性和可支持性目的有特定限制。如需查看 EnvoyFilter API 中支持的功能的 完整列表,请参阅 使用 Istio API 支持的功能(托管式控制平面)
  • Google 提供的支持范围仅限于将用户提供的配置传播到具有 Envoy Sidecar 的工作负载,不包括使用每个扩展程序 API 指定的配置的正确性。

支持的 API 字段

EnvoyFilter API 仅在 TRAFFIC_DIRECTOR 控制平面实现中受支持,并且仅提供有限 支持,如下所示:

  • targetRefs:不支持
  • configPatches[].applyTo:仅支持 HTTP_FILTER
  • configPatches[].patch.operation:仅在使用路由过滤条件时支持 INSERT_FIRSTINSERT_BEFORE
  • configPatches[].patch.value.type_url:请参阅支持的扩展程序
  • configPatches[].patch.filterClass:不支持
  • configPatches[].match.proxy:不支持
  • configPatches[].match.routeConfiguration:不支持
  • configPatches[].match.cluster:不支持
  • 以下字段仅支持 INSERT_BEFORE 操作:
    • configPatches[].match.listener:仅支持 filter
    • configPatches[].match.listener.filter.name:仅支持 envoy.filters.network.http_connection_manager
    • configPatches[].match.listener.filter.subFilter.name:仅支持 envoy.filters.http.router

支持的扩展程序

以下是支持的扩展程序列表,以及它们在各种 发布渠道中支持的 API 字段。 如需了解 API 定义及其语义,请参阅 官方 Envoy 文档

type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit

字段 快速 常规 稳定版
stat_prefix
status
token_bucket
filter_enabled
filter_enforced
response_headers_to_add
request_headers_to_add_when_not_enforced
local_rate_limit_per_downstream_connection
enable_x_ratelimit_headers

type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb

字段 快速 常规 稳定版
(无字段)

用法示例

在本教程中,您将学习如何使用 Envoy 的内置本地速率限制功能,通过 EnvoyFilter API 动态限制服务的流量。

费用

本教程使用 Google Cloud的以下收费组件:

完成本教程后,您可以删除所创建的资源以避免持续产生费用。如需了解详情,请参阅清理

准备工作

  • 确保您的项目已启用结算功能。
  • 在 GKE 集群上配置 Cloud Service Mesh
  • 克隆代码库:

      git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
      cd anthos-service-mesh-samples
    

部署入站流量网关

  1. kubectl 的当前上下文设置为相应集群:

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. 为入站流量网关创建命名空间:

    kubectl create namespace asm-ingress
    
  3. 启用用于注入的命名空间。具体步骤取决于您的控制平面实现

    将默认注入标签应用于命名空间:

    kubectl label namespace asm-ingress \
        istio.io/rev- istio-injection=enabled --overwrite
    
  4. anthos-service-mesh-samples 代码库中部署示例网关:

    kubectl apply -n asm-ingress \
        -f docs/shared/asm-ingress-gateway
    

    预期输出:

    serviceaccount/asm-ingressgateway configured
    service/asm-ingressgateway configured
    deployment.apps/asm-ingressgateway configured
    gateway.networking.istio.io/asm-ingressgateway configured
    

部署 Online Boutique 示例应用

  1. kubectl 的当前上下文设置为相应集群(如果尚未设置):

    gcloud container clusters get-credentials CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    
  2. 为示例应用创建命名空间:

    kubectl create namespace onlineboutique
    
  3. onlineboutique 命名空间添加标签以自动注入 Envoy 代理:

    kubectl label namespace onlineboutique \
       istio.io/rev- istio-injection=enabled --overwrite
    
  4. 部署示例应用、前端的 VirtualService 以及工作负载的服务账号。在本教程中,您将部署 Online Boutique,这是一个微服务演示版应用。

    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/virtual-service.yaml
    
    kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/service-accounts
    

查看服务

  1. 查看 onlineboutique 命名空间中的 Pod:

    kubectl get pods -n onlineboutique
    

    预期输出:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    应用的所有 Pod 都应启动并运行,READY 列中应显示 2/2。这表示 Pod 已成功注入 Envoy 边车代理。 如果几分钟后没有显示 2/2,请查看问题排查指南

  2. 获取外部 IP 并将其设置为变量:

    kubectl get services -n asm-ingress
    export FRONTEND_IP=$(kubectl --namespace asm-ingress \
    get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
    )
    

    您将看到类似如下所示的输出:

    NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
    asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
    
    
  3. 在网络浏览器中访问 EXTERNAL-IP 地址。您应该会在浏览器中看到 Online Boutique 商店。

    Online Boutique 前端

应用速率限制配置

本部分应用 EnvoyFilter 资源,将对 frontend 服务的所有流量限制为 5 个请求/分钟。

  1. 将 CR 应用于 frontend 服务:

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: frontend-local-ratelimit
      namespace: onlineboutique
    spec:
      workloadSelector:
        labels:
          app: frontend
      configPatches:
        - applyTo: HTTP_FILTER
          match:
            context: SIDECAR_INBOUND
            listener:
              filterChain:
                filter:
                  name: "envoy.filters.network.http_connection_manager"
                  subFilter:
                    name: "envoy.filters.http.router"
          patch:
            operation: INSERT_BEFORE
            value:
              name: envoy.filters.http.local_ratelimit
              typed_config:
                "@type": type.googleapis.com/udpa.type.v1.TypedStruct
                type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
                value:
                  stat_prefix: http_local_rate_limiter
                  token_bucket:
                    max_tokens: 5
                    tokens_per_fill: 5
                    fill_interval: 60s
                  filter_enabled:
                    runtime_key: local_rate_limit_enabled
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
                  filter_enforced:
                    runtime_key: local_rate_limit_enforced
                    default_value:
                      numerator: 100
                      denominator: HUNDRED
    EOF
    

    预期输出:

    envoyfilter.networking.istio.io/frontend-local-ratelimit created
    
  2. 验证 CR 状态是否报告任何错误:

    kubectl get envoyfilter -n onlineboutique frontend-local-ratelimit -o yaml
    

    预期输出:

    ...
    status:
      conditions:
      - lastTransitionTime: "2025-06-30T14:29:25.467017594Z"
        message: This resource has been accepted. This does not mean it has been propagated
          to all proxies yet
        reason: Accepted
        status: "True"
        type: Accepted
    
  3. 移除 loadgenerator 部署,因为它会多次调用服务,从而消耗令牌:

    kubectl delete -n onlineboutique deployment loadgenerator
    

    预期输出:

    deployment.apps/loadgenerator deleted
    
  4. 使用 curl 验证在 60 秒内允许的请求数不超过 5 个。429 代码表示正在强制执行速率限制。

    for i in {1..10}; do curl -s http://${FRONTEND_IP} -o /dev/null -w "%{http_code}\n"; sleep 1; done
    

    预期输出:

    200
    200
    200
    200
    200
    429
    429
    429
    429
    429
    

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号继续产生费用,您可以删除项目或删除各个资源。

删除项目

在 Cloud Shell 中,删除项目:

  gcloud projects delete PROJECT_ID

删除资源

  • 如果您希望保留集群并移除 Online Boutique 示例,请执行以下操作:

    1. 删除应用命名空间:

      kubectl delete namespace onlineboutique
      

      预期输出:

      namespace "onlineboutique" deleted
      
    2. 删除入站流量网关命名空间:

      kubectl delete namespace asm-ingress
      

      预期输出:

      namespace "asm-ingress" deleted
      
  • 如果您想防止产生额外费用,请删除集群:

    gcloud container clusters delete CLUSTER_NAME  \
      --project=PROJECT_ID \
      --zone=CLUSTER_LOCATION 
    

问题排查

请参阅解决数据平面可扩展性问题