【入門編】 コンテナ仮想化技術(Docker / LXC)とハイパーバイザー型仮想化のシステムコール及びカーネル共有の比較 – クラウドインフラと仮想化ネットワーク実践ガイド

こんにちは!現場のSREとして日々クラウドやKubernetesの海を泳いでいると、「コンテナって結局、仮想マシンと何が違うの?」という疑問を、新人エンジニアの方から本当によく尋ねられます。

教科書を開くと、「ハイパーバイザー型はハードウェアをエミュレートし…」「コンテナはカーネルを共有し…」といった小難しい言葉が並んでいて、眠くなっちゃいますよね。

今回は、パケットやシステムコールといった複雑な内部の動きを、私たちの身近な「郵便配達」の仕組みに例えて、優しく楽しく紐解いていきたいと思います。一歩ずつ、肩の力を抜いて理解していきましょう!

—

仮想化の基本:マンションの「一棟まるごと」か「ルームシェア」か

まずは、仮想化技術の全体像をイメージしてみましょう。インフラの世界における仮想化には、大きく分けて「ハイパーバイザー型(完全仮想化)」と、「コンテナ型(Docker/LXC)」の2つがあります。

  • ハイパーバイザー型(VMwareやAWS EC2など):

ひとつの巨大な物理サーバーの上に、見えない管理人(ハイパーバイザー)が住んでいて、その下に全く独立した「一戸建ての家」を何軒も建てているような状態です。それぞれの家には独自の水道も電気(=ゲストOS)が通っています。

  • コンテナ型(Dockerなど):

ひとつの大きなマンションがあり、建物全体の水道や電気のメーター(=ホストOSのカーネル)は共有しつつ、部屋の中だけを鍵付きのパーテーション(=名前空間やcgroups)でピシャリと区切って、他人から見えないように暮らしている「ルームシェア」のような状態です。

この「基盤を共有するかどうか」という違いが、システムの仕組みやパフォーマンスに劇的な差を生み出すんです。

—

郵便配達で例える「システムコール」と「カーネル共有」のドラマ

コンピュータのプログラムは、CPUやメモリ、ディスクといったハードウェアに直接触ることができません。必ず、ホストOSの心臓部である「カーネル(Kernel)」という管理人さんにお願い(システムコール)して、代わりに作業をしてもらいます。

ここで、郵便配達(ファイルの読み書きやネットワーク通信の要求)を例に考えてみましょう。

1. ハイパーバイザー型(完全仮想化)の場合

各ゲストOS(各家)には、それぞれ専属の郵便受けと、独自の小さな事務員さんがいます。
ゲストOSのプログラムが「この手紙を外に出したい!」と叫ぶと、まずゲストOSの中の事務員さんが手紙を受け取り、それを一度ハイパーバイザーという管理人さんに渡し、さらにそれが大元のホストOSの郵便局に持ち込まれます。

「検問が何重にもあって安全だけど、届くまでに時間がかかるし、家ごとに事務員さんを雇うからコスト(オーバーヘッド)がかさむ」、これがハイパーバイザー型の世界です。

2. コンテナ型(Docker)の場合

コンテナの中には、ゲストOS(事務員さん)がいません。
コンテナ内のプログラムが「手紙を出したい!」と叫ぶと、余計な仲介人を挟まず、マンション共用の巨大な郵便ポスト(ホストOSのカーネル)に直接、システムコールの手紙をポイッと投げ込みます。

カーネルは「あ、これは3号室のコンテナからの依頼だな」とタグを見てサクッと処理し、すぐに結果を返します。

「仲介人がいないから、爆速で処理が終わるし、余計な事務員(ゲストOS)を養う必要がないからメモリも食わない!」。これがコンテナの軽快さの秘密というわけです。

—

起動時間とリソース消費の圧倒的な違いを体感する

この仕組みの違いは、「起動時間」と「リソースの消費量」にダイレクトに現れます。

  • ハイパーバイザー型:

サーバーを起動するとき、BIOSが立ち上がり、OSのブートローダーが走り、不要なドライバを読み込み……と、まるでパソコンの電源をイチから入れるような重厚なプロセスが必要です。起動には数十秒〜数分かかります。

  • コンテナ型:

