Istio の EnvoyFilter で生の Envoy フィルターを構成する
Istio 自身の API が公開していない機能のために、EnvoyFilter は基盤となる Envoy の設定を直接パッチします。慎重に使います。
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 つの問いに答えます。
- どのプロキシに適用されるか。
workloadSelectorはラベルで特定のワークロードを対象にします。省略すると、その namespace 内全体に適用され、Istio のルート/設定 namespace に置くとメッシュ全体に適用されます。 - Envoy 設定のどこにパッチを適用するか。
applyToフィールドが対象を指定します。LISTENER、FILTER_CHAIN、HTTP_FILTER、NETWORK_FILTER、CLUSTER、ROUTE_CONFIGURATION、そしていくつかの他のものです。 - より具体的には、そのどのインスタンスか。
matchブロックがさらに絞り込みます。たとえば、特定のリスナーポート、特定のフィルターチェーン、あるいはサイドカーのインバウンド、サイドカーのアウトバウンド、ゲートウェイのどれに適用されるかです。 - どの操作を、どの内容で行うか。
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 のアップグレードのたびにテストするものです。トラフィックを構成するデフォルトの方法ではありません。