コンテナー化 Microservices

Note

この電子ブックは 2017 年の春に発行され、それ以来更新されていません。 貴重なままの本に多くがありますが、資料の一部は時代遅れです。

クライアント/サーバー アプリケーションの開発においては、各層で特定のテクノロジを使用する階層化されたアプリケーションの構築に重点が置かれました。 このようなアプリケーションは、多くの場合 、モノリシック アプリケーションと呼ばれ、ピーク負荷用に事前にスケーリングされたハードウェアにパッケージ化されます。 この開発アプローチの主な欠点は、各層のコンポーネント間の緊密な結合、そのため個々のコンポーネントを簡単にスケーリングできないこと、テストのコストです。 単純な更新は、残りの層に予期しない影響を及ぼす可能性があるため、アプリケーション コンポーネントを変更するには、そのレベル全体を再テストして再デプロイする必要があります。

特にクラウドの時代に関して、個々のコンポーネントを簡単にスケーリングできないということです。 モノリシック アプリケーションにはドメイン固有の機能が含まれており、通常はフロントエンド、ビジネス ロジック、データ ストレージなどの機能レイヤーで分割されます。 モノリシック アプリケーションは、図 8-1 に示すように、アプリケーション全体を複数のマシンに複製することによってスケーリングされます。

モノリシック アプリケーションのスケーリング アプローチ

図 8-1: モノリシック アプリケーションスケーリングアプローチ

マイクロサービス

マイクロサービスは、アプリケーションの開発と展開に対する異なるアプローチを提供します。これは、最新のクラウド アプリケーションの機敏性、スケール、信頼性の要件に適したアプローチです。 マイクロサービス アプリケーションは、アプリケーションの全体的な機能を提供するために連携する独立したコンポーネントに分解されます。 マイクロサービスという用語は、各マイクロサービスが 1 つの関数を実装できるように、独立した懸念事項を反映するのに十分な小さなサービスでアプリケーションを構成する必要があることを強調しています。 さらに、各マイクロサービスには適切に定義されたコントラクトがあるため、他のマイクロサービスが通信してデータを共有できます。 マイクロサービスの一般的な例としては、ショッピング カート、在庫処理、購入サブシステム、支払い処理などがあります。

マイクロサービスは、一緒にスケーリングする巨大なモノリシック アプリケーションと比較して、独立してスケールアウトできます。 つまり、需要をサポートするためにより多くの処理能力またはネットワーク帯域幅を必要とする特定の機能領域は、アプリケーションの他の領域を不必要にスケールアウトするのではなく、スケールアウトできます。 図 8-2 は、マイクロサービスが個別にデプロイおよびスケーリングされ、マシン間でサービスのインスタンスを作成するこのアプローチを示しています。

図は、タイルが異なる機能領域を表す 2 つのアプリと、両方のアプリのさまざまな機能領域をホストする 6 つの四角形を示しています。

図 8-2: マイクロサービス アプリケーションのスケーリング アプローチ

マイクロサービスのスケールアウトは、ほぼ瞬時に行うことができるため、アプリケーションは負荷の変化に適応できます。 たとえば、アプリケーションの Web に接続する機能の 1 つのマイクロサービスが、追加の受信トラフィックを処理するためにスケールアウトする必要があるアプリケーション内の唯一のマイクロサービスである可能性があります。

アプリケーションのスケーラビリティのための従来のモデルには、永続的なデータを格納する共有の外部データストアを含む、負荷分散されたステートレスな層があります。 ステートフルなマイクロサービスは独自の永続的なデータを (通常は配置されたサーバーにローカルに格納して) 管理し、ネットワーク アクセスのオーバーヘッドとサービス間操作の複雑さを回避します。 これにより、可能な最速のデータ処理が可能になり、キャッシュ システムが不要になります。 さらに、スケーラブルなステートフル マイクロサービスは通常、データ サイズを管理し、1 台のサーバーでサポートできるスループットを転送するために、インスタンス間でデータをパーティション分割します。

マイクロサービスを使用すると、独立した更新もサポートされます。 マイクロサービス間の疎結合は、迅速かつ信頼性の高いアプリケーションの進化をもたらします。 独立した分散の性質により、ローリング更新がサポートされます。このローリング更新では、1 つのマイクロサービスのインスタンスのサブセットのみがいつでも更新されます。 したがって、問題が検出された場合は、すべてのインスタンスが欠陥のあるコードまたは構成で更新される前に、バグを含む更新をロールバックできます。 同様に、マイクロサービスには通常、スキーマのバージョン管理が使用されるため、どのマイクロサービス インスタンスと通信しているかに関係なく、更新の適用時に一貫したバージョンがクライアントに表示されます。

