ブログ | NGINX

マイクロサービス導入戦略の選択

NGINX-F5 水平黒タイプ RGB の一部
クリス・リチャードソン サムネイル
クリス・リチャードソン
2016 年 2 月 10 日公開

編集者– この 7 部構成の記事シリーズはこれで完了です。

  1. マイクロサービス入門
  2. マイクロサービスの構築: APIゲートウェイの使用
  3. マイクロサービスの構築: マイクロサービス アーキテクチャにおけるプロセス間通信
  4. マイクロサービス アーキテクチャにおけるサービス検出
  5. マイクロサービス向けイベント駆動型データ管理
  6. マイクロサービス導入戦略の選択 (この記事)
  7. モノリスをマイクロサービスにリファクタリングする

また、記事の完全なセットと、NGINX Plus を使用したマイクロサービスの実装に関する情報を電子書籍「マイクロサービス」としてダウンロードすることもできます。 設計から展開まで。 また、マイクロサービス リファレンス アーキテクチャマイクロサービス ソリューション ページに関するシリーズもご覧ください。

これは、マイクロサービスを使用したアプリケーションの構築に関するシリーズの 6 番目の記事です。 最初の記事では、マイクロサービス アーキテクチャ パターンを紹介し、マイクロサービスを使用する利点と欠点について説明します。 以下の記事では、 API ゲートウェイの使用プロセス間通信サービス検出イベント駆動型データ管理など、マイクロサービス アーキテクチャのさまざまな側面について説明します。 この記事では、マイクロサービスを展開するための戦略について説明します。

動機

モノリシック アプリケーションを展開するということは、通常は大規模な単一のアプリケーションの同一のコピーを複数実行することを意味します。 通常は、N 台のサーバー (物理または仮想) をプロビジョニングし、各サーバーでアプリケーションの M インスタンスを実行します。 モノリシック アプリケーションのデプロイは必ずしも完全に簡単ではありませんが、マイクロサービス アプリケーションのデプロイよりもはるかに簡単です。

マイクロサービス アプリケーションは、数十または数百のサービスで構成されます。 サービスはさまざまな言語とフレームワークで記述されています。 それぞれが、独自の特定のデプロイメント、リソース、スケーリング、および監視要件を持つミニアプリケーションです。 たとえば、各サービスの需要に基づいて、各サービスのインスタンスを一定数実行する必要があります。 また、各サービス インスタンスには適切な CPU、メモリ、および I/O リソースが提供される必要があります。 さらに難しいのは、このような複雑さにもかかわらず、サービスの展開は高速で信頼性が高く、コスト効率が良くなければならないということです。

マイクロサービスのデプロイメント パターンにはいくつかの種類があります。 まず、ホストごとに複数のサービス インスタンス パターンを見てみましょう。

ホストパターンごとに複数のサービスインスタンス

マイクロサービスをデプロイする 1 つの方法は、ホストごとに複数のサービス インスタンス パターンを使用することです。 このパターンを使用する場合、1 つ以上の物理ホストまたは仮想ホストをプロビジョニングし、各ホストで複数のサービス インスタンスを実行します。 多くの点で、これはアプリケーション展開に対する従来のアプローチです。 各サービス インスタンスは、1 つ以上のホスト上の既知のポートで実行されます。 ホストマシンは一般的にペットのように扱われます

次の図はこのパターンの構造を示しています。

マイクロサービスアーキテクチャベースのアプリケーションを展開するためのホストごとの複数のサービスインスタンスパターン

このパターンにはいくつかのバリエーションがあります。 1 つのバリエーションは、各サービス インスタンスをプロセスまたはプロセス グループにすることです。 たとえば、Java サービス インスタンスをApache Tomcatサーバー上の Web アプリケーションとしてデプロイする場合があります。 Node.jsサービス インスタンスは、親プロセスと 1 つ以上の子プロセスで構成される場合があります。

このパターンのもう 1 つのバリエーションは、同じプロセスまたはプロセス グループ内で複数のサービス インスタンスを実行することです。 たとえば、同じ Apache Tomcat サーバーに複数の Java Web アプリケーションをデプロイしたり、同じ OSGI コンテナーで複数の OSGI バンドルを実行したりできます。

