Envoy Proxyに入門した

Envoy Proxy

最近 Kubernetes 周りの技術をよく触るのですが、Envoy Proxy (Envoy)もよく耳にするので勉強しました。

Envoy とは?

Envoy はクラウドネイティブな Web サービスのために設計されたロードバランサーです。 元は Lyft が開発しており、現在は CNCF (Cloud Network Computing Foundation) によって管理されています。 Envoy には大きく2つの用途があります。

  • サービスメッシュの通信バス: サービスメッシュ内の各サービス間の通信を制御するプロキシ。サービスディスカバリーや流量の制御をする。
  • エッジプロキシ: サービス内のプライベートネットワークとサービス外をつなぐプロキシ。データセンターや Kubernetes クラスタの外からのアクセスを受け付ける。

背景

モノリスで巨大な Web システムが成長するとき、開発者はマイクロサービス化という選択肢を迫られます。 しかしマイクロサービスなどの分散システムを構築・運用するには、モノリスなシステムと比較して新たな難しさも見えてきます。 Lyft も初めはモノリスなアーキテクチャでしが、成長と共にサービス数が増えて、ネットワークの制御に苦労するようになりました。 そこで Lyft は Envoy を開発しました。

マイクロサービスアーキテクチャを運用する上で、サービス間のネットワーク制御は不可欠です。 たとえばリトライやサーキットブレーカー、帯域制限が必要です。 またデバッグ時に利用する分散トレーシングやログ情報も必要になります。

ネットワーク制御の仕組みをライブラリとして提供すると、各サービスで採用してる言語やフレームワークに応じて用意して、それをメンテナンスする必要があります。 マイクロサービスではそれぞれのサービスが自由な言語・フレームワークが使えるというメリットがある一方、こういったライブラリが使いにくいという課題もあります。 そこで Lyft はライブラリではなくネットワークプロキシとして利用できる Envoy が開発されました。

Envoy の利用実績

Envoy は現在多くのサービスで採用されています。 巨大なクラウド企業である Google、AWS、Microsoft や、国内でも Cookpad や Yahoo! JAPAN などで採用されてます。 Kubernetes と共にサービスメッシュ化も加速し、今後もユースケースが増えるでしょう。 Envoy は直接デプロイして利用することもできますし、IstioHeptio Contourなどの Envoy をラップしたアプリケーションも存在します。

2018 年 11 月、Graduated CNCF Project に認定され、CNCF の中でも十分成熟したプロジェクトとして認定されました。 他に Graduated CNCF Graduated となったプロジェクトに Kubernetes と Prometheus があります。 そのため Envoy はこれらと肩を並べるほどの利用実績と信頼性があるということです。

Envoy のデザイン

基本コンセプト

Envoy は次の思想のもと開発されました。

ネットワークはアプリケーションに対して透過的 (transparent) であるべきだ。 なぜならネットワークまたはアプリケーションに問題が発生したとき原因の特定が簡単だからだ。

Envoy はサービス間のネットワーク制御を、ライブラリではなくネットワークプロキシとして開発しました。 それぞれのサービスは Envoy を経由して別のサービスに接続します。

Envoy を利用したアーキテクチャでは、アプリケーションと同じホスト(正確にはネットワークを共有してるホスト)上に Envoy を構築します。 Kubernetes などでは、Envoy を各アプリケーションのサイドカーコンテナとしてデプロイします。 各サービスは別のサービスを直接参照するのではなく、localhostに建てられた Envoy に接続します。

サイドカーとして立てられた Envoy では、別サービスの IP アドレスなどを知っています。 アプリケーション自体が別のサービスの IP アドレスを知らなくとも、localhostにある Envoy のポートのみを知ればよいです。 経路制御やサービスの IP アドレスが変わったときも、Envoy の設定を更新さえすれば、アプリケーションはネットワークで何が起こったかを知る必要がありません。

Envoyによるサイドカー

基本用語

クライアントが Envoy に接続する側を Downstream と呼び、Envoy がサーバー接続する側を Upstream と呼びます。 Envoy のプロキシ設定は、Listener と Cluster のペアを設定します。

  • Cluster: Envoy が Upstream に接続するホストグループです。
  • Endpoint: Cluster 内にあるメンバーの 1 つで、Upstream のホストです。
  • Listener: Downstream が Envoy に接続するための情報で、アドレス・ポートや UNIX ドメインソケットを指定できます。
  • Route: URL や HTTP ヘッダからどの Cluster に接続するかの経路情報です。

