Envoy Envoy

Istio の EnvoyFilter で生の Envoy フィルターを構成する

Istio 自身の API が公開していない機能のために、EnvoyFilter は基盤となる Envoy の設定を直接パッチします。慎重に使います。

14 min learn.level.上級

Istio の高レベルなリソース、VirtualService、DestinationRule、AuthorizationPolicy は、Envoy の設定形式を直接知らなくても、日常的なトラフィック管理のほとんどをカバーします。しかし、Envoy にはこれらのリソースが公開しているよりはるかに多くのフィルターとオプションがあり、そのギャップのために Istio は EnvoyFilter を提供しています。これは、Istio が生成する Envoy の設定を直接パッチするリソースです。本物の脱出口であり、強力であると同時に、設定を誤りやすいものでもあります。このガイドでは、その構造を、完全な動作例とともに説明します。

EnvoyFilter の用途

必要なことに専用の Istio リソース(ルーティングルール、リトライポリシー、相互 TLS の設定)がある場合は、代わりにそのリソースを使ってください。EnvoyFilter は、それ以外のすべてのためにあります。Lua スクリプティング、リクエストのタッピング、IP タギングなどのフィルターや、Istio の高レベル API にフィールドがない Envoy のその他の機能です。必要なことが通常のリソースでは本当に表現できないと確認してから使ってください。追加する EnvoyFilter は 1 つ増えるごとに、Istio が生成する設定がアップグレードのたびに進化していくのと同期を保つ、保守対象が 1 つ増えることになるからです。

すべての EnvoyFilter が答える 4 つの問い

あらゆる EnvoyFilter リソースは、何を設定するものであっても、同じ 4 つの問いに答えます。

  1. どのプロキシに適用されるか。 workloadSelector はラベルで特定のワークロードを対象にします。省略すると、その namespace 内全体に適用され、Istio のルート/設定 namespace に置くとメッシュ全体に適用されます。
  2. Envoy 設定のどこにパッチを適用するか。 applyTo フィールドが対象を指定します。LISTENER、FILTER_CHAIN、HTTP_FILTER、NETWORK_FILTER、CLUSTER、ROUTE_CONFIGURATION、そしていくつかの他のものです。
  3. より具体的には、そのどのインスタンスか。 match ブロックがさらに絞り込みます。たとえば、特定のリスナーポート、特定のフィルターチェーン、あるいはサイドカーのインバウンド、サイドカーのアウトバウンド、ゲートウェイのどれに適用されるかです。
  4. どの操作を、どの内容で行うか。 patch ブロックは、操作(ADD、REMOVE、MERGE、INSERT_BEFORE、INSERT_AFTER、INSERT_FIRST)と、設定を挿入またはマージするものについては、value としての実際のフィルター設定の両方を指定します。

順序に依存する変更(チェーン内の特定の位置への HTTP フィルターの挿入)には INSERT_* 操作を使い、名前付きの隣接要素、通常は終端の envoy.filters.http.router フィルターを指して、「これの前」または「これの後」を指定します。

完全な例:IP によるリクエストのタグ付け

これは、ポート 80 のサイドカーのインバウンドトラフィックに ip_tagging HTTP フィルターを追加し、終端の router フィルターの直前に挿入します。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: ip-tagging
  namespace: default
spec:
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          portNumber: 80
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
              subFilter:
                name: envoy.filters.http.router
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.ip_tagging
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging
            request_type: BOTH
            ip_tags:
              - ip_tag_name: hello-envoy-conf
                ip_list:
                  - address_prefix: "0.0.0.0"
                    prefix_len: 0