ホストごとに複数のサービス インスタンス パターンには、利点と欠点の両方があります。 大きな利点の 1 つは、リソースの使用が比較的効率的であることです。 複数のサービス インスタンスがサーバーとそのオペレーティング システムを共有します。 プロセスまたはプロセス グループが複数のサービス インスタンス (同じ Apache Tomcat サーバーと JVM を共有する複数の Web アプリケーションなど) を実行する場合は、さらに効率的になります。

このパターンのもう 1 つの利点は、サービス インスタンスのデプロイが比較的高速であることです。 サービスをホストにコピーして起動するだけです。 サービスが Java で記述されている場合は、JAR または WAR ファイルをコピーします。 Node.js や Ruby などの他の言語の場合は、ソース コードをコピーします。 どちらの場合でも、ネットワーク経由でコピーされるバイト数は比較的少なくなります。

また、オーバーヘッドがないため、サービスの開始は通常非常に高速です。 サービスが独自のプロセスである場合は、単にそれを開始するだけです。 それ以外の場合、サービスが同じコンテナ プロセスまたはプロセス グループで実行されている複数のインスタンスのうちの 1 つである場合は、コンテナに動的にデプロイするか、コンテナを再起動します。

魅力的ではあるものの、ホストごとに複数のサービス インスタンス パターンにはいくつかの重大な欠点があります。 大きな欠点の 1 つは、各サービス インスタンスが個別のプロセスでない限り、サービス インスタンスの分離がほとんどまたはまったく行われないことです。 各サービス インスタンスのリソース使用率を正確に監視することはできますが、各インスタンスが使用するリソースを制限することはできません。 動作が不適切なサービス インスタンスがホストのメモリまたは CPU をすべて消費する可能性があります。

複数のサービス インスタンスが同じプロセスで実行される場合、分離はまったく行われません。 たとえば、すべてのインスタンスが同じ JVM ヒープを共有する場合があります。 動作が不適切なサービス インスタンスにより、同じプロセスで実行されている他のサービスが簡単に中断される可能性があります。 さらに、各サービス インスタンスによって使用されるリソースを監視する方法はありません。

このアプローチのもう 1 つの大きな問題は、サービスを展開する運用チームが、その実行方法の具体的な詳細を知っておく必要があることです。 サービスはさまざまな言語やフレームワークで記述できるため、開発チームが運用チームと共有する必要がある詳細事項が多数あります。 この複雑さにより、展開中にエラーが発生するリスクが高まります。

ご覧のとおり、よく知られているにもかかわらず、ホストごとに複数のサービス インスタンス パターンにはいくつかの重大な欠点があります。 次に、これらの問題を回避するマイクロサービスを展開する他の方法を見てみましょう。

ホストパターンごとのサービスインスタンス

マイクロサービスをデプロイする別の方法は、ホストごとのサービス インスタンスパターンです。 このパターンを使用する場合、各サービス インスタンスを独自のホスト上で分離して実行します。 このパターンには 2 つの異なる特殊化があります。 仮想マシンごとのサービス インスタンスとコンテナーごとのサービス インスタンス。

仮想マシンパターンごとのサービスインスタンス

仮想マシンごとのサービスインスタンスパターンを使用する場合、各サービスをAmazon EC2 AMIなどの仮想マシン (VM) イメージとしてパッケージ化します。各サービスインスタンスは、その VM イメージを使用して起動される VM (たとえば、EC2 インスタンス) です。 次の図は、このパターンの構造を示しています。

マイクロサービス アーキテクチャ ベースのアプリケーションをデプロイするための仮想マシンごとのサービス インスタンス パターン

これは、Netflix がビデオストリーミング サービスを展開するために使用する主なアプローチです。 Netflix は、 Aminator を使用して各サービスを EC2 AMI としてパッケージ化します。 実行中の各サービスインスタンスは EC2 インスタンスです。