すでにホストOSが元気よく動いているので、コンテナの中身は単なる「アプリケーションの実行ファイルとそのお友達(ライブラリ)」だけです。電源を入れる必要すらなく、単に新しいプロセスを「はい、スタート!」と走らせるだけなので、数秒(下手をすればミリ秒単位)で起動します。

実務の現場でオートスケーリング(負荷に応じてサーバーの数を自動で増やす仕組み)を構築するとき、この起動の速さは正義になります。Kubernetesがこれほど支持されているのも、このコンテナの「軽さ」と「俊敏さ」がベースにあるからです。

—

現場で使える!Dockerコンテナの裏側を覗いてみよう

百聞は一見にしかず。実際に私たちが普段使っているDockerが、どのように動いているのか、簡単な設定とコマンドでその片鱗に触れてみましょう。

以下のDockerfileは、極めて軽量なWebサーバーを立ち上げるための設定例です。

# ベースイメージとして、最小限のLinuxディストリビューションを使用する
# (重たいOS機能は削ぎ落とされているため、イメージサイズが非常に小さくなります)
FROM alpine:3.19

# パッケージマネージャーを使って、軽量なWebサーバー(nginx)をインストール
RUN apk add --no-cache nginx

# コンテナ起動時に実行されるデフォルトのコマンドを指定
# デモンストレーション用にフォアグラウンドでNginxを動かす
CMD ["nginx", "-g", "daemon off;"]

この設定ファイルをビルドしてコンテナを起動してみましょう。ターミナルで以下のコマンドを叩きます。

# Dockerイメージのビルド(設計図から製品を作る)
docker build -t my-lightweight-web .

# コンテナのバックグラウンド起動(マンションの一室を借りて住み始める)
docker run -d --name web-container -p 8080:80 my-lightweight-web

ここで起動したコンテナの中に入り、ホストOSとカーネルを共有している実感を少しだけ味わってみましょう。以下のコマンドを実行してみてください。

# 稼働中のコンテナ内でシェル(司令室)を起動する
docker exec -it web-container /bin/sh

# カーネルのバージョンを確認してみる
uname -r

出力されたカーネルのバージョンを見ると、あなたが今アクセスしているコンテナの中のバージョンと、ホストOS(手元のLinuxやWSL2など)のバージョンが完全に一致しているはずです。
「あ、本当に同じ心臓部(カーネル)を共有して動いているんだな」と実感できる瞬間です。

—

隔離性とセキュリティのトレードオフ

ここまでコンテナの素晴らしさを語ってきましたが、SREとして忘れてはならないのが「セキュリティと隔離性」のトレードオフです。

  • ハイパーバイザー型:

万が一、ゲストOSのひとつの内部で凶悪なウイルスが暴れ回り、カーネルごとクラッシュさせても、ハイパーバイザーが壁になっているため、他のゲストOSや大元の物理サーバーには被害が及びません(完全な隔離)。

  • コンテナ型:

もしコンテナ内のアプリケーションに深刻な脆弱性があり、ホストOSのカーネルを直撃するようなシステムコールが悪用された場合、最悪の場合は同じホスト上で動いている他のすべてのコンテナや、ホストOS自体が乗っ取られるリスクがあります。

そのため、Kubernetesなどの本番環境では、コンテナがホストのカーネルリソースを勝手に荒らさないように、SecurityContextを設定して権限を厳しく制限したり、Pod Security Standardsを適用してセキュリティの担保を行ったりする泥臭い工夫が不可欠になります。

—

まとめ:適材適所でクラウドインフラを使いこなそう

今回は、コンテナとハイパーバイザー型の違いを、カーネルの共有と郵便配達の例えを交えながら解説しました。

  • ハイパーバイザー型は、強固なセキュリティと完全な独立性が求められるシステムや、異なるOS(LinuxとWindowsなど)を混在させたいときに最適です。
  • コンテナ型は、圧倒的な起動の速さ、リソースの節約、そしてKubernetesによる爆発的なスケーラビリティを活かしたモダンなマイクロサービス開発に最適です。

「どちらが優れているか」ではなく、「それぞれの仕組みの裏側で、パケットやシステムコールがどう流れているか」をイメージできるようになると、インフラの設計やトラブルシューティングが何倍も楽しく、そして確実になりますよ。

それでは、また次回の技術の海でお会いしましょう!SREの現場からは以上です。

コメント

タイトルとURLをコピーしました