そもそもコンテナって何?

記事タイトルとURLをコピーする

 技術1課の櫻井です。
 近頃、新サービスの開発や実装でコンテナを利用する企業も増えてきている中で、 「コンテナって名称は聞くけど実はどんなものなのかよくわかっていない」、「仮想化技術は触れたことがあるけどコンテナはさっぱり」という方もいらっしゃるのではないでしょうか。恥ずかしながら私自身がそうです。 そこで、自分の勉強も兼ねて今回はコンテナの基礎の基礎、そもそもコンテナはどのようなものなのか、EC2のような他の仮想化技術とどのように違うのかといった点を自分のような初学者の方にもわかりやすいようにまとめてみました。

コンテナと仮想化

 コンテナは仮想化技術の一種です。 仮想化とは物理的なハードウェアリソースを隠匿し、論理的なリソースをユーザーへ提供するための技術です。 AWSのほとんどのサービスが仮想化技術を利用しています。 例えば、EC2は論理的なリソースであり、私たちはEC2の配下にある物理的リソースを意識することはほとんどありません。

仮想化技術の種類

 コンテナ以外にも仮想化技術はあります。 現在主流の仮想化技術は3種類あり、そのうちの一つがコンテナとなっています。 コンテナがどのようなものか理解するためにまずは各仮想化技術の特徴を見てみましょう。

ホストOS型

 ホストOS型は物理ハードウェア上にOSをインストールし、そのOS上で仮想化ソフトウェアと仮想マシンを実行する仮想化技術です。 物理マシン上で動作するOSをホストOS、仮想マシン上で動作するOSをゲストOSと呼びます。 アプリケーションのように使えるため導入が簡単なのが特徴です。 一方で、ゲストOSの処理にホストOSの処理も行うのでオーバーヘッドが生じて処理速度が出にくいデメリットがあります。 VMwareのWorkstation PlayerやOracleのVirtualBoxがこれにあたります。

ハイパーバイザー型

 ハイパーバイザー型では、ホストOSの代わりにハイパーバイザーと呼ばれるソフトウェアと仮想マシンを物理ハードウェア上で実行します。 こちらの方式はハイパーバイザーが仮想マシンのリソースとホストシステムのリソースを対応付け、仮想マシンが独立したホストシステムのように振舞います。 ハイパーバイザー型はホストOSを介する処理のオーバーヘッドがないため、ホストOS型よりもパフォーマンスが高いです。 現行世代のインスタンスタイプのEC2は、AWS独自のハイパーバイザーであるNitro Hypervisor上で動作しているハイパーバイザー型にあたります。

コンテナ型

 コンテナはアプリケーションとそれが動くために必要なミドルウェア、 そしてOSの一部(ライブラリーや設定など)を一つにまとめそれぞれ独立して動作するようにする仮想化技術です。 先の二つのように実際にOSが動作する訳ではなく、OSに近い動作環境を再現している形となっています。 ホストOS上にインストールされたコンテナエンジンが各コンテナを生成・管理することで各アプリケーションが実行されます。

コンテナが動く仕組み

 三つの仮想化技術を比較してみてみるとホストOS型とハイパーバイザー型ではゲストOSが起動しており、従来の物理的なコンピュータを論理的に置き換えたような形となっています。 一方で、コンテナの場合(OSの一部は含まれますが)アプリケーションとミドルウェアだけで動作しているような形となります。 アプリケーションの土台としてOSが存在すると勉強した自分からするとイマイチこのアプリケーションとミドルウェアだけのイメージがつかなくて理解が難しいです。 そこで、コンテナが動く仕組みについてもう少し詳しく見てみましょう。