独自の VM を構築するために使用できるツールは多種多様です。継続的インテグレーション (CI) サーバー ( Jenkinsなど) を構成して Aminator を呼び出し、サービスを EC2 AMI としてパッケージ化することができます。Packer.ioは、 VM イメージを自動作成するためのもう 1 つのオプションです。 Aminator とは異なり、EC2、DigitalOcean、VirtualBox、VMware などのさまざまな仮想化テクノロジーをサポートしています。

Boxfuse社は VM イメージを構築する魅力的な方法を持っており、これは以下で説明する VM の欠点を克服します。 Boxfuse は、Java アプリケーションを最小限の VM イメージとしてパッケージ化します。 これらのイメージはビルドが速く、起動も速く、攻撃対象領域が限られているためより安全です。

CloudNative社には、EC2 AMI を作成するための SaaS サービスである Bakery があります。 マイクロサービスのテストに合格した後に Bakery を呼び出すように CI サーバーを構成できます。 Bakery は、サービスを AMI としてパッケージ化します。Bakery などの SaaS サービスを使用すると、AMI 作成インフラストラクチャのセットアップに貴重な時間を費やす必要がなくなります。

仮想マシンごとのサービス インスタンス パターンには、多くの利点があります。 VM の主な利点は、各サービス インスタンスが完全に分離して実行されることです。 CPU とメモリの量は固定されており、他のサービスからリソースを盗むことはできません。

マイクロサービスを VM としてデプロイするもう 1 つの利点は、成熟したクラウド インフラストラクチャを活用できることです。 AWS などのクラウドは、負荷分散や自動スケーリングなどの便利な機能を提供します。

サービスを VM としてデプロイするもう 1 つの大きな利点は、サービスの実装テクノロジがカプセル化されることです。 サービスが VM としてパッケージ化されると、ブラック ボックスになります。 VM の管理 API は、サービスをデプロイするための API になります。 展開がはるかにシンプルになり、信頼性が高まります。

ただし、仮想マシンごとのサービス インスタンス パターンにはいくつかの欠点があります。 1 つの欠点は、リソースの利用効率が低いことです。 各サービス インスタンスには、オペレーティング システムを含む VM 全体のオーバーヘッドがあります。 さらに、一般的なパブリック IaaS では、VM のサイズが固定されており、VM が十分に活用されない可能性があります。

ちなみに、パブリック IaaS では通常、VM がビジー状態かアイドル状態かに関係なく、VM に対して料金が請求されます。 AWS などの IaaS では自動スケーリングが提供されますが、需要の変化に迅速に対応することは困難です。 その結果、VM を過剰にプロビジョニングする必要があり、導入コストが増加します。

このアプローチのもう 1 つの欠点は、サービスの新しいバージョンの展開に時間がかかることです。 VM イメージは、通常、サイズが大きいため、ビルドに時間がかかります。 また、VM はサイズが大きいため、インスタンス化に時間がかかるのが一般的です。 また、通常、オペレーティング システムの起動にはある程度の時間がかかります。 ただし、Boxfuse によって構築された軽量 VM が存在するため、これは普遍的に当てはまるわけではないことに注意してください。

仮想マシンごとのサービス インスタンス パターンのもう 1 つの欠点は、通常、ユーザー (または組織内の他のユーザー) が、差別化につながらない大量の重労働を担当することになる点です。 VM の構築と管理のオーバーヘッドを処理する Boxfuse などのツールを使用しない限り、それはユーザーの責任となります。 この必要かつ時間のかかる作業は、コアビジネスの妨げになります。

次に、より軽量でありながら VM の利点の多くを備えたマイクロサービスをデプロイする別の方法を見てみましょう。

コンテナパターンごとのサービスインスタンス

コンテナーごとのサービス インスタンスパターンを使用すると、各サービス インスタンスは独自のコンテナー内で実行されます。 コンテナは、オペレーティング システム レベルでの仮想化メカニズムです。 コンテナは、サンドボックス内で実行される 1 つ以上のプロセスで構成されます。 プロセスの観点から見ると、プロセスには独自のポート名前空間とルート ファイル システムがあります。 コンテナのメモリと CPU リソースを制限できます。 一部のコンテナ実装には I/O レート制限もあります。 コンテナ テクノロジの例としては、 DockerSolaris Zonesなどがあります。

