クラウドコンピューティングが普及した現在、仮想マシン (VM) とコンテナという用語をおそらく両方とも耳にしたことがあるでしょう。どちらも、クラウドコンピューティングや従来のデータセンター(オンプレミスデータセンターを含む)で果たす役割があります。この記事では、この両者の違いを説明して、それらを比較対照し、いくつかのユースケースで、それぞれの長所を活かせる場面を確認します。

技術的な違い

まず、技術的な違いを整理しましょう。そのためには、オペレーティングシステム (OS) カーネルについての理解が必要です。カーネルは、すべての低レベルソフトウェアに対して、以下を担当します。

  • プロセスに対するCPU時間の公平な割り当て
  • RAMの管理
  • ハードディスク(磁気またはSSD)、キーボード、マウス、ディスプレイ、ネットワークインターフェイスなどのハードウェアデバイスに対するアクセス権の付与
  • ハードドライブ上のファイルにアクセスするための抽象化レイヤー(ファイルシステム)の提供
  • プロセス間通信の処理
  • ネットワークスタックのさまざまなネットワークレイヤー(IP、TCP、UDPなど)の実装
  • および、ここには書ききれない他の多くの側面

これは膨大であり、実際、カーネル(Linuxカーネルなど)は非常に大きく、何百万行ものコードから構成されています。

では、VMとコンテナで技術的に大きく異なる部分は何でしょうか。VMは独自のカーネルを実行し、コンテナはホストのカーネルを使用するという部分です。次の小さな図にこれを視覚的に示します。

Containers vs. VMs diagram chart

図1:コンテナとVM

コンテナを「軽量VM」と呼ぶ人もいますが、これは大きな誤解を招くものです。コンテナ内では少数のプロセス(多くの場合単一のプロセス)しか実行されません。コンテナ内で完全なオペレーティングシステムを実行することはほぼ不可能です。

一方、VMは、それ自体が独立したオペレーティングシステムであり、実際のハードウェア上で実行されていると「信じています」。そのハードウェアが、実際にはハイパーバイザー(ホストカーネル内で実行されているソフトウェア)を介してシミュレートされているものであることは、まったく認識していません。

VMについて

VMは、実際のハードウェア上で実行されている別のOS(ホストOS)上で動作するOS(ゲストOS)と見なすことができます。VMを実行するには、ホストOSにハイパーバイザーが必要です。これにより、シミュレートされたハードウェアを備えた仮想化レイヤーが提供されるため、ゲストOSは実際のハードウェア上で実行されているように認識します。これ以外の点では、ゲストOSは標準OSとまったく同じように動作します。

重要な点:クラウドベンダーがインスタンスを実行すると、クラウドベンダーではVMが実際に起動されます。

VMを使用する利点は次のとおりです。

  • ゲストOSは、標準OSとまったく同じように動作し、実際のハードウェア上ではなくハイパーバイザー上で実行されていることを認識しません。
  • VMを単一ファイルとして「保存」し、別の場所に移動したり複製したりできます。

欠点は次のとおりです。

  • VMはリソース消費(ディスク容量、CPU、RAM)が大きくなります。これは、それ自体が完全なOSであるためです。
  • VMは完全なOSであるため、多くのメンテナンスが必要です。この問題は、インフラストラクチャがイミュータブル(変更不可)になるように設計することで回避できます。
  • VMは、ハイパーバイザーレイヤーがあるため、ホストOSよりもわずかに低速になりますが、現在ではこれは最小限に抑えられています。
  • VMには多くのプロセスとサービスが含まれているため、通常、VMの起動に多少時間がかかります。

コンテナについて

それでは、コンテナについて見ていきましょう。コンテナを理解する良い方法は、コンテナをホストカーネル上で実行されている1つ以上のプロセスとして考えることです。ただし、ホストカーネルは、それらの各プロセスを独自の隔離された環境に保持します。つまり、これらの各プロセスは、当該カーネルで実行されている他のプロセスを認識できません。同じコンテナ内のプロセスは互いを認識できますが、他のコンテナまたはホストカーネル内で実行されているプロセスを認識することはできません。

ホストカーネルでコンテナを実行するには、上記のように、プロセスを隔離できるソフトウェアテクノロジーが必要です。Linuxカーネルは、このテクノロジーを提供していて、それは「名前空間」と呼ばれています。

ホストOSのカーネルを共有しているため、コンテナ内で別の完全なOSを実行することは不可能であることがわかります。したがって、コンテナは、「軽量VM」ではなく、プロセスが含まれている閉じられたボックスとして考えることが適切でしょう。プロセスはボックス内で実行できますが、あるボックスから他のボックスに移動することはできません。

詳細は省きますが、ホストカーネルを微調整して、特定のコンテナ内のプロセスがボックスの外にあるものを「見たり」、「触れたり」できるようになることを知っておくとよいでしょう。ただし、これは大きなセキュリティリスクとなるため、可能な限り避ける必要があります。

では、コンテナを使用する利点は何でしょうか。

  • コンテナは、特定のワークロードに必要なプロセスのみを実行するという意味で「軽量」であり、VMと比較してCPU、RAM、およびディスク容量を節約できます。
  • 通常、コンテナはすばやく起動しますが、これはそこで実行されるソフトウェアによって異なります。いずれにせよ、VM内で実行されている同じソフトウェアよりも高速に起動できます。
  • 多くのアプリケーションの膨大な数のコンテナイメージを提供する、Docker Hubなどのパブリックレジストリーがあります。
  • 攻撃対象領域はVMに比べて小さくなります。

