マイクロサービスを実現するためのサービスメッシュとは？

#はじめに

今までのモノリシックアーキテクチャとは異なり、ビジネス機能に沿った複数の小さい単位に分割し、連携させるマイクロサービスアーキテクチャーへの移行の流れが高まっています。

マイクロサービスとは、[ThoughtWorks](https://www.thoughtworks.com/)社のマーチン・ファウラーとジェームス・ルイスが最初に提唱したソフトウェアアーキテクチャです。モノリシックアーキテクチャを、ビジネス機能に沿って複数の小さい「マイクロサービス」に分割し、それらを連携させるアーキテクチャにすることで、迅速なデプロイ、優れた回復性やスケーラビリティといった利点を実現しようとするものです。

今では[Amazon](https://www.amazon.com/)や[Netflix](https://www.netflix.com/)、[Spotify](https://www.spotify.com/)などの世界的テックカンパニーでも導入されるようになってきています。

その文脈で、複雑化するマイクロサービス全体を管理・運用するために「サービスメッシュ」という概念が広がり、サービスメッシュを実現するソフトウェアとして「Istio」や「Envoy」などが出てきました。

本記事では、サービスメッシュの前提となるマイクロサービスの課題、サービスメッシュの概念、それを実現するための方法についてソフトウェアの紹介も交えながら書いていきたいと思います。

#マイクロサービスの課題

まず、サービスメッシュの概念について説明する前に、その概念が出てくるきっかけとなったマイクロサービスの課題について簡単に触れておきたいと思います。

マイクロサービスについては、こちらの記事で詳しく書いているので、合わせて参考にしてもらえればと思います。
[マイクロサービスアーキテクチャのまとめ（メリット/デメリット/用いる技術）](https://qiita.com/yusuke_kinoshita/items/54bac5a69bf89cc18383)

###課題1. サービス管理の複雑化
複数の小さなサービス単位が相互に連携するため、依存関係にあるサービスの接続情報の管理が難しくなります。バージョンの違いや、通信ヘッダーに設定されているコンテキスト、さらには業務データのコンテンツに基づいたルーティングが求められることもあります。そうすると、基盤レベルに留まらず、より上位の通信スタックを意識したルーティングを考慮しなければならず、管理コストが高まります。

###課題2. モニタリング管理の複雑化
マイクロサービスでは、一つのリクエストが複数のサービスに跨ることにより、リクエスト全体の処理の流れを把握（トレーシング）することは難しくなります。

一方で、多次元での監視が求められることになります。各サービスごと、各サービスのバージョンごとの様々な観点から、メトリクスやログ、トレースを収集し、状態をタイムリーに表示あるいは通知しなければなりません。分散配置された各サービスからの情報収集と、表示と通知の仕組みが求められます。

###課題3. セキュリティ管理の複雑化
マイクロサービスにおいても、アクセス元のサービスの権限に応じて、提供するコンテンツを制御したいケースが存在すると考えられます。
通常、このようなケースを実現するには、認証・認可の仕組みが必要となるのですが、各サービスにおいて個別に実装していくと大きなコストを発生させてしまいます。

###課題4. 障害解析の複雑化
マイクロサービスでは、複数の小さなサービスが相互に連携しているため、あるサービスで発生した障害が連鎖した場合、システムの構成要素が多数に上るため、問題判別に時間と手間がかかり、障害解析の難易度は高くなる傾向があります。

ユーザーがリクエストする限り、依存リソースへのアクセスは続き、ダウンした依存リソースへのアクセスはレイテンシの増加を引き起こし、滞留したリクエストは余分なリソースを消費し、そしてユーザーは長時間レスポンスを待つ必要が出てきてしまいます。

#サービスメッシュとは？

上述の通り、複数のマイクロサービスに分割するため、管理対象が増加し、運用管理は複雑化し、複雑に絡み合った通信経路の集合体となります。また、障害が発生した際も複数のサービスから原因を特定しなければならないので、障害解析は高難易度化しがちです。

そこで、「サービスメッシュ」では、下図のように、各マイクロサービスに対してSidecarを用意し、サービス間のコミュニケーションをすべてSidecar経由とすることにより、アプリケーション開発者がビジネスロジックの開発に専念できるようしています。
![サービスメッシュの概念図](http://philcalcado.com/img/service-mesh/6-a.png)
引用：http://philcalcado.com/img/service-mesh/6-a.png

マイクロサービスでは、各サービスが他のサービスと連携するために構成されるネットワークが網の目のようになるので、そこからなぞらえて「サービスメッシュ」と呼ばれています。

#サービスメッシュを実現するソフトウェア

マイクロサービス全体を管理し、インフラストラクチャに依存せずにサービスメッシュ機能を提供するソフトウェアとして[Istio](https://istio.io/)、[Linkerd](https://linkerd.io/)、[Consul](https://www.hashicorp.com/products/consul)などがあります。

サービスメッシュが提供するネットワークサービスは以下のとおりです。

* トラフィック制御
* 回復性、耐障害性処理
* 可視化、分散トレース
* 認証、セキュリティ機能

##Envoy
![Envoy-logo](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405375/15f6e1b6-8085-06ae-dbb8-15e5c55abdb8.png)
引用：https://www.envoyproxy.io/

後述の[Istio](https://istio.io/)のData Plane（データプレーン）としても利用されている、Lyft社が開発したサービスメッシュを実現するためのソフトウェアです。また、[CNCF（Cloud Native Computing Foundation）](https://www.cncf.io/)をGraduateしています。

C++で書かれた高パフォーマンスのL4/L7プロキシで、サイドカープロキシとしてデプロイされ、各サービスに対してアプリケーションの改修なく、マイクロサービスに必要な下記の機能を付加できます。

* 動的なサービスディスカバリ
  * 設定ファイルによる静的な設定に加え、RESTまたはgRPCのAPIによるサービスディスカバリーが可能です。

* ロードバランス
  * ラウンドロビン・ランダム・重み付け最少接続数の3つの負荷分散モデルが利用可能です。
  * シャドーイングという機能があり、Envoyを流れるリクエストの複製を別のホストに流すことが可能です。ホストからのレスポンスは捨てられるため、例えば、本番環境で実際に流れるリクエストを使ってデプロイ前にテストを行うことができ、本番へのデプロイのリスクを下げるといった使い方ができます。

* 様々なプロトコルの対応
  * TCP, TLS, HTTP1.1, HTTP/2, gRPC に加え、 MongoDB, DynamoDB, Redis などもサポートしています。UDPも今後サポートされるようです。

* 障害の分離
  * 脆弱性の発見、回復性テストに利用することができます。

* メトリクスの取得
  * Zipkinなどの分散トレーシングに対応しており、メトリクスのエクスポートも行います。
  * メトリクスの可視化については[Grafana](https://grafana.com/)や[Prometheus](https://prometheus.io/)などのツールがあります。

* トラフィックの分割
    * これにより、A/Bテストやカナリアリリースを実現することができます。

* TLS終端処理

* ヘルスチェック

詳しくは[公式サイト](https://www.envoyproxy.io/)を見てください！

##Istio
![Istio-logo](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405375/a3f4be10-e36c-51c6-f8d8-105450f9112c.png)
引用：https://istio.io/

[Istio](https://istio.io/)は、Google、IBM、Lyftで共同開発したOSS化されたサービスメッシュフレームワークで、環境非依存のプラットフォームで利用可能です。

※2019年3月にバージョンが1.1に到達しています（参考：https://istio.io/blog/2019/announcing-1.1/）
※ベータ版ですが、GCPのマネージドサービスとして提供されています（参考：https://cloud.google.com/istio/docs/istio-on-gke/overview）

各マイクロサービスと一緒にSidecarProxyとをデプロイし、それ経由で他のマイクロサービスとの通信を行います。[Istio](https://istio.io/)では、SidecarProxyとしてLyftが作成した[Envoy](https://www.envoyproxy.io/)を採用しています。

Istioのアーキテクチャは、大きく「Data Plane（データプレーン）」と「Control Plane（コントロールプレーン）」の2つに分けることができます。（下図の通り）
![Istio-arc](https://istio.io/docs/concepts/what-is-istio/arch.svg)
Data Plane（データプレーン）では、プロキシによるマイクロサービス間の通信を管理しており、Istio用に拡張された「Envoy」をサイドカープロキシとして、KubernetesのPod内にデプロイしています。

Control Plane（コントロールプレーン）には、以下の4つのコンポーネントが含まれています。

* Envoy: サービスメッシュのイン/アウトバウントの全てのトラフィックを管理するプロキシサーバで、KubernetesではPodのサイドカーとしてデプロイします。ちなみに、EnvoyはIstio用に拡張されたものを使用しています。

* Mixer：サービスメッシュ上でポリシー管理とテレメトリーを制御する管理コンポーネントです。Envoyと連携して、アクセス制御や、ログ、トレース、メトリクスの収集を実行します。
 
* Pilot：Envoyのサービスディスカバリやトラフィック管理を担当するコンポーネントです。Envoyに構成情報を連携し、サービス間の動作を制御するのが役割です。

* Citadal（以前のIstio-Auth）：サービス間認証とエンドユーザ認証を実現するコンポーネントです。KubernetesのService Accountを利用したユーザ認証や、サービス間のTLS相互認証を行います。この認証を利用することで、ポリシーベースでサービスメッシュを管理することができます。また、将来的にはFine-Granted Access Controlに対応するようです。

#まとめ

マイクロサービスアーキテクチャの流れの中で、その課題となるサービス全体の管理や運用の複雑化の解決方法として、サービスメッシュとそれを実現するためのソフトウェアが出てきています。

「Istio」や「Envoy」などのソフトウェアは、マイクロサービスを検討する場合、導入を検討すべきなのではないかと個人的に感じています。
今後も引き続き動向に注目し、アップデートがあればこの記事も更新しようと思います。