コンテナとカーネル

   先ほど「コンテナはアプリケーションとそれが動くために必要なミドルウェア、 そしてOSの一部(ライブラリーや設定など)」をまとめたものだと記載しました。 アプリケーションが動く際、内部でOSの中核であるカーネルの機能を呼び出して動作しています。 カーネルはアプリケーションとCPUやメモリといったハードウェアとの仲介を行っており、カーネルに対する呼び出しをシステムコールといいます。 カーネルがシステムコールを処理することでアプリケーションを動作させているのです。
 Linuxには、RedHat Enterprise Linux(RHEL)やCentOS、Ubuntu、Amazon Linuxなど様々なディストリビューションが存在しますが、基本的に共通のカーネルを使用しています。そのため、基本的にはアプリケーションの実行に必要なライブラリさえあれば、アプリケーションを動作できる仕様となっています。
 しかし、カーネルが共通していたとしてもRHELで動作するように作成したアプリケーションをAmazon LInuxで動作させようとする場合、OSの設定といった動作環境の違いにより動いたとしても正しく動作しない可能性があります。 そのため、先ほど述べた通りコンテナの中にはOSの一部が含まれ「OSに近い動作環境を再現している形」になるということです。
 従って、コンテナはアプリの動作に最低限必要な部分(アプリケーション・ミドルウェア・OSの一部)だけを含み、共通して利用できる部分(カーネル)は含まないことで非常に軽量な仮想環境を作成できる形となっている訳です。

コンテナとプロセス

 コンテナがOS無しでアプリケーションを動作できる仕組みはわかりましたが、個々のコンテナが独立した環境として動作する仕組みは不明です。 ホストOS型やハイパーバイザー型がコンピュータの中に論理的なコンピュータを何台も作成する形のためそれぞれが独立するのは想像しやすいですがコンテはアプリケーションやミドルウェアが含まれるだけでどのように独立しているかわかりづらいです。この点について詳しくみてみましょう。  コンテナは一言で表すと単なるプロセスです。 プロセスはOS上で実行しているプログラムのため、コンテナは先述のホストOS型やハイパーバイザー型とは異なり、 仮想環境が一つのプログラムとして独立して動作している形の仮想化技術となっています。 プロセスは通常、ファイルシステムやライブラリなどのシステムリソースを共有して動作します。 一方でコンテナの場合、通常のプロセスとは異なりプロセスの一部をグループ化して独立した環境として動作させており、各プロセスから他のプロセスは見えない形となっています。 貨物輸送のコンテナのように独立した空間にプロセスが入っている形のためコンテナという名称が付けられたそうです。 では、どのようにプロセスを独立させて動かしているのでしょうか。 最後にコンテナに使用されるLinuxカーネルの機能の一部であるnamespaceとcgroupsの役割を簡単に説明します。

namespace

namespace(名前空間)とは、プロセスを他のプロセスと分離する機能です。 先ほど、「プロセスは通常、ファイルシステムやライブラリなどのシステムリソースを共有して動作します」と記載しましたが、 このnamasepaceによってシステムリソースが各プロセスごとに分離されて動くようになります。 これにより、ユーザー権限やプロセスID、ファイルシステム、ネットワークインターフェイスといったUNIXシステムの基礎の部分を別々に管理することができます。 これらが別々に管理されることで、各プロセスは全く別のシステムのように動作することが可能となります。

cgroup

namespaceがシステムリソースを分離するのに対して、cgroupはCPUやメモリなどホストマシンの物理的なリソースを分離する機能です。 プロセスが用いるCPUの使用率やメモリの割当、デバイスへのアクセスをcgroupが制御します。 これにより、一つのプロセス(コンテナ)がリソースを大量に消費してしまい他のプロセスに影響が出ることを防いでいます。

まとめ

はじめにコンテナは仮想化技術の一種ということがわかりましたが、ホストOS型やハイパーバイザー型とは仮想化の方法が異なっていました。 ホストOS型やハイパーバイザー型はコンピューターの中に丸ごとコンピューターが作成されて動作しているような形でしたが、 一方でコンテナは各仮想環境一つ一つがプロセスとして動作しており、それらプロセスは通常のプロセスと異なる独立した環境で動作していました。そしてそしてそのような環境を実現するのがnamespaceやcgroupといったLinuxカーネルの機能というのが今回の話のまとめとなります。

私自身の感想ですが、Linuxカーネルの機能を用いて隔離された環境で動作するプロセスがコンテナということになりますが、やはりホストOS型やハイパーバイザー型とは全く異なる仮想化なのだなと感じます。一方で、全く見たこともない新しい技術というよりかはLinuxカーネル機能が使われているだけの技術と分かったのもコンテナという概念に対してのイメージが固まることにつながったかと思います。