ただし、コンテナにも不利な点があります。

  • コンテナ内で完全なOSを実行することはできません。
  • 理論的には、1つのコンテナでエクスプロイトが発生すると、他のコンテナでもエクスプロイトが発生する可能性があります。ただし、現在ではコンテナの実行に使用されるLinux名前空間テクノロジーが非常に成熟し、安全になったため、その可能性は非常に低くなっています。
  • コンテナを単一ファイルに保存して移動することはできません。
  • ルートファイルシステムはエフェメラルです。つまり、ルートファイルシステムに書き込まれたものはコンテナを終了するとすべて破棄されます。

VMとコンテナの比較

次に、VMとコンテナの実際的な違いに移りましょう。言うまでもなく最初に注意すべきことは、VM内でコンテナを実行することはできるがその逆はできない、ということです。

VMとコンテナには、それぞれ異なる目的があります。VMは、完全なOSを実行し、長期間使用するように設計されています。一方、コンテナは、特定のワークロードを実行し、本質的にエフェメラルかつイミュータブルです。その結果、コンテナが長期ストレージ(例えば、コンテナを再起動した後も存続する永続ストレージ)を必要とする場合は、ボリュームをマウントする必要があります。このボリュームは、個別に宣言して管理する必要があります。

一般的に、コンテナは、単一のタスクに焦点を当てて設計されているため、VMよりも機敏に操作できます。実際、VMが必要とされるユースケースでは、その代わりにコンテナを使用することは通常困難です。しかし、コンテナを使用できるユースケースでは、通常、コンテナとVMのどちらでも選択できます(ただし、これら2つのオプションではアーキテクチャが大きく異なります)。

おそらくKubernetesのようなコンテナオーケストレーションツールについて耳にしたことがあるでしょう。コンテナを使用する場合は、このようなツールがおそらく必要になります。ツールには、独自の学習曲線とセキュリティに関する考慮事項があります。クラウドベンダーのVMを使用する場合は、通常、自動スケーリンググループやロードバランサーなど、そのベンダーが提供する管理ツールのみで十分です。従来のデータセンターでVMを使用している場合は、VMware vSphereのようなVM指向のオーケストレーションツールが必要になるでしょう。これにも独自の学習曲線(おそらくコンテナオーケストレーションツールよりも急勾配)があります。

最後になりますが、コンテナは、内部ロードバランサーの使用に代わるアーキテクチャであるサービスメッシュのセットアップに適しています。

Service mesh vs. load balancers diagram chart

図2:サービスメッシュとロードバランサー

上の図から、2番目のアーキテクチャは1番目のアーキテクチャよりも多くのリソースを消費することが直感的にわかります。例えば、HashiCorp Consulでもサービスメッシュを作成できますが、Kubernetesクラスター上でIstioなどを使用するよりも煩雑で設定が困難です。

セキュリティの側面

表面的には似ていますが、VMとコンテナのセキュリティ上の課題は大きく異なります。最初に、両方のテクノロジー(ハイパーバイザーとカーネル名前空間)を可能にするソフトウェアレイヤーは、現在非常に成熟しており、非常に安全であるため、セキュリティ面ではどちらも問題にはなりません。

VMは基本的にOS全体を実行するため、システム全体をセキュリティで保護するために必要な、以下に示すすべての手順がVMに必要となります。

  • OSハードニング
  • ウイルス対策ソフトウェアの実装
  • 定期的および適時のパッチの適用(イミュータブルインフラストラクチャを使用している場合は回避可能)
  • rootユーザーではなく通常のユーザーとしてのプロセスの実行
  • SSHサーバーのハードニング
  • ファイアウォールの設定
  • 攻撃対象領域の縮小(不要なソフトウェアの削除)
  • イメージ構築時の脆弱性の特定(スキャナー使用)
  • 実行時に脆弱性を特定するためのツールの導入

このリストからわかるように、VMをセキュリティで保護するのは大変な作業です。その多くはVMの実行に使用されるイメージを構築するときに行われますが、実行時に脆弱性や侵害されたシステムを検知するために、かなりの量の作業が行われます。

対照的に、コンテナのセキュリティ確保はより簡単です。

  • コンテナが特権モードで実行されないように確認します。
  • rootユーザーではなく通常のユーザーとしてプロセスを実行します。
  • ファイルシステムの権限が可能な限り制限されていることを確認します。
  • イメージ構築時にスキャナーを使用して脆弱性を特定します。

コンテナの実行に関連するランタイムセキュリティの側面はまだありますが、通常はVMよりも処理と実装が簡単です。

どちらの場合も、上記のVMのケースでホストOSをセキュリティで保護するために説明したすべての手順は、VM/コンテナを実行するホストOSにも当てはまります。

クラウドストライクは、ウイルスやその他の悪意のあるソフトウェア、およびネットワーク攻撃からワークロードを保護するためのさまざまなソリューションを提供できます。

VMとコンテナの違いは、技術レベルでは非常に簡単に理解できます。それぞれに関連するユースケースを見ると、それらの相違がより明確で興味深いものになります。

Dockerが作成されて以来、コンテナの使用は着実に増加しています。それらは機敏で、不変性を強制します。さらに、Kubernetesなどの強力なオーケストレータと組み合わせることで、VMよりも大きな利点が得られます。これが、コンテナが徐々に主流になっている理由ですが、一部の組織では従来のVMを長期間使用し続けるでしょう。