上から下へ読みます。workloadSelector がないので、これは default namespace 内のすべてのワークロードに適用されます。applyTo: HTTP_FILTER は HTTP フィルターを追加することを示します。match ブロックは、これをポート 80 にバインドされたリスナー上のサイドカーのインバウンドトラフィックに絞り込みます。具体的には HTTP Connection Manager のフィルターチェーン内で、router フィルターを基準に位置を決めています。patch は、その router の前に新しいフィルターを挿入すると指定し、フィルターの名前、type URL(@type)、フィルター固有のフィールドという完全な設定を与えます。ここでは、送信元 IP に関係なく(0.0.0.0/0 はすべてに一致)、すべてのリクエストに X-Envoy-IP-Tags: hello-envoy-conf を付与します。

適用して確認します。

kubectl apply -f ip-tagging-filter.yaml
kubectl exec deploy/httpbin -c istio-proxy -- curl -s -D - http://localhost:80/get -o /dev/null | grep -i x-envoy-ip-tags

フィルターの名前、type URL、フィールドを見つける

name、typed_config の @type、その下のフィールドは、フィルターごとに固有のものであり、それらの出典は Envoy 自身のフィルターのドキュメントです。ただし、1 か所にまとまっているのではなく、リンクされた複数のページに分散しています。フィルターの概要ページは通常、その protobuf リファレンスにリンクしており、そこで各フィールドが定義され、入れ子になった型にはさらにリンクがあることもよくあります。かなりのタブの切り替えを覚悟してください。いくつか、作業を速くする方法があります。

  • type URL が分かったら、GitHub で検索します。ある程度一般的なフィルターなら、それを使って動作する EnvoyFilter や生の Envoy 設定を、すでに誰かが公開している可能性が高く、フィールドのリファレンスだけから組み立てるよりも、たいていは早い出発点になります。
  • すべての Envoy フィルターが Istio のプロキシビルドにコンパイルされているわけではありません。 Istio は特定の Envoy ビルドを配布しており、envoyproxy.io で文書化されているフィルターが、そこに含まれている保証はありません。フィルターを前提に解決策を設計する前に、Istio のビルドで実際に利用可能かを確認してください。
  • YAML のインデントが深くネストした設定で間違いやすいと感じるなら、value ブロックには YAML ではなく JSON を使ってください。Envoy の設定はどちらも受け付けます。ネストした YAML ブロックのインデントのずれは、EnvoyFilter が意図どおりに動作せずに黙って失敗する最も一般的な原因の 1 つです。

実際に動作しているものを確認する

パッチが期待どおりに反映されたかを、動作から推測するだけでなく確認するのに役立つツールが 2 つあります。

istioctl proxy-config listener POD_NAME -n NAMESPACE
istioctl proxy-config route POD_NAME -n NAMESPACE
istioctl proxy-config cluster POD_NAME -n NAMESPACE
istioctl proxy-config all POD_NAME -n NAMESPACE -o json

istioctl proxy-config に bootstrap、clusters、routes、listeners、all を続けると、特定のサイドカーの実際の設定が、Istio と Envoy によって組み立てられたとおりに、デフォルトでは表形式で、-o を付けると YAML/JSON で出力されます。パッチを当てようとしたものではなく、実際に動作しているものの確かな情報です。完全な設定ダンプを視覚的に比較する場合、Envoy の完全な設定は、ターミナルで直接読むには長すぎるので、閲覧可能な相互リンク付きの構造として表示する設定ダンプビューア(Envoy コミュニティがいくつか保守しています)のほうが、生の JSON をスクロールするより読み進めやすいことがよくあります。

中心となる注意点

EnvoyFilter は、Istio 自身が生成し、変更のたびに再生成する設定にパッチを当てます。つまり、高レベルのリソースにはない形で、Istio の内部と本質的に結合しています。ある Istio バージョン向けに書かれた EnvoyFilter は、アップグレードで Istio が生成するリスナーやフィルターチェーンの構造が変わると、何にも一致しなくなったり、意図しないものに一致したりして、黙って機能しなくなる可能性があります。名前が示すとおりに扱ってください。特定の、確認済みのギャップのための精密なツールであり、Istio のアップグレードのたびにテストするものです。トラフィックを構成するデフォルトの方法ではありません。

人気のガイド