サービスメッシュの利点

複数のサービスで構成されたシステムにサービスメッシュを採用するモチベーションについて説明します。

サービスメッシュ必読ガイド - 第2版: 次世代のマイクロサービス開発」によると、サービスメッシュが解決しようとする課題は次のとおりです。

  • サービスディスカバリー、ルーティング、およびアプリケーションレベル (レイヤー 7) の非機能通信要件を処理するために、言語固有の通信ライブラリを個々のサービスにコンパイルする必要がなくなります。
  • 外部サービスのネットワークロケーション、セキュリティクレデンシャル、サービス品質ターゲットなど、サービス通信構成の外部化。
  • 他のサービスのパッシブおよびアクティブな監視を提供します。
  • 分散システム全体にポリシーの適用を分散化する。
  • 可観測性にデフォルトを提供し、関連データの収集を標準化します。
    • リクエストロギングの有効化
    • 分散トレーシングの構成
    • メトリクスの収集

非機能通信要件の処理

3つのサービス (Service A、Service B、Service C) で構成されたシステムを例にします。

図はサービスメッシュを利用しない構成です。

最初に Service A の実装を考えてみましょう。

Service A が Service B の API (/list) を呼び出す場合、URL は http://service-b/list となります。Service C の API (/items) を呼び出す場合の URL は http://service-c/items となります。

Service A と同様に Service B、Service C もそれぞれ依存するサービスの URL を生成します。

次にサービスメッシュ (Service Mesh) を利用する場合のトポロジーは次の図のとおりです。

proxy の代表例は Envoy Proxy です。

各サービスと proxy は同一の Pod に同梱して運用します。

ここで、先の例 Service A の実装を考えてみます。

Service A が Service B の API (/list) を呼び出す場合の URL は http://localhost/service-b/list となります。Service C の API (/items) を呼び出す場合の URL は http://localhost/service-c/items となります。

ここで、proxy はサービスディスカバリーにより、Service B、Service C のアドレスを理解してルーティングします (ルーティングの設定は、サービスメッシュにより自動的に反映されます)。

Service A と同様に Service B、Service C もそれぞれ依存するサービスへのルーティングを proxy が実行します。

これだけだと、URL のホスト名を localhost にかえて、サービス名をパスのプレフィックスにしただけで、メリットよりも proxy があることによる性能面での劣化の方が気になるでしょう。

さて、ここで Service C の APIREST API から gRPC を使う HTTP/2 に切り替えてパフォーマンスを向上したくなったと仮定してみてください。

サービスメッシュを利用していない最初の例の場合、Service C に依存する他のサービスは、Service C の API を呼び出すための改修が必要になります。そして、Service C の新バージョンのデプロイに合わせて、依存するすべてのサービスのデプロイも実施する必要があります。

サービスメッシュを利用している場合はどうなるでしょうか。

サービスメッシュの proxy の代表例 Envoy Proxy について「Istio in Action」の中で次のように書かれています。

Envoy can accept HTTP/1.1 connections and proxy to HTTP/2—or vice versa—or proxy incoming HTTP/2 to upstream HTTP/2 clusters. gRPC is an RPC protocol using Google Protocol Buffers (Protobuf) that lives on top of HTTP/2 and is also natively supported by Envoy.

Envoy は、HTTP/1.1 を HTTP/2 に (またはその逆にも) プロキシします、また受信した HTTP/2 を上流の HTTP/2 クラスタにプロキシすることができます。gRPC は、Google の Protocol Buffers (Protobuf) を使用する RPC プロトコルで HTTP/2 を使用しますが Envoy によってネイティブにサポートされています。

サービスメッシュの proxy を使用すると図のようになります。

他のサービスのパッシブおよびアクティブな監視

再び Service A について考えてみます。

Service A が、Service B の API を呼び出す必要があった時に Service B が停止していた場合、タイムアウトするまで処理がブロックされたくはないでしょう。

このためには、他のサービスの状態を監視し、停止しているサービスへのルーティングを行わないようにするサーキットブレーカーと呼ばれる機能によって、ブロックを防ぐことが一般的です。

サービスメッシュを利用しない場合は、各サービスでこのような機能を実装する必要がありますが、proxy はサービスの死活監視などパッシブとアクティブな監視により、このような機能が実現されます。

分散システム全体にポリシーの適用を分散化

サービスメッシュの proxy はポリシーを適用する機能が組み込まれています。

これを適用することで、ゼロトラストネットワークに必要な、認証 (JWT認証、mTLS 等)、認可 (OPA等) によるネットワークセキュリティの実行が可能です。

例えば、NIST (米国国立標準技術研究所) の「Zero Trust Architecture (NIST SP 800-207)」を参考にあてはめると次のようになります。

ZTA

可観測性と関連データの収集の標準化

可観測性とは、「マイクロサービスアーキテクチャ 第2版」によれば、

システムの可観測性とは、外部出力からシステムの内部状態をどの程度把握できるかです。

サービスメッシュの proxy はアクセスログ、サービスのログ、メトリクス、分散トレーシングデータ等を収集し配信できます。

各サービスへのプロダクト固有のエージェントの組み込み等を回避できます。

最後に

サービスをコンテナ化する大きな利点は、サイズの小さいイメージを作成することで、起動が俊敏となり、ミリ秒単位でスケールイン/アウトできることにあると考えています。

このためには、コンテナで実装するサービスは、可能な限り少ない責務のドメインに特化したコードのみとし、外部化が可能な実装はサービスメッシュでも実現されているように、サイドカーやコントロールプレーンとデータプレーンの分離等のコンセプトを取り入れることが必要でしょう。

さらに、サービスメッシュは、Feature Flags (Feature Toggles) や Blue/Green デプロイ、カナリアリリース等を実現できる機能もあります。

参考