EnvoyFilter によるデータプレーンの拡張性

EnvoyFilter API を使用すると、他の Istio API では実現できない Cloud Service Mesh のデータプレーン機能を拡張できます。EnvoyFilter API を使用すると、ワークロードに適用される他のポリシーから生成された Envoy 構成をカスタマイズできます。たとえば、HTTP フィルタチェーンにフィルタを追加できます。

重要な考慮事項

  • API サーフェスは内部実装の詳細に関連付けられているため、この機能を使用する場合は注意が必要です。構成が正しくないと、メッシュが不安定になる可能性があります。他の Istio API がニーズに合わない場合にのみ、EnvoyFilter API を使用してください。
  • EnvoyFilter API は、信頼性とサポートの目的で、使用できるフィールドと拡張機能に特定の制限があります。 EnvoyFilter API でサポートされている機能の完全なリストについては、 Istio API を使用する場合のサポートされている機能(マネージド コントロール プレーン)をご覧ください。
  • Google が提供するサポートの範囲は、ユーザーが指定した構成を Envoy サイドカーを持つワークロードに伝播することに限定されており、拡張機能ごとの API を使用して指定された構成の正確さには及びません。

サポートされている API フィールド

EnvoyFilter API は、TRAFFIC_DIRECTOR コントロール プレーンの実装でのみサポートされており、次のようにサポートは限定的 です。

  • targetRefs: サポートされていません
  • configPatches[].applyTo : HTTP_FILTER のみがサポートされています
  • configPatches[].patch.operation: ルートフィルタで使用する場合、INSERT_FIRSTINSERT_BEFORE のみがサポートされます。
  • configPatches[].patch.value.type_url: [Supported Extensions]
  • 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

フィールド Rapid 標準 Stable
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

フィールド Rapid 標準 Stable
(フィールドなし)

type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor

フィールド Rapid 標準 Stable
compressor_library
choose_first
response_direction_config.common_config.min_content_length
response_direction_config.common_config.content_type
response_direction_config.common_config.enabled
response_direction_config.disable_on_etag_header
response_direction_config.remove_accept_encoding_header
response_direction_config.uncompressible_response_codes
request_direction_config.common_config.min_content_length
request_direction_config.common_config.content_type
request_direction_config.common_config.enabled

EnvoyFilter コンプレッサ構成を 完全にサポートされるように更新する方法については、EnvoyFilter コンプレッサ 構成を最新化するをご覧ください。

type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua

フィールド Rapid 標準 Stable
stat_prefix
default_source_code.inline_string

インライン Lua スクリプトに関する重要な考慮事項と制限事項:

  • セキュリティと安定性を確保するため、Lua 機能と Envoy Lua ラッパーのサブセットのみが許可されます。サポートされていない機能を使用したり、ドキュメントに記載されている上限を超えたりすると、EnvoyFilter が拒否されます。
  • 複雑な Lua スクリプトはパフォーマンスに影響する可能性があります。スクリプトのリソース使用量を十分にテストしてください。

サポートされていない Lua 機能:
次の Lua 機能と Envoy 提供の Lua ラッパーは対象外です。

  • Envoy ラッパー:
    • httpCall
    • filterContext
  • Lua 標準ライブラリ:
    • 基本パッケージ: collectgarbagedofilegetmetatableloadfilerawsetsetfenvsetmetatable
    • モジュール: module
    • OS パッケージ: executeremoverenamesetlocale
    • I/O ライブラリとデバッグ ライブラリ: iodebug
  • LuaJIT 拡張機能: ffijit

スクリプトのサイズと数の上限:

  • 個々のスクリプト サイズ: default_source_code.inline_string で提供される単一の Lua インライン スクリプトは、50 KB を超えることはできません。
  • スクリプトの合計サイズ: 単一クラスタ内のすべての EnvoyFilter リソースのすべての Lua スクリプトの合計サイズは、100 KB を超えることはできません。
  • パッチ数: 単一クラスタ内のすべての EnvoyFilter リソースの Lua EnvoyFilter configPatches の合計数は、10 に制限されています。

使用例

このチュートリアルでは、Envoy の組み込みローカル レート制限を使用して、EnvoyFilter API を使用してサービスへのトラフィックを動的に制限する方法について説明します。

費用

このチュートリアルでは、課金対象である次の Google Cloudコンポーネントを使用します。

このチュートリアルの終了後に作成したリソースを削除すれば、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

Ingress ゲートウェイをデプロイする

  1. kubectl の現在のコンテキストをクラスタに設定します。

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. Ingress ゲートウェイの名前空間を作成します。

    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. Envoy プロキシを自動的に挿入するには、onlineboutique 名前空間にラベルを付けます。

    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 のショップが表示されます。

    オンライン ショップのフロントエンド

レート制限構成を適用する

このセクションでは、EnvoyFilter リソースを適用して、frontend サービスへのすべてのトラフィックを 5 リクエスト/分に制限します。

  1. frontend サービスに CR を適用します。

    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. Ingress ゲートウェイの名前空間を削除します。

      kubectl delete namespace asm-ingress
      

      予想される出力:

      namespace "asm-ingress" deleted
      
  • 追加料金の発生を回避するには、クラスタを削除します。

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

トラブルシューティング

データプレーンの拡張性の問題を解決するをご覧ください。