したがって、マイクロサービス アプリケーションにはモノリシック アプリケーションよりも多くの利点があります。

  • 各マイクロサービスが比較的小さく、管理しやすく進化させやすい。
  • 他のサービスとは関係なく各マイクロサービスを開発して展開できます。
  • 各マイクロサービスを個別にスケールアウトできます。 たとえば、カタログ サービスまたはショッピング バスケット サービスを注文サービスよりも大きくスケールアウトすることが必要な場合があります。 そのため、結果として得られるインフラストラクチャでは、スケールアウト時にリソースがより効率的に消費されます。
  • 各マイクロサービスで問題が分離されます。 たとえば、サービスに問題がある場合、影響を受けるのはそのサービスだけです。 他のサービスは引き続き要求を処理できます。
  • 各マイクロサービスで最新のテクノロジを利用できます。 マイクロサービスは自律的であり並行して実行されるため、モノリシック アプリケーションで使用される可能性のある古いフレームワークを強制的に使用するのではなく、最新のテクノロジとフレームワークを使用できます。

ただし、マイクロサービス ベースのソリューションには、次の潜在的な欠点もあります。

  • アプリケーションをマイクロサービスに分割する方法を選択するのは困難な場合があります。各マイクロサービスは、データ ソースに対する責任を含め、端から端まで完全に自律的である必要があります。
  • 開発者はサービス間通信を実装する必要がありますが、それによってアプリケーションに複雑さと待機時間が加わります。
  • 複数のマイクロサービス間のアトミック トランザクションは、通常は可能ではありません。 したがって、ビジネス要件は、マイクロサービス間の最終的な整合性を容認する必要があります。
  • 実稼働環境では、多数の独立したサービスからなるシステムの展開と管理には運用上の複雑さが伴います。
  • クライアントからマイクロサービスへの直接通信は、マイクロサービスのコントラクトをリファクターすることを困難にする場合があります。 たとえば、時間の経過に伴い、システムをサービスに分割する方法を変更することが必要になる場合があります。 1 つのサービスを 2 つ以上のサービスに分割することもあれば、2 つのサービスをマージすることもあります。 クライアントがマイクロサービスと直接的に通信している場合、このリファクタリングによって、クライアント アプリとの互換性が破綻する可能性があります。

コンテナー詰め

コンテナー化は、アプリケーションとそのバージョン管理された依存関係のセットに加えて、配置マニフェスト ファイルとして抽象化された環境構成をコンテナー イメージとしてまとめてパッケージ化し、1 つの単体としてテストしたうえで、ホスト オペレーティング システムに展開するソフトウェア開発のアプローチです。

コンテナーは、分離され、リソース制御された、ポータブル オペレーティング環境です。他のコンテナーやホストのリソースに触れることなくアプリケーションを実行できます。 したがって、コンテナーは、新しくインストールされた物理的なコンピューターまたは仮想マシンと同様に認識され、動作します。

図 8-3 に示すように、コンテナーと仮想マシンには多くの類似点があります。

図は、Virtual Machinesとコンテナーの比較を示しています。仮想マシンには、それぞれ 3 つのアプリがゲスト OS でサイロ化されており、ハイパーバイザーとホスト OS があり、コンテナーには 1 つの OS 上のコンテナー エンジンで 3 つのアプリがホストされています。

図 8-3: 仮想マシンとコンテナーの比較

コンテナーは物理または仮想マシンと同様に、オペレーティング システムを実行し、ファイル システムがあり、ネットワーク経由でアクセスできます。 ただし、コンテナーの背後にあるテクノロジおよび概念は仮想マシンとは大きく異なります。 仮想マシンには、アプリケーション、必要な依存関係、完全なゲスト オペレーティング システムが含まれます。 コンテナーの場合、アプリケーションとその依存関係が含まれますが、他のコンテナーとオペレーティング システムを共有し、ホスト オペレーティング システム上で分離されたプロセスとして実行されます (コンテナーごとに特殊な仮想マシン内で実行される Hyper-V コンテナーは除きます)。 したがって、コンテナーはリソースを共有し、通常は仮想マシンよりも必要なリソースが少なくなります。

