Envoy Envoy

HTTP Connection Manager と HTTP フィルターチェーン

Envoy が生のバイトを、処理可能な HTTP リクエストに変える仕組みと、そのパイプラインに独自のロジックを組み込む方法。

10 min learn.level.中級

Envoy で日常的に設定することの大半、つまりヘッダー操作、アクセスログ、リトライ、外部認可は、特定の 1 つのネットワークフィルター、HTTP Connection Manager の中で行われます。このガイドでは、それが何をするのか、独自のフィルターチェーンがどう構成されているのか、そして組み込まれていないロジックで拡張する方法を説明します。

HCM:バイトから HTTP へ

リスナーのフィルターチェーンは、ネットワークレベルから始まり、「リクエスト」という概念がまだない、生のバイトストリームに対して動作します。HTTP Connection Manager(HCM) は、それを変えるネットワークフィルターです。バイトストリームを HTTP のリクエスト、ヘッダー、ボディ、トレーラーにパースし、その時点から、チェーンでそれより後ろにあるすべてのものが、生のバイトではなく HTTP のセマンティクスで動作できます。

リクエストレベルの機能も、ここにあります。アクセスログ、リクエストとレスポンスの操作、そして重要なこととして、HCM 自身の入れ子になった HTTP フィルターのチェーンです。これは、それが収まっているネットワークレベルのフィルターチェーンとは別の概念です。

HTTP フィルターチェーン

HCM の内部では、HTTP フィルターが、各 HTTP リクエストに対して定義された順序で実行されます。CORS の処理、レート制限、外部認可(リクエストを許可するかを決めるための別サービスへの呼び出し)、Lua スクリプティング、WebAssembly(Wasm)モジュールなどです。チェーンの最後のフィルターは通常、終端フィルターで、ほぼ常に router フィルターです。その役割は、リクエストをルートのマッチングに、そしてそこからクラスターに引き渡すことです。

順序は重要です。認証フィルターの前に置かれたレート制限フィルターは、後に置かれたものとは動作が異なります。フィルターチェーンに対する Envoy の設定は、どのフィルターが存在するかだけでなく、各フィルターが他に対してどこに位置するかも明示します。

Envoy を拡張する:選択肢

Envoy の組み込みフィルターのどれも必要なことをしてくれない場合、独自のロジックを追加する方法がいくつかあり、それぞれコストと到達範囲が異なります。

  • ネイティブの C++ フィルターは、カスタム Envoy ビルドに直接コンパイルされます。最も高機能ですが、最も手間がかかります。アップストリームのビルドを使うのではなく、独自の Envoy ビルドを維持することを意味します。Istio 自身の Envoy ディストリビューションは、組み込みの動作の一部にこの方法をとっています。
  • 外部処理(ext_proc) では、Envoy がリクエストの途中で別のサービスを呼び出し、そのサービスが必要な処理を行って、制御をフィルターチェーンに戻します。カスタムロジックを Envoy 自身のプロセスの完全に外に置けますが、リクエストごとにネットワークの往復が発生します。
  • Lua スクリプティングでは、Lua フィルターが、リクエストやレスポンスに対して埋め込みスクリプトを実行します。再ビルドも別サービスも不要で、素早く書いて反復できますが、Lua と Envoy の Lua API が公開している範囲に限られます。
  • WebAssembly(Wasm) では、選んだ言語でフィルターを .wasm モジュールにコンパイルし、Envoy がそれをチェーンの一部としてロードして実行します。スクリプトやカスタムビルドではなく、ポータブルな成果物としてフィルターを配布して再利用することに最も向いた拡張の仕組みです。

どれが適しているかは、どれだけの制御が必要か、運用上の負担をどこまで引き受けられるかによります。Lua スクリプトは何かを試す最速の方法であることが多く、Wasm モジュールは動作が確認できたものを出荷する、よりポータブルな方法です。カスタムの C++ ビルドや外部サービスは、そのどちらでも必要なことができないときに残る選択肢です。

フィルターを設定するために実際に必要なもの

どの拡張の仕組みを使うにしても、HTTP フィルターの設定は常に 3 つのことに行き着きます。

  1. フィルターの名前。安定した識別子です。
  2. その type URL。これは、Envoy の設定システムに、これがどの種類のフィルターか、その設定がどのような形かを正確に伝えます。
  3. フィルター固有の設定そのもの。そのフィルターが実際に受け付けるフィールドです。

各フィルターに対する Envoy 自身のドキュメントのページには、その type URL と設定フィールドが記載されていますが、あるフィルターのドキュメントは、1 か所にまとまっているのではなく、リンクされた複数のリファレンスページに分散していることがよくあります。特定のフィールドの正確な構文を見つけるには、上から下へ読むよりも、リンクの連鎖をたどることが頻繁に必要になります。type URL が分かったら、公開されているコードホスティングで検索するのも実用的な近道です。ある程度一般的なものであれば、リファレンスのドキュメントだけから組み立てるのではなく、そこから出発できる動作する設定を、すでに誰かが公開しているのが普通です。

サービスメッシュを使っている場合、これはどこに現れるか

Envoy が Istio や同様のメッシュの下でサイドカーとして動作している場合、一般的なケースで生の HTTP フィルター設定を手作業で書くことはまれです。メッシュ自身の API(ルーティングルール、セキュリティポリシー)が生成してくれます。しかし、メッシュの高レベル API がカバーしていないこと、そして必ず何かはカバーされていないのですが、そのためには、メッシュが提供するより低レベルの脱出口を通じて、HTTP フィルターを直接設定することになります。このシリーズの次のガイドは、まさにそれを、Istio の EnvoyFilter リソースを例に取り上げて説明します。

人気のガイド