動的な設定変更と xDS

Envoy の設定は全て静的なファイルで与えることができますし、Envoy をシャットダウンせず設定の更新もできます。 設定を動的に変更するには gRPC、REST API や、ファイルの更新などがサポートされいます。 gRPC と REST API による設定変更は、Envoy"が"制御サーバーに Envoy の設定を問い合わせます。 REST API ではサーバーをポーリングして設定をリロードし、gRPC では gRPC ストリームを使って新しい設定をロードします。 Envoy ではこの API 提供する制御サーバーをコントロールプレーンと呼び、Envoy 側をデータプレーンと呼びます。

設定を取得する API は、Envoy の各種項目毎に用意されてます。 たとえば Listener の設定を取得する API は Listener Discovery Service (LDS) と呼びます。 また Cluster の設定を取得する API は Cluster Discovery Service (CDS) と呼びます。 これらの API をまとめて、xDS APIと呼びます。

xDS API には以下の API が含まれます。

  • Listener Discovery Service (LDS)
  • Route Discovery Service (RDS)
  • Cluster Discovery Service (CDS)
  • Endpoint Discovery Service (EDS)
  • Secret Discovery Service (SDS)

これらの API 毎に独立した gRPC ストリームを利用できますが、Aggregated Discovery Services (ADS)を使うと単一のストリームで複数の xDS API を利用できます。

EnvoyとxDSサーバー

Envoy の利用例

サービスディスカバリー

サービスメッシュ内であるサービスが別のサービスに接続するには、接続先の IP アドレスを知る必要があります。 特に Kubernetes のように IP アドレスが不定の環境では必要な仕組みです。 一番単純なサービスディスカバリーの実装は DNS です。 Kubernetes ではユーザーが Service リソースを作成すると、対応する DNS レコードが DNS サーバーに登録されます。 しかし DNS は詳細な経路設定ができませんし、負荷分散のルールも設定できません(Kubernetes の Service リソースはラウンドロビンで Pod を選びます)。

Envoy ではより柔軟なサービスディスカバリーを実装できます。 この機能を使うと、たとえば一部のユーザーにのみ新しいサービスを提供できたり、データベースを分割してる環境で欲しいデータのあるインスタンスを見つけたりできます。 Envoy を利用するとこういった柔軟な設定ができます。 アプリケーションは宛先のインスタンスを直接知らずとも、Envoy を経由して透過的に目的のサービスに到達できます。 コントロールプレーンとデータプレーンが役割ごとに別れて、わかりやすいアーキテクチャになっています。

エッジプロキシ

サービスディスカバリーの仕組みを使うと、エッジプロキシとしても役立てる事ができます。 Envoy は NGINX のように、HTTP リクエストのヘッダーやパスに応じた経路を設定したり、複数経路を重み付けでロードバランシングできます。 そのため Blue-Green デプロイやカナリアリリースに必要な機能が備わっています。

Heptio Contour はバックエンドに Envoy を採用した Kubernetes で利用できるエッジプロキシです。 Kubernetes の Ingress Controller では Blue-Green デプロイやカナリアリリースをできるほどの柔軟性がありません。 Heptio Contour は Ingress Controller で足りない機能を Custom Resource Definition として提供します。

Heptio Contour のお話は KubeCon + CloudNativeCon でもあったので時間のある人はぜひ。

まとめ

Envoy を軽く触って最初に思ったのは「高級な L7LB だなぁ」という感想程度でした。 機能自体は目新しいものは少ないですが、素な機能のみを提供してるため使い方は無限大です。 そして xDS API などの設計は良くできてるなという感想です。 他のロードバンサーの実装と違い、クラウドネイティブなアプリケーションでは大活躍できそうだと思いました。

今後もちまちまと調査を進めて、もう少し実用的な記事も書いていきたいと思います。

参考


Profile picture

Shin'ya Ueoka

B2B向けSaaSを提供する会社の、元Webエンジニア。今はエンジニアリング組織のマネジメントをしている。