コンテナー指向の開発と展開のアプローチの利点は、一貫性のない環境セットアップとそれらに伴う問題から発生する問題の大部分が排除されることです。 さらに、コンテナーでは、必要に応じて新しいコンテナーをインスタンス化することで、迅速なアプリケーション スケールアップの機能が可能になります。

コンテナーを作成および操作する際の主な概念は次のとおりです。

  • コンテナー ホスト: コンテナーをホストするように構成された物理マシンまたは仮想マシン。 1 つ以上のコンテナーがコンテナー ホストで実行されます。
  • コンテナー イメージ: イメージは、互いに積み重ねられた階層化されたファイルシステムの和集合で構成され、コンテナーの基礎となります。 イメージには状態がなく、さまざまな環境に展開されても変更されることはありません。
  • コンテナー: コンテナーはイメージのランタイム インスタンスです。
  • コンテナーの OS イメージ: コンテナーは、イメージから展開されます。 コンテナーのオペレーティング システム イメージは、コンテナーを構成する潜在的に多数のイメージ レイヤーのうち、最初のレイヤーです。 コンテナーのオペレーティング システムは不変であり、変更することはできません。
  • コンテナー リポジトリ: コンテナー イメージが作成されるたびに、イメージとその依存関係がローカル リポジトリに格納されます。 これらのイメージは、コンテナー ホストで何度も再利用できます。 コンテナー イメージは、さまざまなコンテナー ホスト間で使用できるように、Docker Hub などのパブリックまたはプライベート レジストリにも格納できます。

マイクロサービス ベースのアプリケーションを実装する場合、企業はコンテナーを採用する傾向が高まっています。Docker は、ほとんどのソフトウェア プラットフォームとクラウド ベンダーで採用されている標準的なコンテナー実装となっています。

eShopOnContainers 参照アプリケーションは、図 8-4 に示すように、Docker を使用して 4 つのコンテナー化されたバックエンド マイクロサービスをホストします。

eShopOnContainers 参照アプリケーション バックエンド マイクロサービス

図 8-4: eShopOnContainers 参照アプリケーションバックエンド マイクロサービス

参照アプリケーションのバックエンド サービスのアーキテクチャは、マイクロサービスとコンテナーが連携する形の複数の自律的なサブシステムに分解されます。 各マイクロサービスには、ID サービス、カタログ サービス、注文サービス、バスケット サービスという 1 つの機能領域があります。

各マイクロサービスには独自のデータベースがあり、それによって、他のマイクロサービスから完全に切り離すことができます。 必要に応じて、アプリケーション レベルのイベントを使用して、異なるマイクロサービスのデータベース間の一貫性が実現されます。 詳細については、「 マイクロサービス間の通信」を参照してください。

参照アプリケーションの詳細については、「.NET マイクロサービス: コンテナー化された .NET アプリケーションのアーキテクチャ」を参照してください。

クライアントとマイクロサービス間の通信

eShopOnContainers モバイル アプリは、図 8-5 に示すように、 クライアントからマイクロサービスへの直接 通信を使用して、コンテナー化されたバックエンド マイクロサービスと通信します。

図は、3 つのバックエンド マイクロサービスに接続されたモバイル デバイスでホストされているアプリを示しています。それぞれに独自の Web A P I コンテナーが含まれています。

図 8-5: クライアントからマイクロサービスへの直接通信

クライアントからマイクロサービスへの直接通信では、モバイル アプリは、マイクロサービスごとに異なる TCP ポートを使用して、パブリック エンドポイントを介して各マイクロサービスに直接要求を行います。 実稼働環境では、そのエンドポイントは通常、マイクロサービスのロード バランサーにマップされ、要求は使用可能なマイクロサービス インスタンス間に分散されます。

ヒント

API ゲートウェイ通信の使用を検討してください。 クライアントからマイクロサービスへの直接通信には、大規模で複雑なマイクロサービス ベースのアプリケーションを構築するときに欠点が発生する可能性がありますが、小規模なアプリケーションには十分ではありません。 数十個のマイクロサービスを使用して大規模なマイクロサービス ベースのアプリケーションを設計する場合は、API ゲートウェイ通信の使用を検討してください。 詳細については、「.NET マイクロサービス: コンテナー化された .NET アプリケーションのアーキテクチャ」を参照してください。

