Envoy: サービスディスカバリ

# tldr
勉強がてらにEnvoyのドキュメントを邦訳してみました。ベースはGoogle Translateで、ところどころ不自然な箇所を直しています。

原文としたのEnvoyのドキュメントは[こちらのディレクトリ以下](https://github.com/envoyproxy/envoy/tree/master/docs)にあります（ライセンス：[Apache License 2.0](https://github.com/envoyproxy/envoy/blob/master/LICENSE), [NOTICE](https://github.com/envoyproxy/envoy/blob/master/NOTICE)）。


## サービスディスカバリ

アップストリームクラスターが構成で定義されている場合、Envoyはクラスターのメンバーを解決する方法を知る必要があります。これはサービスディスカバリとして知られています。

### サポートされているサービスディスカバリタイプ

#### 静的

静的は最も単純なサービス検出タイプです。設定は各上流ホストの解決されたネットワーク名（IPアドレス/ポート、UNIXドメインソケットなど）を明示的に指定します。

#### 厳密なDNS

厳密なDNSサービス検出を使用している場合、Envoyは指定されたDNSターゲットを継続的かつ非同期的に解決します。 DNS結果に返された各IPアドレスは、アップストリームクラスタ内の明示的なホストと見なされます。つまり、クエリが3つのIPアドレスを返す場合、Envoyはクラスタに3つのホストがあり、3つすべてが負荷分散されるべきであると見なします。結果からホストが削除された場合、Envoyはそのホストがもう存在していないとみなし、既存の接続プールからトラフィックを排出します。 Envoyが転送パス内のDNSを同期的に解決することは決してないことに注意してください。最終的な一貫性を犠牲にして、長時間実行されているDNSクエリをブロックする心配はありません。

単一のDNS名が同じIPに複数回解決されると、これらのIPは重複排除されます。

複数のDNS名が同じIPに解決されると、ヘルスチェックは共有されません。つまり、同じIPに解決されるDNS名でアクティブヘルスチェックを使用する場合は注意が必要です。DNS名間でIPが何度も繰り返されると、アップストリームホストに過度の負荷がかかる可能性があります。

#### 論理DNS

論理DNSは、厳密DNSに似た非同期解決メカニズムを使用します。ただし、厳密にDNSクエリの結果を取得し、それらがアップストリームクラスタ全体を構成すると仮定するのではなく、論理DNSクラスタは、新しい接続を開始する必要があるときに返される最初のIPアドレスのみを使用します。したがって、単一の論理接続プールには、さまざまなアップストリームホストへの物理接続が含まれることがあります。接続は排水されません。このサービス検出タイプは、DNSを介してアクセスする必要がある大規模Webサービスに最適です。このようなサービスは通常、ラウンドロビンDNSを使用してさまざまなIPアドレスを返します。通常、クエリごとに異なる結果が返されます。このシナリオで厳密なDNSが使用されている場合、Envoyは解決間隔ごとにクラスタのメンバが変化していると想定し、接続プールの枯渇、接続の循環などを招きます。代わりに論理DNSでは、接続は循環するまで存続します。大規模Webサービスと対話するとき、これはすべての可能な世界の中で最高です：非同期/最終的に一貫したDNS解決、長命の接続、および転送パスのゼロブロッキング。

#### 元の行き先

iptablesのREDIRECTまたはTPROXYターゲットを介して、あるいはプロキシプロトコルを使用して、着信接続がEnvoyにリダイレクトされる場合は、元の宛先クラスタを使用できます。このような場合、元の宛先クラスタにルーティングされた要求は、明示的なホスト構成やアップストリームホストの検出を行わずに、リダイレクションメタデータの指定に従ってアップストリームホストに転送されます。上流ホストへの接続はプールされ、未使用のホストはcleanup_interval（デフォルトは5000ms）より長くアイドル状態になっているとフラッシュされます。元の宛先アドレスが利用できない場合、アップストリーム接続は開かれません。 EnvoyはHTTPヘッダから元の送信先を取得することもできます。元の宛先サービスディスカバリは、元の宛先ロードバランサーとともに使用する必要があります。

#### エンドポイントディスカバリサービス（EDS）

エンドポイント検出サービスは、Envoyがクラスターメンバーの取得に使用するgRPCまたはREST-JSON APIサーバーに基づくxDS管理サーバーです。クラスターメンバーは、Envoyの用語では「エンドポイント」と呼ばれています。各クラスタに対して、Envoyは検出サービスからエンドポイントを取得します。 EDSは、いくつかの理由から好ましいサービス発見メカニズムです。

- Envoyは各アップストリームホストについて明確な知識を持っており（DNS解決ロードバランサを介したルーティングに対して）、よりインテリジェントなロードバランシングの決定を下すことができます。
- 各ホストのディスカバリAPIレスポンスに含まれる追加属性は、ホストの負荷分散の重み、カナリアステータス、ゾーンなどをEnvoyに通知します。これらの追加属性は、負荷分散、統計収集などの間にEnvoyメッシュによってグローバルに使用されます。

Envoyプロジェクトは、EDSの参照gRPC実装と、JavaとGoの両方の他のディスカバリーサービスを提供します。

#### カスタムクラスタ

Envoyはカスタムクラスタ検出メカニズムもサポートしています。カスタムクラスタは、クラスタ設定のcluster_typeフィールドを使用して指定されます。

一般的にアクティブヘルスチェックは、負荷分散とルーティングの決定を行うために、最終的に一貫性のあるサービス検出サービスデータと共に使用されます。これについては次のセクションで詳しく説明します。

### やがて一貫したサービス発見に

多くの既存のRPCシステムはサービスの発見を完全に一貫したプロセスとして扱います。この目的のために、彼らはZookeeper、etcd、Consulなどのような、完全に首尾一貫したリーダー選挙のバッキングストアを使用しています。

Envoyは、サービスの発見には完全な一貫性が必要ではないという考えで最初から設計されました。代わりに、Envoyはホストが最終的に一貫した方法でメッシュから出入りすると仮定します。サービスからサービスへのEnvoyメッシュ設定の推奨される方法では、クラスタの健全性を判断するために、最終的に一貫したサービス検出とアクティブヘルスチェック（Envoyによるアップストリームクラスタメンバーのヘルスチェック）が使用されます。このパラダイムには多くの利点があります。

- すべての健康上の決定は完全に分散されています。したがって、ネットワークパーティションは適切に処理されます（アプリケーションがパーティションを適切に処理するかどうかは別の話です）。
- ヘルスチェックがアップストリームクラスタ用に設定されている場合、Envoyは2×2マトリックスを使用してホストにルーティングするかどうかを決定します。

| 検出ステータス | ヘルスチェックOK | ヘルスチェック失敗 |
| --- | --- | --- |
| Discovered | Route | Don't Route |
| Absent | Route | Don't Route / Delete |

- ホスト検出/ヘルスチェックOK
  Envoyはターゲットホストにルーティングします。
- ホスト不在/ヘルスチェックOK：
  Envoyはターゲットホストにルーティングします。設計ではディスカバリサービスがいつでも失敗する可能性があると想定しているため、これは非常に重要です。検出データがなくなった後もホストがヘルスチェックに合格し続けた場合でも、Envoyはルーティングを続けます。このシナリオで新しいホストを追加することは不可能ですが、既存のホストは引き続き正常に動作します。発見サービスが再び正常に動作しているとき、データは最終的に再収束します。
- ホスト検出/ヘルスチェックFAIL
  Envoyはターゲットホストにルーティングしません。ヘルスチェックデータは、ディスカバリデータよりも正確であると想定されています。
- ホスト不在/ヘルスチェック
  Envoyはルーティングせず、ターゲットホストを削除します。これが、Envoyがホストデータを消去する唯一の状態です。