次の図は、このパターンの構造を示しています。

マイクロサービスアーキテクチャベースのアプリケーションをデプロイするためのコンテナごとのサービスインスタンスパターン

このパターンを使用するには、サービスをコンテナ イメージとしてパッケージ化します。 コンテナ イメージは、サービスを実行するために必要なアプリケーションとライブラリで構成されるファイル システム イメージです。 一部のコンテナ イメージは、完全な Linux ルート ファイル システムで構成されています。 その他はより軽量です。 たとえば、Java サービスをデプロイするには、Java ランタイム、Apache Tomcat サーバー、およびコンパイルされた Java アプリケーションを含むコンテナ イメージを構築します。

サービスをコンテナ イメージとしてパッケージ化したら、1 つ以上のコンテナを起動します。 通常、各物理ホストまたは仮想ホスト上で複数のコンテナを実行します。 コンテナを管理するには、 KubernetesMarathonなどのクラスター マネージャーを使用する場合があります。 クラスター マネージャーは、ホストをリソースのプールとして扱います。 コンテナに必要なリソースと各ホストで利用可能なリソースに基づいて、各コンテナを配置する場所を決定します。

コンテナごとのサービスインスタンス パターンには、利点と欠点の両方があります。 コンテナの利点は VM の利点と似ています。コンテナはサービス インスタンスを相互に分離します。 各コンテナで消費されるリソースを簡単に監視できます。 また、VM と同様に、コンテナはサービスを実装するために使用されるテクノロジーをカプセル化します。 コンテナ管理 API は、サービスを管理するための API としても機能します。

ただし、VM とは異なり、コンテナは軽量なテクノロジーです。 コンテナ イメージは通常、非常に高速に構築されます。 たとえば、私のラップトップでは、 Spring Bootアプリケーションを Docker コンテナとしてパッケージ化するのにわずか 5 秒しかかかりません。 また、長い OS ブート メカニズムがないため、コンテナーの起動も非常に速くなります。 コンテナが起動すると、実行されるのはサービスです。

コンテナの使用にはいくつかの欠点があります。 コンテナ インフラストラクチャは急速に成熟していますが、VM のインフラストラクチャほど成熟していません。また、コンテナはホスト OS のカーネルを相互に共有するため、VM ほど安全ではありません。

コンテナのもう 1 つの欠点は、コンテナ イメージの管理という、差別化されていない重労働の責任を負わなければならないことです。 また、 Google Container EngineAmazon EC2 Container Service (ECS) などのホスト型コンテナ ソリューションを使用している場合を除き、コンテナ インフラストラクチャと、場合によってはコンテナが実行される VM インフラストラクチャを管理する必要があります。

また、コンテナは、VM ごとに価格が設定されるインフラストラクチャにデプロイされることがよくあります。 その結果、前述のように、負荷の急増に対処するために VM をオーバープロビジョニングする追加コストが発生する可能性があります。

興味深いことに、コンテナと VM の区別は曖昧になる可能性があります。 前述したように、Boxfuse VM は構築と起動が高速です。 Clear Containers プロジェクトは、軽量 VM の作成を目指しています。 [編集者注: 2017 年 12 月に発表されたとおり、Clear Containers の開発は現在、オープンソースのKata Containersプロジェクトで継続されています。]ユニカーネルへの関心も高まっています。 Docker, Inc. は最近、Unikernel Systems を買収しました。

また、サーバーレス デプロイメントという新しい概念も普及しつつあります。これは、コンテナまたは VM のどちらにサービスをデプロイするかを選択する問題を回避するアプローチです。次に、これについて見てみましょう。

サーバーレスデプロイメント

