キーポイント
- Service interaction and governance model are critical in a microservices-based architecture. Advanced architecture patterns like service orchestration and service mesh can help address challenges we face in distributed systems.
- Challenges like siloed development and complex service-to-service interaction (Death Star architecture) can lead to performance issues in production, security issues in terms of access control, and lack of overall system monitoring.
- Service orchestration helps with these challenges, but it also has some disadvantages like lack of decentralized policy enforcement.
- Service mesh-based solutions offer several advantages compared to traditional microservices architectures in the areas of connectivity, reliability, security, and observability.
このシリーズ記事の最初のパートでは、マイクロサービス、サーバレス、コンテナ化などのテクノロジートレンドのアーキテクチャの進化と戦略的なアーキテクチャパターンについて説明しました。疎結合、拡張性、インターフェイスベースの設計などの原則に基づくアーキテクチャは、テクノロジープラットフォームの大きな変化の際によりしなやかさがあります。適切に設計されたソリューションは、時間の経過とともに時代遅れになるテクノロジーコンポーネントからビジネスロジックを分離することにより、時の試練に耐えます。
パート 2 では、アーキテクチャの安定化のギャップと、分散モノリスや「Death Star (デススター) アーキテクチャ」などのアンチパターンに焦点を当てました。これは、アーキテクチャとテクノロジーの安定性のバランスを取る必要があることを示しています。
このパート 3 では、マイクロサービスベースのアーキテクチャにおけるサービスの相互作用の重要性、分散システムの一般的な課題、およびサービスオーケストレーションやサービスメッシュなどの高度なアーキテクチャパターンがこれらの課題への対処にどのように役立つかについて説明します。
マイクロサービスアーキテクチャにはいくつかの利点がありますが、いくつかの課題もあります。これらの課題をアーキテクチャの機会と見なし、サービスオーケストレーションを通じてそれらを克服する方法を探ります。
この記事で説明するデザインパターンは、AWS、VMware Tanzu Application Service (以前のPivotal Cloud Foundry)、Kubernetesなどのクラウドプラットフォームに適用できます。しかも、クラウド以外のインフラストラクチャでも使用できます。
Kubernetes は、いくつかの組織で事実上のクラウドプラットフォームになっています。サービスメッシュフレームワークは、現在 Kubernetes を使用している場合でも、将来 Kubernetes を探索する予定である場合でも、クラウド上で Kubernetes を最大限に活用するための優れた方法を提供します。この記事では、サービスメッシュがプロダクションにデプロイされたサービスの管理にどのように役立つかを示します。
まず、開発者およびアーキテクトとして、分散アプリケーションアーキテクチャで経験する課題から始めましょう。
課題 1: サイロ化された開発
下の分散システムの例は、サービスベースアーキテクチャとクラウドプラットフォームが登場する前の従来のアプリケーションアーキテクチャの課題を示しています。
図1 サイロ化された開発の例
2つのクライアントアプリケーション (App 1とApp 2) と3つのビジネスサービス (Service 1、Service 2、Service 3) があります。
この例では、App 1 は Service 1 および Service 2 と通信します。App 2 は Service 2 とのみ通信します。Service 2 は Service 3 とも通信します。
App 1 を調べて、このアプリケーション内で何が起こっているかを特定しましょう。
これは、マイクロサービスが登場する前にアプリケーションが通常どのように開発およびデプロイされたかの一例であり、このデザインは現在でも一部のアプリケーションで使用されています。
図2 内部のアプリケーションとサービスの機能
上のサンプルアプリケーションには、重要なビジネスロジックと非ビジネスロジックタスクが混在していて、すべてアプリケーションコード内に埋め込まれています:
- 非機能: 認証、認可、通知など。
- 共通プラットフォームタスク: サービスルーティング、サービスディスカバリ、サービスリトライ/サーキットブレーカ、トレースなど。
非機能要件は通常、アプリケーションにハードコードされ、複数のアプリケーションに共通の関心事であるにもかかわらず、ビジネスロジックと絡み合っています。
この例は、アプリケーションの外部で管理し、複数のビジネスアプリで活用する必要がある非機能タスクを比較した、一般的なアプリケーションに含まれる実際のビジネスコードの量を示しています。
8つの関数のうち1つだけが、アプリケーション内に属するアプリ固有のロジックを保持します。他の7つの機能は、アプリケーションロジックと組み合わせるべきではありません。
他のアプリケーションを深く掘り下げると、同じトレンドが明らかになるでしょう。
Service 1、2、および3の内部を見ると、同様のパターンが明らかになります。各サービスには独自のビジネスロジックがあり、前に見たのと同じ非機能とプラットフォームタスクが混ざっていますが、これはサービスの一部であるべきではありません。認証、認可、顧客通知などの一般的な非機能サービスがあります。ルーティング、サービスディスカバリ、サービス監視とトレースなど、クラウドプラットフォームでホストされるすべてのビジネスアプリケーションに共通するプラットフォームサービスもいくつかあります。
下に示すように、2つのアプリケーションと3つのサービスを備えた分散システムの単純な例は、これらの各コンポーネントの内部を見るとそれほど単純には見えません。
図3 各アプリとサービスで共通機能が冗長な分散システムの例
すべてのアプリケーションとサービスには、非機能コードがすべて含まれています。この種のデザインには多くの欠点があります。
各アプリケーションとサービスで同じ機能が重複して実装および拡散されているため、アプリケーション開発 (市場投入までの時間) が長くなり、保守コストが飛躍的に高くなります。
これらすべての共通機能が各アプリとサービスに組み込まれているため、これらの機能のそれぞれに使用される特定のテクノロジーとフレームワークと密結合されています。たとえば、Spring Cloud Gateway と、ルーティングとトレースの Zipkin や Jaeger です。基盤となるテクノロジーをアップグレードするには、すべてのアプリケーションとサービスを変更、再構築、および再デプロイする必要があり、ユーザのダウンタイムと停止 (outages) が発生します。
これらの課題のために、分散システムは複雑になりつつあります。これらのアプリケーションは、サイロ化された開発と1回限りのソリューションの急増を回避するために、再設計およびリファクタリングする必要があります。
ネットワークがより安定して信頼できるようになると、図3に示すように「処理中」の呼び出しが「ネットワーク経由」の通信に移行し始める可能性があります。
これらの複雑なシステムは「共通サービス」と呼ばれるデザインパターンで個々のアプリケーションやサービスにそれらの機能を組み込むことなく、共通の機能を利用するように再設計されています。
共通サービス
各アプリケーションに埋め込まれたコードの解決策は、これらの共通機能をそれぞれ独自のサービスにカプセル化し、中心的なサーバ (VMの場合) またはクラウド内のコンテナでサービスをホストすることです。
図4 独立したマイクロサービスにカプセル化された共通機能
クライアントアプリケーションは、アプリが共通機能を実行する必要があるときに、これらのリモートサービスを呼び出します。図4に示すように、共通ロジックは各アプリケーションまたはビジネスサービスに組み込まれていません。
共通サービスはステートレスで、理想的には Twelve-Factor App のベストプラクティスを使用して開発またはリファクタリングする必要があります。これによりコンシューマアプリケーションで再利用する付加価値を得られます。
オープンソースフレームワークを使用して、Java アプリケーション用の Spring Boot や Spring Cloud、.NET ベースのアプリケーション用の Asp.Net Core ミドルウェアなどでこれらの共通サービスを開発できます。これらのサービスは理想的には Twelve-Factor ベースのアプリケーションであるため、アプリを任意のクラウドプラットフォームにデプロイすることが容易です。また、プロダクション環境での管理と監視も容易です。
このアーキテクチャにはいくつかの利点があります:
- アプリケーションチームの開発とデリバリーのタイムラインが速いということは、市場投入までの時間が短いことを意味します。
- 個々のデプロイメントは他のアプリケーションやサービスから分離されているため、コンポーネント間の依存関係が少なくなります。
- 各サービスレベルでのスケーラビリティ。
- セキュリティおよびテクノロジー標準への自動コンプライアンス。
- より小さく、より速く、より簡単な継続的なメンテナンスにより、共有機能がアップグレードされたときにすべてのアプリケーションとサービスを再構築して再デプロイする必要がなくなります。
- 長期的には技術的負債が少なくなります。
これらの共通サービスは、オートスケーリング、モニタリング、デプロイメントのしやすさなどの機能 (capabilities) を適切にサポートするクラウドプラットフォーム (AWS、Azure、Kubernetes、以前は Pivotal Cloud Foundry と呼ばれていた VMWare Tanzu Application Service) でホストできます。
ただし、共通サービスは、クラウドネイティブジャーニーの移行アーキテクチャにすぎず、目標ではありません。共通マイクロサービスに基づくアーキテクチャにはいくつかの利点もありますが、サービスの相互作用が密結合されていることや、ルーティング、ディスカバリー、サーキットブレーカーポリシーに関する一元化されたポリシーの実施がないことなど、いくつかの新しい課題もあります。
これらの新しい課題については、この記事の後半で検討します。
組織でのマイクロサービスの導入と拡大に伴い、クライアントアプリケーションとビジネスサービス間の通信、およびサービス間の相互作用が重要になります。この通信の複雑さに対処しないと、サービスのパフォーマンスが低下し、システムの可用性が損なわれる可能性があります。
次に、アプリとサービス間の通信の課題について詳しく見ていきましょう。
課題 2: アプリ/サービスとサービス/サービスの通信
大規模なアプリケーションをきめ細かいサービスに分割すると、デプロイされるコンポーネントの総数が増え、これらのコンポーネント間の相互作用がますます複雑になります。図5はこの複雑さを示しています。
図5 アプリケーションとサービス間通信の課題
各クライアントアプリケーションから抽象化され、個別のサービスとしてデプロイされた共通機能を使用しても、サービスの相互依存性とサービスが相互に呼び出す方法はアーキテクチャに大きな脅威をもたらします。
前の例を拡張して、さらにいくつかのビジネスサービスを含め、サービス通信への影響を調べてみましょう。
図5のサービス間通信でわかるように、異なるサービス間には依然として密結合があります。また、システム全体の動作が遅い場合や停止している場合に、どのサービスで問題が発生しているかを特定することも困難です。
マイクロサービスとこの複雑な相互作用モデルを導入している他の企業も同じ課題を経験しているのではないかと思うかもしれません。彼らはあります。Netflix、Amazon、Twitterなどの企業は、サービスの通信やガバナンスプロセスの効果的なモデルがなしで、アプリケーションやサービスが別のサービスを呼び出そうとした場合に、同じ課題を経験しました。この一連の記事のパート 2で述べたように、このアーキテクチャの課題は業界で非常に普及しているため「デススターアーキテクチャ」と呼ばれるアンチパターンとして定義されています。
これらの企業は、サービスオーケストレーションによってこのアーキテクチャの課題を克服しました。
サービスオーケストレーション
図6 サービスオーケストレーションにより改善されたサービス間相互作用
図6のサービスオーケストレーションのモデルでは、以前のアーキテクチャと同様に、クライアントアプリケーションの外部で共通サービスを管理し、独自のデプロイメント、ライフサイクル、およびスケーラビリティのニーズを備えています。
主な改善点は、ルーティングサービスをすべての共通サービスの前に移動したことです。
クライアントアプリケーションは、ルーティングサービスのみを呼び出す必要があります。クライアントアプリケーションからのリクエストのユースケースとコンテキストに応じてルーティングサービスは1つ以上の共通サービスとアプリケーションサービスを事前に定義された順序で呼び出します。
このアーキテクチャには多くの利点があります:
- まず第一に、クライアントアプリケーションと共通サービスは疎結合されています。また、柔軟なトラフィック管理と一元化されたポリシーの実施も可能になります。
- ポリシーは、認証や認可などのセキュリティに関連すること、サービスの再試行やサーキットブレーカールールなどのSLAに関連すること、または可観測性と監視に関連することができます。
- このアーキテクチャは、システムのエンドツーエンドの監視を提供します。
このアーキテクチャは、クライアントアプリケーション、バックエンドの共通サービス、ルータ自体など、アーキテクチャのさまざまな部分がどのように相互作用するかという点でも、多くの柔軟性を提供します:
- クライアントアプリケーションには、Webアプリケーション、モバイルアプリ、IoTデバイス、またはその他のサービスがあります。
- バックエンドサービスは、モノリシックアプリ、マイクロサービス、またはサーバレスファンクションです。
- ルーティングサービスは、プロダクションアプリケーションのダウンタイムがゼロのルーティング/分割やカナリアデプロイメントなどのさまざまな機能に使用できます。
- クライアントとサービス間の通信は、リクエスト/レスポンスメカニズムを使用してトランザクションおよび同期にすることも、非同期の publish/subscribe メッセージングに基づくこともできます。
サービスオーケストレーションアーキテクチャでは、コンシューマアプリケーションチームは、ユーザインターフェイス画面とアプリケーション固有のサービスにのみ焦点を当てる必要があるため、アプリケーション固有ではないテクノロジーの変動性と共通の基本機能からビジネスロジックとIPを保護します。すべての共通サービス (ビジネスサービス、非機能サービス、プラットフォームサービス) はクラウドプラットフォームでホストされサービスオーケストレーターとして機能するルーティングサービスによって呼び出されます。
図7のダイアグラムが示すように、共通サービスで使用されるすべてのテクノロジーとフレームワークは、コンシューマアプリケーションから完全に抽象化されています。
テクノロジーの抽象化
図7 クライアントアプリケーションからテクノロジーを抽象化するサービスオーケストレーターベースのソリューション
サービスオーケストレーションがクライアントアプリケーションからテクノロジーをどのように抽象化するかを見てみましょう。
図7に示すように、一元化されたサービスオーケストレーターを使用すると、クライアントアプリケーションはこれらのテクノロジーを認識する必要がありません。また、これらのテクノロジーはいずれもクライアントアプリに影響を与えずにアップグレードできます。
これまでこの記事で説明したサービスベースのアーキテクチャと同様、見た目と同じぐらいよいサービスオーケストレーションアーキテクチャにも、まだいくつかの課題があります。
- ルーティングサービスは、単一障害点になる可能性があります。
- ルーティングサービスは、ユースケースに関係する各サービスをネットワーク経由で呼び出す必要があるため、パフォーマンスのオーバーヘッドが発生します。
- サービスのネイティブ呼び出しはありません。
- 分散型のポリシー実施はありません。
これまでに説明した3つの異なるアーキテクチャ (従来の分散システム、マイクロサービスベースアーキテクチャ、サービスオーケストレーションベースのアプリケーション) の課題について、サービスメッシュとサイドカーと呼ばれる新しいクラウドネイティブデザインパターンのペアについて説明しましょう。
サービスメッシュとサイドカー
この記事で説明する最終的なアーキテクチャモデルは、サービスメッシュとサイドカーのデザインパターンに基づいており、サイドカー機能がサポートされている Kubernetes プラットフォームにすぐに適用できます。
図8に示すこのアーキテクチャでは、サービスオーケストレーションソリューションと同様に、さまざまなポリシーを定義および管理するための「コントロールプレーン」と呼ばれる中心的なコンポーネントがまだあります。
「データプレーン」と呼ばれるものの一部であるサイドカーコンテナは、実行時にビジネスサービスに自動的に注入 (inject) されます。これらのサイドカープロキシは、コントロールプレーンで定義され、データプレーンに複製されるポリシーを適用します。
サービスメッシュベースのソリューションは、分散システムアーキテクチャがセキュリティ、可観測性、およびトラフィック管理機能を向上させるのに役立ちます。
サービスメッシュソリューションの基礎となる基本原則は、集中型のポリシー管理と運用であり、分散型のポリシーの実行と実施 (両方の長所) があります。
図8 Kubernetesがホストするアプリのサービスメッシュとサイドカー
サービスメッシュ機能
サービスメッシュベースのソリューションは、下に示すように、接続性、信頼性、セキュリティ、および可観測性に関して、従来のマイクロサービスアーキテクチャと比較していくつかの利点を提供します。
接続性:
- トラフィック制御 (ルーティング、分割)
- ゲートウェイ: 入り口 (ingress), 出口 (egress)
- サービスディスカバリー
- A/B テスト, カナリア
- サービスタイムアウト、リトライ
信頼性:
- サーキットブレーカ
- フォールトインジェクション/カオステスト
セキュリティ:
- サービス間認証 (mTLS)
- 証明書 (Certificate) 管理
- ユーザ認証 (JSON Web Tokens)
- ユーザ認可 (ロールベースアクセス制御)
- 暗号化
可観測性:
- 監視
- テレメトリ、計測、メトリクス
- 分散トレース
- サービスグラフ
サービスメッシュテクノロジーはここ数年で多くの注目を集めており、Istio、Linkerd、Consul Connect などのいくつかの実装があります。この記事の焦点は、成功したマイクロサービスベースアーキテクチャの背後にあるアーキテクチャパターンについて説明することです。サービスメッシュ機能と実装の詳細については詳しく説明しません。
サービスメッシュテクノロジーの詳細に興味がある場合は、The InfoQ eMag - Service Mesh Ultimate Guide をご覧ください。
結論
マイクロサービス間の相互作用と通信を実装するには、さまざまな方法があります。サービスオーケストレーションは、コアアーキテクチャコンポーネントとして API ゲートウェイを使用して管理できます。API ゲートウェイによって提供される機能以外の追加機能が必要な場合は、それらの追加のクラウドネイティブアーキテクチャ要件にサービスメッシュとサイドカーを使用できます。
クラウドネイティブアプリケーションアーキテクチャのさまざまなレイヤ間の相互作用をデザインすることが重要です。これには、モデリング作業で一級市民としてデータ、サービス、イベントをモデル化する方法が含まれます。
この記事のパート 4では、クラウドネイティブアーキテクチャ導入の最後のピースであるクラウドネイティブ DevOpsについて説明します。CI/CD、コンテナ化、Kubernetes クラウドプラットフォームなどの DevOps プラクティスが、マイクロサービスやサービスオーケストレーションパターンとともに、クラウドの導入にどのように役立つかを見ていきます。
参考
- Adoption of Cloud-Native Architecture, Part 1: Architecture Evolution and Maturity
- Adoption of Cloud Native Architecture, Part 2: Stabilization Gaps and Anti-Patterns
- Pattern: Service Mesh
- Microservices Communication and Governance Using Service Mesh
- Microservices Interaction and Governance Model - Orchestration v Choreography
- マルチランタイム・マイクロサービスアーキテクチャ (Multi-Runtime Microservices Architecture)
- Responsible Microservices
- Introducing Istio Service Mesh for Microservices
著者について
Srini Penchikala氏 は、テキサス州オースティンにあるGeneral MotorsのGlobal Manufacturing ITのシニアITアーキテクトです。彼はソフトウェアアーキテクチャ、設計、開発で25年以上の経験があり、現在はクラウドネイティブアーキテクチャ、マイクロサービスとサービスメッシュ、クラウドデータパイプライン、継続的デリバリーに重点を置いています。Penchikala氏は、組織にエンタープライズクラウドネイティブサービスメッシュソリューションを実装する際の共同作成者およびリードアーキテクトです。Penchikala氏は、Big-Data Processing with Apache Spark を執筆し、Manningの Spring Roo in Action を共同執筆しました。彼は頻繁にカンファレンスの講演者であり、ビッグデータトレーナであり、さまざまな技術Webサイトにいくつもの記事を公開しています。
Marcio Esteves氏 は、テキサス州ヒューストンにあるTokyo Marine HCCのアプリケーション開発ディレクターであり、ソリューションアーキテクチャ、QA、および企業とビジネスのIT全体で協力して、グローバルにデプロイされるクラウドベースのシステムで収益を生み出すことに重点を置いた共通テクノロジーの導入を推進する開発チームを率いています。以前、Esteves氏はGeneral Motors IT Global Manufacturingのチーフアーキテクトであり、機械学習、ビッグデータ、IoT、AI/クラウドファーストマイクロサービスアーキテクチャなどのデジタルトランスフォーメーションを活用するテクノロジーを担当する一流のアーキテクトとクラウドネイティブエンジニアでした。Esteves氏はビジョンと戦略を開発し、いくつかの重要なビジネスアプリケーションで使用される自動的にスケールするマイクロサービスを使用して、GMでエンタープライズクラウドネイティブのサービスメッシュソリューションの実装を主導しました。彼はまた、オースティンのダウンタウンにあるVertifyDataの取締役会テクニカルアドバイザーも務めています。