サービス メッシュ 102: Envoy のコンフィギュレーションについて

前回お届けした記事「サービス メッシュ 101」では、サービス メッシュとは何か、何をするものなのか、そして Envoy はサービス メッシュの中でどこに位置するのかといった、サービス メッシュの基本的な部分についてお話ししました。今回は、サービス メッシュにおける Envoy のコンフィギュレーションの基本を中心に、より詳細な内容を紹介したいと思います。

前回の記事で、いくつかの異なるサービス メッシュが Envoy を使用していることをお伝えしました。Istio は、データ プレーンに Envoy を採用しているサービス メッシュの一例です。Kong のオープン ソース プロジェクトである Kuma と、そのエンタープライズ版である Kong Mesh も、そのデータ プレーンに Envoy を使用しています。

Envoy のコンフィギュレーションにおける主要パート

Envoy は、動的コンフィギュレーション、複数のロード バランシング アルゴリズム、広範なプロトコル サポート、リトライ、サーキット ブレーカー、レート制限など、さまざまな機能をサポートしているため、その設定は複雑になることがあります。Envoy のコンフィギュレーションを最も簡単に行う方法は、コア コンポーネントに分解することです。

まずは、リスナーから始まります。

リスナーは、単に Envoy がトラフィックを受信するための手段です。リスナーは、IP アドレスとポートに関連付けられています。IP アドレスはゼロの場合もあり、それはつまり、そのポートにある IP アドレスへのトラフィックは、リスナーによってキャプチャされ、Envoy の残りの部分をパススルーして最終目的地に到達していることを意味します。

すべてのリスナーには、関連する一連のフィルターがあります。フィルターは Envoy にとってのプラグインのようなもので、Envoy がどのようにトラフィックを処理するかを決定します。使用されるフィルターに応じて、Envoy はレイヤー 4 プロキシとして動作したり (アプリケーションの認識/知識なし)、レイヤー 7 プロキシとして動作したり (アプリケーション/プロトコルの認識あり) します。

下の図は、Envoy がレイヤー 4 プロキシとして動作する TCP プロキシ フィルターを使用している様子を示しています。Envoy は、どのような種類のトラフィックであるか、またはトラフィックが何をしているかについて、ハイレベルなアプリケーション知識を持ちません。

図1: TCP プロキシ フィルターを使用したリスナー

レイヤー 4 プロキシとして動作している場合、つまり、上位のアプリケーションプロトコルをデコードせずに TCP または UDP トラフィックをプロキシするだけの場合、フィルターをパススルーしたトラフィックは、次にクラスターに誘導されます。

クラスターは、Envoy が受信したトラフィックの送信先に相当します。

しかし、その送信先には、複数の仮想マシン (VM) や複数のコンテナーなど、複数のシステムが含まれている可能性があり、Envoy はクラスター内のシステムにトラフィックをロード バランスする必要があります。このため、Envoy は各クラスター内のエンドポイントのリストを管理します。すべてのクラスターには、1 つまたは複数のエンドポイントがあります (1 つのクラスターには、単一のエンドポイントがある場合と、数十のエンドポイントがある場合があります)。また、クラスターは、クラスター内のエンドポイントへのロード バランスの方法を Envoy に正確に指示するロード バランシング構成を持っています。

Envoy がレイヤー 7 のプロキシとして動作する場合 (HTTP/1.1 やHTTP/2 などの高レベルのアプリケーション プロトコルをデコードする場合)、フローは若干異なります。HTTP トラフィックの場合、ルートという新たなコンポーネントが登場します。

図2: HTTP トラフィックをプロキシする際のコンポーネント

この場合、Envoy はハイレベルのアプリケーション知識を持っています。Envoy が HTTP トラフィックをデコードしているため、リクエストされたホスト、リクエスト ヘッダー、パス、送信されたクエリ パラメーターなどを把握しています。これらの情報に基づいた決定を行うことができます。ここで登場するのがルートです。ルートは、異なるホスト名やパスにトラフィックを誘導する際に、Envoy が下す決定を定義します。つまり、Envoy はリクエストされたホスト名や URL パスに基づいて、トラフィックをクラスターに向けることができるのです。

要約すると、一般的なトラフィックの流れは次のようになります。

  1. まず、1 つまたは複数のフィルターが、リスナーを介して入ってくるトラフィックを操作します。
  2. フィルターにアプリケーション レベルのフィルターが含まれている場合、Envoy はプロトコルをデコードしてクラスターを決定します。HTTP ベースのトラフィックの場合は、一連のルートを見て、どこに行くべきか (どのクラスターがトラフィックを受信するべきか) を決定します。
  3. トラフィックは、クラスター内のエンドポイントに誘導されます。複数のエンドポイントが存在する場合は、クラスターのロード バランシング設定に従ってトラフィックがロード バランスされます。

API を介した Envoy の動的コンフィギュレーション

Envoy はこれらの情報をどこで得るのでしょうか?リスナーや、ルート、クラスター、エンドポイントなどの情報はどこから得られるのでしょうか?これらの情報はすべて、サービス メッシュのコントロール プレーンから得られます。前回の記事で、コントロール プレーンの役割は、Kubernetes などの他のシステムと統合し、メッシュ上で利用可能なサービスに関する情報を収集することだと説明しました。

トラフィックのルーティングやレート制限などの機能を左右するポリシーの影響を受けて、コントロール プレーンが収集した情報は、リスナー、フィルター、ルート、クラスター、エンドポイントといった Envoy が理解できる形状に変換する必要があります。いわゆる Envoy の「言語」に変換された後は、ワークロードの前に置かれた個々のデータ プレーン (Envoy のインスタンス) に渡されなければなりません。コントロール プレーンは、Envoy が公開している xDS API と呼ばれる API を通じてこれを行います。

DSとは “Discovery Service” の略です。xDS の “x” は変数のようなものです。「x ディスカバリー サービス」といった感じで、リスナーやクラスター、ルート、エンドポイント (またその他多数のオプション) が “x” に置き換えられると考えるとよいでしょう。実際、Envoy のあらゆる主要コンポーネントと主要なコンフィギュレーション オプションには、xDS API に対応するディスカバリー サービスが用意されています。

また、ADS (Aggregated Discovery Service) により、コントロール プレーンはこれらの情報を 1 つの大きな流れに乗せることができます。ADS は、大きな水源だとイメージするとよいでしょう。Envoy は、さまざまな場所から少しずつ情報を得るのではなく、1 つのストリームですべての設定を得ることができます。

Envoy を使った実例

サービス メッシュにおける Envoy のコンフィギュレーションの概要は参考になりましたでしょうか?以下の動画 (英語) では、サービス メッシュ内での Envoy の設定方法について、4 つの実用的な例を紹介しています。デモでは、クラスター API を使用して AWS 上でプロビジョニングされた Kubernetes 1.20.7 を使用しています。これらのクラスターは Kuma サービス メッシュを実行しており、kumactl install control-plane のコマンドを使用してインストールしました。次にデモ アプリをデプロイします。このアプリは 2 つのセクション (フロントとバッ クエンド) を持つシンプルなアプリです。また、エコー サービスと呼ばれる 3 つ目のサービスを追加して、Envoy 構成に変換されたサービス メッシュ ポリシーのデモを行います。


Kong Enterprise の概要、価格、およびライセンス体系などの詳細は、こちらを参照してください。


記事参照: 2021 年 9 月 2 日
Scott Lowe 
© Kong Inc. 2021
Service Mesh 102: Envoy Configuration