マイクロサービス間の通信

マイクロサービス ベースのアプリケーションは分散システムであり、複数のマシンで実行されている可能性があります。 通常、各サービス インスタンスはプロセスです。 そのため、サービスは、各サービスの性質に応じて、HTTP、TCP、Advanced Message Queuing Protocol (AMQP) などのプロセス間通信プロトコル、またはバイナリ プロトコルを使用して対話する必要があります。

マイクロサービス間通信の 2 つの一般的な方法は、データのクエリ時の HTTP ベースの REST 通信と、複数のマイクロサービス間で更新を通信する場合の軽量な非同期メッセージングです。

非同期メッセージング ベースのイベント ドリブン通信は、複数のマイクロサービス間で変更を伝達する場合に重要です。 このアプローチでは、ビジネス エンティティを更新した場合など、注目すべきことが発生したときにマイクロサービスによってイベントが発行されます。 その他のマイクロサービスは、これらのイベントにサブスクライブします。 その後、マイクロサービスがイベントを受信すると、独自のビジネス エンティティが更新され、さらに多くのイベントが発行される可能性があります。 この発行とサブスクライブ機能は、通常、イベント バスで実現されます。

イベント バスを使用すると、図 8-6 に示すように、コンポーネントが相互に明示的に認識される必要なく、マイクロサービス間のパブリッシュ/サブスクライブ通信が可能になります。

イベント バスを使用したパブリッシュ/サブスクライブ

図 8-6: イベント バスを使用したパブリッシュ/サブスクライブ

アプリケーションの観点から見ると、イベント バスは、インターフェイスを介して公開される発行とサブスクライブのチャネルにすぎません。 ただし、イベント バスの実装方法は異なる場合があります。 たとえば、イベント バスの実装では、RabbitMQ、Azure Service Bus、または NServiceBus や MassTransit などの他のサービス バスを使用できます。 図 8-7 は、eShopOnContainers 参照アプリケーションでのイベント バスの使用方法を示しています。

参照アプリケーションでの非同期イベント ドリブン通信

図 8-7: 参照アプリケーションでの非同期イベント ドリブン通信

RabbitMQ を使用して実装された eShopOnContainers イベント バスにより、1 対多の非同期発行/サブスクライブ機能が提供されます。 つまり、イベント発行後に複数のサブスクライバーが同じイベントをリッスンしている可能性があります。 図 8-9 は、この関係を示しています。

一対多の通信

図 8-9: 一対多通信

この一対多の通信アプローチでは、イベントを使用して複数のサービスにまたがるビジネス トランザクションを実装し、サービス間の最終的な一貫性を確保します。 最終的な整合性のあるトランザクションは、一連の分散ステップで構成されます。 そのため、ユーザー プロファイル マイクロサービスは UpdateUser コマンドを受信すると、データベース内のユーザーの詳細を更新し、UserUpdated イベントをイベント バスに発行します。 バスケット マイクロサービスと注文マイクロサービスの両方がこのイベントを受信するようにサブスクライブし、応答としてそれぞれのデータベースの購入者情報を更新しました。

注意

RabbitMQ を使用して実装される eShopOnContainers イベント バスは、概念実証としてのみ使用することを目的としています。 運用システム向けには、代替イベント バスの実装を検討してください。

イベント バスの実装の詳細については、「 .NET マイクロサービス: コンテナー化された .NET アプリケーションのアーキテクチャ」を参照してください。

まとめ

マイクロサービスは、アプリケーションの開発と展開のアプローチを提供します。これは、最新のクラウド アプリケーションの機敏性、スケール、信頼性の要件に適したアプローチです。 マイクロサービスのメインの利点の 1 つは、個別にスケールアウトできることです。つまり、需要が増加していないアプリケーションの領域を不必要にスケーリングすることなく、需要をサポートするためにより多くの処理能力またはネットワーク帯域幅を必要とする特定の機能領域をスケールできます。

コンテナーは、分離され、リソース制御された、ポータブル オペレーティング環境です。他のコンテナーやホストのリソースに触れることなくアプリケーションを実行できます。 マイクロサービス ベースのアプリケーションを実装する場合、企業はコンテナーを採用する傾向が高まっています。Docker は、ほとんどのソフトウェア プラットフォームとクラウド ベンダーで採用されている標準的なコンテナー実装となっています。