次の方法で共有


コンテナー化 Microservices

Note

この電子ブックは 2017 年春に発行されて以降、改訂されていません。 このブックには今なお価値のある内容が多く含まれていますが、一部の記載内容は古くなっています。

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

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

Monolithic application scaling approach

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

マイクロサービス

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

まとめてスケーリングされる大規模なモノリシック アプリケーションと対照的に、マイクロサービスは個別にスケールアウトできます。 つまり、アプリケーションの他の領域を不必要にスケールアウトするのではなく、需要に応じるためにより多くの処理能力やネットワーク帯域幅を必要とする特定の機能領域をスケーリングできます。 図 8-2 は、このアプローチでマイクロサービスが個別にデプロイおよびスケーリングされ、複数のマシン上にサービスのインスタンスが作成される様子を示しています。

Diagram shows two apps with tiles representing different functional areas and six rectangles hosting various functional areas from both apps.

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

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

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

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

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

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

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

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

コンテナー詰め

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

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

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

Diagram shows a comparison between Virtual Machines and Containers, where virtual machines have three apps each siloed on a guest O S, with a hypervisor and a host O S, and the containers have three apps hosted in a container engine on a single OS.

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

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

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

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

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

企業がマイクロサービス ベースのアプリケーションを実装する際にはコンテナーを採用することが増えており、Docker は、ほとんどのソフトウェア プラットフォームとクラウド ベンダーによって採用されている標準のコンテナー実装になっています。

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

eShopOnContainers reference application back-end microservices

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

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

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

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

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

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

Diagram shows an app hosted on a mobile device connected to three Backend Microservices, each with its own Web A P I Container.

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

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

ヒント

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

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

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

マイクロサービスからマイクロサービスへの通信として一般的な 2 つのアプローチは、データのクエリ時の HTTP ベースの REST 通信と、複数のマイクロサービスに対して更新を通信するときの軽量非同期メッセージングです。

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

図 8-6 に示すように、イベント バスによって、コンポーネントが互いを明示的に認識する必要がないマイクロサービス間の発行-サブスクライブ通信が可能になります。

Publish-subscribe with an event bus

図 8-6: イベント バスを使用した発行-サブスクライブ

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

Asynchronous event-driven communication in the reference application

図 8-7: リファレンス アプリケーションの非同期イベントドリブン通信

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

One-to-many communication

図 8-9: 一対多通信

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

Note

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

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

まとめ

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

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