コンテナの正体:「軽量な仮想マシン」ではなく「強化されたユーザ管理」である

目次

腑に落ちなかったこと

コンテナを学び始めたとき、ほとんどの解説が「仮想マシンとの比較」から入る。「仮想マシンはOSごと仮想化するが、コンテナはカーネルを共有するので軽い」。

だが腑に落ちなかった。「カーネルを共有する」とはどういうことか。仮想マシンの「軽量版」なら、何を軽くしているのか。そもそもコンテナは何を「仮想化」しているのか。

調べていくうちにわかった。コンテナは仮想マシンとは根本的に異なる技術である。 仮想マシンの延長で理解しようとすること自体が、理解を遠ざけていたのである。

一言で言えば、コンテナ ≒ 強化されたOSのユーザ管理 + ネットワーク仮想化である。この記事では、なぜそう言えるのかを順を追って説明する。

仮想マシンは「ないものを、あるように見せる」技術

まず仮想マシンの本質を整理する。

仮想化とは、物理リソースを抽象化し、実際の状態とは異なる状態に見せかけることである。仮想マシンの場合、1台の物理マシン上に、あたかも独立した物理マシンが複数台あるかのように見せかける。

各仮想マシンは、自分専用のCPU・メモリ・ディスク・ネットワークインターフェースを持っていると「思い込んでいる」。実際にはハイパーバイザがそう見せかけているだけで、仮想マシン上のOSは、自分が仮想環境にいることすら知らない。

キーワードは「見せかける」である。存在しないハードウェアを、存在するかのように振る舞わせる。これが仮想化の本質である。

コンテナは「見せかけ」ていない

コンテナは根本的に違う。何かを「見せかける」のではなく、OSのカーネル機能を使って、実際に環境を分離する

具体的には、Linuxカーネルが持つ2つの機能が核になる。

Namespace — 「見える範囲」を制限する

Namespaceは、プロセスから見えるOSリソースの範囲を制限する機能である。

通常、OSの上で動くプロセスは、すべてのプロセス一覧・すべてのファイルシステム・すべてのネットワークインターフェースを見ることができる。Namespaceはこの「見える範囲」を制限する。

Namespace制限する対象
PID namespace見えるプロセスの範囲
Mount namespace見えるファイルシステムの範囲
Network namespace見えるネットワークインターフェースの範囲
UTS namespaceホスト名
User namespaceUID/GIDのマッピング
IPC namespaceプロセス間通信の範囲

例えば、あるプロセスをPID namespaceに入れると、そのプロセスからは同じnamespace内のプロセスしか見えなくなる。他のプロセスが消えたわけではなく、見えなくなっただけである。

つまりこれは「仮想的なOSを作っている」のではなく、1つのOSの中で、見える範囲を区切っているだけである。

cgroups — 「使える量」を制限する

cgroups(Control Groups)は、プロセスが使えるリソースの量を制限する機能である。

  • このプロセスグループはCPUを最大50%まで
  • このプロセスグループはメモリを最大512MBまで

これも仮想化ではない。仮想的なCPUやメモリを作り出しているのではなく、実際のCPUとメモリの使用量に上限をかけているだけである。

仮想マシンとの決定的な違い

ここで「仮想マシンも見える範囲を制限しているのでは?」と思うかもしれないが、それは違う。

仮想マシンは各VMに完全に独立した仮想ハードウェアを与え、その上で独立したOSを起動する。各OS同士は、相手の存在すら知らない。制限しているのではなく、そもそも別世界を作っているのである。

例えていえば、コンテナは「同じ家の中に壁を立てて部屋を分ける」。仮想マシンは「家を丸ごと別に建てる」。

コンテナ仮想マシン
OS1つ。カーネルを共有VMごとに独立したOSが動く
隔離の方法1つのOSの中で見える範囲を制限別のOS同士なので最初から見えない
隔離の強度壁で仕切った部屋(カーネル共有ゆえに漏れうる)別の家(原理的に漏れない)

この違いが、セキュリティ特性の差にも直結する。コンテナはカーネルを共有しているため、カーネルの脆弱性を突かれると隔離が破れる可能性がある。仮想マシンはOS自体が別なので、そのリスクは原理的に低い。「軽さ」と「隔離の強度」はトレードオフの関係にある。

OSのユーザ管理と同じ構造

ここまで読んで、既視感がないだろうか。

OSのユーザ管理も、まったく同じことをやっている。

ユーザ管理コンテナ
見える範囲の制限ファイルパーミッション(他ユーザのファイルにアクセスできない)Namespace(他コンテナのプロセスやファイルが見えない)
使える量の制限ulimit(プロセス数やファイル数の上限)cgroups(CPU・メモリの上限)
仕組みOSカーネルの機能OSカーネルの機能

どちらも「OSが持つ機能を使って、環境を分離する」という点で同じ構造である。コンテナはユーザ管理の延長線上にある技術であり、仮想マシンの延長線上にはない。

ユーザ管理では「AさんのファイルをBさんが読めないようにする」レベルだったものを、コンテナではプロセス・ファイルシステム・ネットワークまで丸ごと分離できるように強化した。コンテナとは、強化されたユーザ管理なのである。

なぜ「仮想化」と混同されるのか

1つだけ、コンテナが仮想化技術を使う部分がある。ネットワークである。

コンテナのNetwork namespaceには、仮想ネットワークインターフェース(veth)が割り当てられる。これは実在しないネットワークインターフェースを作り出しているので、確かに「仮想化」である。

しかしこれはコンテナの本質ではなく、ネットワークを分離するための手段の1つに過ぎない。プロセスの隔離もファイルシステムの隔離もリソースの制限も、すべて仮想化ではなくカーネル機能による実際の分離である。

ネットワーク部分だけを見て「コンテナは仮想化技術」と言うのは、「家にエアコンがあるから家は家電だ」と言うようなものである。

まとめ

仮想マシンコンテナ
本質ないものを、あるように見せかけるあるものの、見える範囲と使える量を制限する
使う技術ハイパーバイザ(ハードウェアの抽象化)Namespace + cgroups(カーネル機能)
近い概念仮想化OSのユーザ管理
OS仮想マシンごとに独立したOSが動く全コンテナが1つのOSカーネルを共有する

コンテナを「軽量な仮想マシン」と理解すると、「なぜカーネルを共有するのか」「なぜ起動が速いのか」が永遠に腑に落ちない。仮想マシンの枠組みで考えている限り、答えは出ない。

コンテナは仮想マシンとは別の系譜の技術である。強化されたOSのユーザ管理に、ネットワーク仮想化を加えたもの。そう捉えれば、「カーネルを共有する」のは当然である。同じOSの機能を使っているのだから。「なぜ起動が速いのか」も自明になる。OSを起動していないからである。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次