サービスメッシュの本質は、トラフィック管理や可観測性ではない
Abstruct
サービスメッシュが、真に提供する価値は何なのか。それはトラフィック管理と可観測性なのだろうか。
サービスメッシュがこれほどにまで繁栄した理由について、私なりに考察する。
Introduction
近年では、ソフトウェアのアーキテクチャとして、マイクロサービスが大流行した。かつては最大手のインターネット企業のみが必要性に迫られていた、マイクロサービスアーキテクチャだが、昨今の急激に成長するITビジネスの中で、多くの企業にとってマイクロサービスは、あらゆる企業が取り組むべき必然性のあるソリューションとなっている
マイクロサービス・アーキテクチャによって、大規模な開発チームがより俊敏になり、より多くのデプロイを実現させられることは、大きなメリットだ。一方で、マイクロサービス特有の課題も数多く存在する。
マイクロサービスに移行する際に発生する運用上の問題の多くは、結局のところ、ネットワークに由来するものであると私は考えている。
ネットワークに由来する課題における代表的なところで考えれば、トラッフィク管理、可観測性、セキュリティの3つである。
具体的には、以下のような機能を実装するが代表的なものとして挙げられる。これは、マイクロサービスの発展の過程で多くの場合で必要となる機能だ。
- トラフィック管理
- サービスディスカバリ
- 動的なリクエストルーティング
- 負荷分散
- ミラーリング
- スロットリング
- タイムアウト
- リトライ
- サーキットブレイカー
- カオスエンジニアリング
- カナリアリリース
- 可観測性
- モニタリング
- ロギング
- 分散トレーシング
- セキュリティ
- トラフィックアクセスコントロール
- サービス間の認可
- ファイアウォール
- 相互TLS
ここで、重要なことは、これらの機能はいずれも分散システムにおけるネットワークに由来する課題であることであり、分散システムにおいてネットワークを通じてシステムが成り立っている以上、上記の課題以外にもネットワーク由来の課題は起こり得るということだ。
Problem statement
では、前述したネットワーク由来の課題解決策をどう実装するのか。
前述した課題一つ一つを見ていくと、それらは主要なプログラミング言語においては、ライブラリを用いて実現可能だ。
例えば、Javaを使ったサービスで、サーキットブレイカーを実装したいとしたらHystricsを利用することを検討するだろう。Hystrixは、簡単な設定でサーキットブレイカーを実装できるだけでなく、メトリックスの収集、リアルタイムの監視、自動的なフェイルオーバーなどの機能も提供している。
他にも、resilience4jやSentinelのようなライブラリもあり、これらのライブラリは、Javaの開発者にとって非常に便利であり、多くの企業がこれらのライブラリを使用して、分散システムの信頼性を向上させている。
このように一つ一つの課題に対して、ライブラリを導入したり実装したりすることで、ネットワークの信頼性、可観測性、セキュリティを高めていくことは技術的には可能であろう。
しかし、実際にはマイクロサービスは100以上もある、それらは独立したチームであり自律的に動いている。
その全てのチームがJavaのAPIを作成しているだろうか、いや、機械学習モデルをデプロイする際にはPythonを使っているだろうし、GoやRustを用いているチームもあるだろう。全てのマイクロサービスにおいて統一的にネットワークに関する課題を解決するライブラリを作るのは難しいだろう。
仮に、全てのマイクロサービスがJavaのような一つのプログラミング言語を用いていたとしよう。そして、仮にネットワークに関する課題を解決できるような強力なライブラリを作成したとしよう。もしそうだとして、全てのマイクロサービス間の全ての通信においてサーキットブレイカーの導入を強制させることができるだろうか。
どこかのマイクロサービスは、独自の仕組みでネットワークの信頼性を高めるかもしれない。そうなれば、可観測性はどうなるだろうか。ログやメトリクスは一貫性のあるフォーマットに揃うだろうか。アクセスコントロールはどうなるだろうか。相互TLS通信は実現できるだろうか。
そもそも、本来マイクロサービスでは、各チームは自分のサービスに対して責任を持ち、他のサービスの実装に依存するべきではない。ところが各マイクロサービスの実装で、どのように認証/認可を行うのだろうか。サービス間はデフォルトでmTLSやRBACで認証/認可が行われるようにすべきだが、それは通信先のマイクロサービスの実装に依存せざるをえなくなってしまうのではないだろうか。
はたまた、ネットワークに関する新たな課題への対応策を実施したい場合に、全てのマイクロサービスの全ての通信に対して新たな課題解決策のための更新をすることを強制できるだろうか。ライブラリのバージョンアップが必要なことを認知してもらうだけでもかなり大変そうだ。
全てのマイクロサービス間の通信に対して、一貫した仕組みを「アプリケーションに手を加えずに」実現できる仕組みがほしい
こんなふうに考えたくはならないだろうか。
Material and Method
まさに、これがサービスメッシュの解決する課題だ。
以下の図はIstioのOverviewである。
Istioには、データプレーンとコントロールプレーンがある。
Data Plane
データプレーンは、全ての通信のインバウンド、アウトバウンドをインターセプトするプロキシだ。
このプロキシには、Envoyを利用していて、このプロキシの中で前述したような課題解決の機能を提供する。
トラフィックルーティング,メトリクスやTracingの収集、サービスディスカバリ、サーキットブレイカーなどをこのEnvoy Proxyが行う。
では、このEnvoy Proxyは全てのPodのサイドカーとしてデプロイされているのはなぜだろうか。
これは、アプリケーション側で実装する必要があるのだろうか。
Control Plane
いいや、Istioは、サービスメッシュを実現するために、各サービスインスタンスにEnvoy Proxyを自動的に設置することによって、データプレーンを構成する。そのため、アプリケーションはIstioやEnvoy Proxyについて一切意識する必要がなく、設定等も不要である。
この役割を担っているのが、istio-initである。
istio-init は、Istioのサイドカープロキシを Kubernetes クラスター内のすべてのワークロードに注入するために使用される、Initializerである。
このようにData Planeを管理するのがControl Planeである。
他にも、RouteRuleなどの設定を常に最新に保つように、Reconciliation Loopを実行したり、可観測性を高めるためにログを集約したりとサービスメッシュの中核を担うのがこのコントロールプレーンである。
Discussion and Conclusion
サービスメッシュが解決する課題は、本質的には、トラフィック管理でもなければ、可観測性でもなければ、セキュリティでもない。それらは確かに、サービスメッシュを導入することによって解決される課題であるが、サービスメッシュの本質ではないように思える。なぜなら、サービスメッシュではなくてもそれらの課題を解決する現実的な方法は存在するからである。
サービスメッシュの本質は、コントロールプレーンであり、これはKubernetesに対する考え方と似ている。
Istioは、yamlによって、ネットワーク管理におけるあらゆる機能を設定できる。
そして、Control Planeは常に最新の設定となるように、Reconciliation Loopを実行する。これがネットワーク管理の世界で、Configuration as Dataが実現された瞬間である。
これまでは、インフラストラクチャをデータとして管理する。という革命を起こしたのが、Kubernetesであった。
これがIstioのようなサービスメッシュのツールによって、その革命がネットワークレイヤーにも及んだ。言うならば、Traffic Management as Dataとでも言おうか。
私の考えでは、サービスメッシュの本質はControl Planeであり、Kubernetesである。
アプリに手を加えずに様々な課題解決を実行したいPlatformチームが、
ビジネスロジックに集中し最高のアプリケーションを開発することに集中したいマイクロサービスチームの手を煩わせる必要なく、ネットワークレイヤーに関する前述したあらゆる機能を透過的に導入させることができる。
そういったものがサービスメッシュである。
また、サービスメッシュという仕組みは、実態としてはアプリケーションの横で動くサイドカーでしかないので、拡張することができる。
IstioのようにProxyにEnvoyを使っている場合は、Envoyフィルターの利用をすることで、Pluggableに拡張することができる。
Envoyフィルターとは、Envoyのコア機能に影響を与えず、Envoy プロキシで実行されるカスタム機能を定義するための手段である。Envoy Filter を使用すると、Envoy プロキシの様々なレイヤーで、カスタム処理を追加できる。
そして、それらは、envoy.yamlによってコード化されるため、標準でIaCが実現できる。
また、Kubernetesのカスタムリソース等で表現すればConfiguration as Dataの世界に引っ張り出すこともできる。
マイクロサービス由来で起こり得るネットワークの課題を、解決するためのソリューションを管理するものがサービスメッシュなのではないだろうか。
そして、近年では、サービスメッシュ導入における損益分岐点なんかが話題になることがある。
たしかに、全てのマイクロサービス導入企業において、サービスメッシュを導入すべきであるとは一概には言えない。というのも、サービスメッシュ自体の運用が必要になり、結局はデータプレーンは単なるプロキシであり、ネットワークそのものが複雑化していることに変わりはないからだ。
IaCによって設定をすることで自動化できるとはいえ、全てがなんの問題もなくうまくいくほどシンプルではない。
だから、損益分岐点の話題が出るのは当然だ。
Wantedlyのブログに非常に興味深いものが書いてあった。まさにこの問いに答えるような文章を見つけた。
この記事はKubeforkというPull Requestごとのテスト環境を動的に生成する社内ツールを作ったという話だ。私自身もこのツールの開発に少しだけ携わっていたことがある。
このツールは、IstioのVirtual Serviceをつかって、Kubernetesクラスタのコピーを仮想的に作成するというチャレンジングな取り組みをしている。
そして、この記事の終わりは以下のような文章で締めくくられている。
今回作った基盤はこれまで作ってきたものの上に構築されたものです。簡単に示すと下のようなものがあります。
- context propagation は feature flag 用の基盤として実装済みだった
- servicex があったから context propagation の実装が簡単だった
- istio が導入済みだったので service mesh の導入は簡単だった
- そもそも全 microservice が Kubernetes に移行が完了していた
今回作ったものを全て位置から積み上げていくとしたら莫大な時間がかかっていただろうなということが想像されます。良い基盤は一朝一夕にはできないので少しずつ良いものを良い粒度で作っていくことが大事だなと実感しています。
私はこのような考え方がすごく好きだ。
私はあらゆる技術選定の根底にある考え方として、「良い基盤は一朝一夕ではできない」「少しずつ良いものにしていく」という考え方を持っておくことが大切だと考えている。
Platformを作るのは、決して簡単なことではない。サービスメッシュを導入すれば直ちに良い基盤となるわけではない。サービスメッシュとは、コントロールプレーンであり、ネットワークの管理のための下地にすぎない。
なんかそれっぽく動く基盤を作るのではなく、価値のあるプラットフォームを創る覚悟がなければ、サービスメッシュを導入しても運用負荷の大きさに苦しむ可能性もある。
けれど、継続的に価値のあるプラットフォームを作り続けていくならば、サービスメッシュしかり、Kubernetesしかり、それらのControl Planeによる管理は大きな見返りのある投資であると考える。
Envoyは「ネットワークレイヤーの課題はアプリケーションからは透過的であるべきである」という思想を掲げており、Istioはそれを体現したコントロールプレーンだ。
さぁ、あなたはそのテネッツに共感できるか。そして、サービスメッシュに投資するか。
もし、興味をもったら、下記のメルカリの事例でも、実際にcustom envoy filterを用いた拡張を行っているので、ぜひお読みいただきたい。
References
Discussion