AWS Lambda は、サーバーレスデプロイメントテクノロジーの一例です。 Java、Node.js、Python サービスをサポートします。 マイクロサービスをデプロイするには、それを ZIP ファイルとしてパッケージ化し、AWS Lambda にアップロードします。 また、リクエスト (イベント) を処理するために呼び出される関数の名前などを指定するメタデータも提供します。 AWS Lambda は、リクエストを処理するのに十分なマイクロサービスのインスタンスを自動的に実行します。 かかった時間と消費されたメモリに基づいて、リクエストごとに課金されます。 もちろん、細部に注意を払う必要がありますが、AWS Lambda には制限があることがすぐにわかります。 しかし、開発者であるあなたも、組織内の誰も、サーバー、仮想マシン、またはコンテナのいかなる側面についても心配する必要がないという考え方は、非常に魅力的です。

Lambda 関数はステートレスなサービスです。 通常、AWS サービスを呼び出してリクエストを処理します。 たとえば、画像が S3 バケットにアップロードされたときに呼び出される Lambda 関数は、DynamoDB の画像テーブルにアイテムを挿入し、Kinesis ストリームにメッセージを公開して画像処理をトリガーできます。 Lambda 関数はサードパーティの Web サービスを呼び出すこともできます。

Lambda 関数を呼び出す方法は 4 つあります。

  1. ウェブサービスリクエストを使用して直接
  2. S3、DynamoDB、Kinesis、Simple Email ServiceなどのAWSサービスによって生成されたイベントに応じて自動的に
  3. AWS API Gateway 経由で自動的にアプリケーションのクライアントからの HTTP リクエストを処理する
  4. cronのようなスケジュールに従って定期的に

ご覧のとおり、AWS Lambda はマイクロサービスをデプロイするのに便利な方法です。 リクエストベースの料金設定では、サービスが実際に実行した作業に対してのみ料金を支払います。 また、IT インフラストラクチャの責任を負う必要がないため、アプリケーションの開発に集中できます。

ただし、いくつか重要な制限があります。 サードパーティのメッセージ ブローカーからのメッセージを消費するサービスなど、長時間実行されるサービスを展開するために使用することを意図したものではありません。 リクエストは 300 秒以内に完了する必要があります。 理論上、AWS Lambda はリクエストごとに個別のインスタンスを実行する可能性があるため、サービスはステートレスである必要があります。 サポートされている言語のいずれかで記述する必要があります。 サービスはすぐに開始する必要があります。そうしないと、タイムアウトして終了する可能性があります。

まとめ

マイクロサービス アプリケーションのデプロイは困難です。 さまざまな言語やフレームワークで書かれたサービスは数十、あるいは数百あります。 それぞれが、独自の特定のデプロイメント、リソース、スケーリング、および監視要件を持つミニアプリケーションです。 仮想マシンごとのサービス インスタンスやコンテナーごとのサービス インスタンスなど、いくつかのマイクロサービス展開パターンがあります。 マイクロサービスをデプロイするためのもう 1 つの興味深いオプションは、サーバーレス アプローチである AWS Lambda です。 このシリーズの次の最後のパートでは、モノリシック アプリケーションをマイクロサービス アーキテクチャに移行する方法について説明します。

編集者– この 7 部構成の記事シリーズはこれで完了です。

  1. マイクロサービス入門
  2. マイクロサービスの構築: APIゲートウェイの使用
  3. マイクロサービスの構築: マイクロサービス アーキテクチャにおけるプロセス間通信
  4. マイクロサービス アーキテクチャにおけるサービス検出
  5. マイクロサービス向けイベント駆動型データ管理
  6. マイクロサービス導入戦略の選択 (この記事)
  7. モノリスをマイクロサービスにリファクタリングする

また、記事の完全なセットと、NGINX Plus を使用したマイクロサービスの実装に関する情報を電子書籍「マイクロサービス」としてダウンロードすることもできます。 設計から展開まで。 また、マイクロサービス リファレンス アーキテクチャマイクロサービス ソリューション ページに関するシリーズもご覧ください。

ゲストブロガーの Chris Richardson 氏は、Amazon EC2 向けの初期の Java PaaS (Platform as a Service) であるオリジナルのCloudFoundry.comの創設者です。 彼は現在、アプリケーションの開発および展開方法の改善について組織にコンサルティングを行っています。 彼はまた、 https://microservices.ioでマイクロサービスに関するブログを定期的に書いています。


「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"