OS仮想化技術の系統(ハイパーバイザとコンテナ)
Type-1とType-2、準仮想化と完全仮想化、コンテナの違いを系統で一望できます。VT-xやEPTが何を解決したのかまで原理から整理し、選定の軸を手に入れます。
- 1.仮想化はハイパーバイザ型とコンテナ型に大別され、前者はハードウェアを、後者はカーネルの見え方を仮想化します。
- 2.ハイパーバイザはType-1(ベアメタル)とType-2(ホスト型)に分かれ、x86では特権命令の問題をVT-xが、ページテーブル二重変換をEPTが解決しました。
- 3.完全仮想化はゲスト無改変、準仮想化はゲスト改変で速度を稼ぐ手法で、コンテナはカーネル共有ゆえに最も軽く隔離は最も弱い系統です。
仮想化を二つの幹で捉える
「仮想化」と一括りにされる技術は、何を仮想化するか で大きく二つの幹に分かれます。一方は ハードウェア(CPU・メモリ・デバイス) を仮想化し、その上にゲスト OS のカーネルを丸ごと載せる ハイパーバイザ型。もう一方は OS が見せる カーネルの景色 だけを仮想化し、ホストのカーネルを共有したままプロセスを隔離する コンテナ型 です。
この分岐を見失うと「VM とコンテナのどちらが速い/安全か」という議論が噛み合いません。両者は同じ軸の上にある競合ではなく、仮想化する層が違う別系統 だからです。本稿はこの二幹をさらに枝分かれさせ、年代と分岐を追って系統を整理します。
仮想化
├─ ハイパーバイザ型(ハードウェアを仮想化/ゲストカーネルを持つ)
│ ├─ 軸1:位置で分岐
│ │ ├─ Type-1(ベアメタル:HWの直上で動く) 例: Xen, ESXi, Hyper-V, KVM
│ │ └─ Type-2(ホスト型:ホストOSの上で動く) 例: VirtualBox, VMware Workstation
│ └─ 軸2:ゲスト改変の有無で分岐(位置とは独立)
│ ├─ 完全仮想化(ゲスト無改変) 例: 初期VMware, HW支援後のKVM
│ └─ 準仮想化(ゲストにフックを入れる) 例: Xen PV(Type-1かつ準仮想化)
└─ コンテナ型(カーネルを共有/名前空間+cgroupsで隔離)
└─ 例: Docker, LXC, containerd
VMM(Virtual Machine Monitor)は仮想マシンを管理する制御プログラムの古典的呼称で、現在は ハイパーバイザ とほぼ同義です。本稿でも区別せず用います。重要なのは名前ではなく、それが HW の直上にいるか(Type-1)、ホスト OS の上にいるか(Type-2) という位置です。
Type-1 と Type-2:ハイパーバイザの位置で分かれる
ハイパーバイザ型の最初の分岐は、ハイパーバイザが どこに座るか です。
- Type-1(ベアメタル型):ハードウェアの 直上 でハイパーバイザが動き、その上に各ゲスト OS が並びます。間にホスト OS がないぶんオーバーヘッドが小さく、隔離も強い。サーバー仮想化の主流で、Xen・VMware ESXi・Microsoft Hyper-V が代表です。KVM は Linux カーネル自体をハイパーバイザに変える方式で、カーネルが直接ハードウェアを握るため実質 Type-1 に分類されます。
- Type-2(ホスト型):通常の ホスト OS の上に1アプリとして ハイパーバイザが乗り、その上でゲストを動かします。導入が容易で開発・検証向け。VirtualBox・VMware Workstation が代表です。ゲストの操作がホスト OS のカーネルを経由するぶん、一般に Type-1 より遅くなります。
KVM は「Linux 上で動くから Type-2」と誤解されがちですが、KVM はホスト OS の一アプリではなく カーネルモジュールとしてカーネルそのものに溶け込み、ハードウェアの仮想化支援を直接駆動します。ゲストの実行は CPU 上で直に走るため、性能特性も分類も Type-1 寄り とするのが正確です。
x86 の難所:なぜ「素朴な仮想化」は失敗したか
ハイパーバイザの核心は、ゲストの特権命令をハイパーバイザが横取りして代行する ことにあります。理想は「ゲストが特権命令を実行 → CPU が例外(トラップ)を上げる → ハイパーバイザが捕まえて処理する」という trap-and-emulate です。Popek と Goldberg が1974年に示した条件では、すべての特権命令がユーザーモードで確実にトラップする ことが仮想化可能性の前提でした。
ところが x86 はこの条件を満たしませんでした。一部の命令(例として POPF)は、ユーザーモードで実行しても トラップせず黙って異なる挙動をする(sensitive だが privileged でない)ため、ハイパーバイザが介入できません。x86 はそのままでは仮想化できなかったのです。この壁を越えるために、二つの異なる解法が生まれました。
trap-and-emulate(理想):
guest が特権命令を実行
→ CPU が #GP 例外でトラップ
→ ハイパーバイザが命令をエミュレートし、結果をゲストへ返す
x86 の問題:
一部の sensitive 命令がユーザーモードでトラップしない
→ ハイパーバイザが介入できず、仮想化が破綻する
- 解法A:完全仮想化(バイナリ変換) — VMware が採った道。ゲストのコードを実行直前に走査し、問題のある命令をハイパーバイザ呼び出しに動的に書き換える(binary translation)。ゲスト OS は 無改変 のまま動く点が最大の長所ですが、変換のコストが伴います。
- 解法B:準仮想化(paravirtualization) — Xen が採った道。ゲスト OS の ソースに手を入れ、特権操作を直接 ハイパーコール(ハイパーバイザへの明示的な呼び出し)に置き換える。トラップに頼らないため高速ですが、ゲスト OS の改変が必須 で、改変できない OS(当時の Windows 等)には使えませんでした。
判定軸は一点、ゲスト OS を改変するか です。改変不要なら完全仮想化、ゲストにハイパーコール用のフックを入れるなら準仮想化です。「ゲストが自分は仮想化されていると知っているか」で言い換えても同じで、準仮想化のゲストは仮想化を自覚して協調します。
ハードウェア支援:VT-x と EPT が地図を塗り替えた
2005年前後、Intel VT-x と AMD AMD-V が登場し、状況が一変します。これらは CPU に 新しい動作モード を追加しました。VT-x では VMX root モード(ハイパーバイザ用) と VMX non-root モード(ゲスト用) を分け、ゲストは non-root モードで 本物の特権命令も含めてそのまま実行 できます。介入が必要な事象が起きたときだけ VM exit でハイパーバイザへ制御が移り、処理後 VM entry でゲストへ戻ります。
これにより、x86 のトラップ問題は ハードウェアが面倒を見る ようになり、バイナリ変換なしの完全仮想化が高速に成立しました。KVM はこの支援を前提に設計されています。ただし VM exit / entry は決して安価ではなく、その 回数を減らす ことが今日の性能設計の主眼です。
残る難所が メモリ仮想化 でした。ゲストは「ゲスト仮想 → ゲスト物理」の変換をすると思っていますが、ゲスト物理アドレスは本物の物理メモリではありません。ハードウェア支援以前は、ハイパーバイザが シャドウページテーブル を維持し、「ゲスト仮想 → ホスト物理」を一段で引けるよう裏で同期していました。ゲストがページテーブルを書き換えるたびに VM exit が必要で、コストの源でした。
EPT(Intel Extended Page Tables)/NPT(AMD Nested Page Tables) はこれをハードウェアで解きます。CPU が 二段のページテーブルを自動でたどり、「ゲスト仮想 → ゲスト物理」をゲストの通常ページテーブルで、「ゲスト物理 → ホスト物理」を EPT で変換します。ハイパーバイザはゲストのページ操作に介入する必要がなくなり、VM exit が激減しました。
EPT による二段変換(ハードウェアが自動でたどる):
ゲスト仮想アドレス
--[ゲストのページテーブル]--> ゲスト物理アドレス
--[EPT / NPT]------------------> ホスト物理アドレス
頻出は「何を支援したか」の対応です。VT-x / AMD-V=CPU の特権命令の仮想化(VMX root / non-root、VM exit / entry)。EPT / NPT=メモリの二段アドレス変換。前者が trap-and-emulate の x86 問題を、後者がシャドウページテーブルのコストを置き換えた、と二点で整理すると混同しません。TLB は GVA→HPA の最終結果をキャッシュします。
メモリ変換の基礎は ページング と 仮想メモリ を、特権命令とモード切替の前提は カーネルモードとユーザーモード も合わせてどうぞ。
もう一つの幹:コンテナ
ここまでのハイパーバイザ型はすべて ゲスト OS のカーネルを各 VM が持つ 前提でした。コンテナはこの前提を捨てます。ホストのカーネルを全コンテナで共有 し、見える資源を 名前空間 で区切り、使える資源を cgroups で制限することで、新しいカーネルを起動せずに隔離を作ります。OS を一つ起動しないぶん、起動はミリ秒級で軽量です。
代償は 隔離の強度 です。カーネルを共有するため、カーネルの脆弱性を突かれると隔離を越えてホストや他コンテナに波及しえます。ハイパーバイザ型が HW 境界 で隔離するのに対し、コンテナは カーネル内の論理境界 で隔離する、という層の違いがそのままセキュリティ強度の差になります。詳しくは 名前空間と cgroups を参照してください。
| 観点 | Type-1 ハイパーバイザ | Type-2 ハイパーバイザ | コンテナ |
|---|---|---|---|
| 仮想化する層 | ハードウェア | ハードウェア | カーネルの見え方 |
| ゲストカーネル | VMごとに別に持つ | VMごとに別に持つ | ホストと共有(持たない) |
| 位置 | HWの直上 | ホストOSの上 | ホストOS上のプロセス群 |
| 隔離の強さ | 強い(HW境界) | 強い(HW境界) | 中(カーネル共有のぶん弱い) |
| 起動の速さ | 遅い(OS起動) | 遅い(OS起動) | 速い(プロセス起動) |
| 代表例 | ESXi, Xen, KVM, Hyper-V | VirtualBox, VMware WS | Docker, LXC, containerd |
近年は両幹の 中間 も育っています。Kata Containers や gVisor は、コンテナの操作性を保ちつつ、軽量 VM やユーザー空間カーネルで 追加の隔離層 を挟む方式です。これは系統樹の二幹が、互いの弱点(VM の重さ、コンテナの隔離の弱さ)を補い合う形で交差し始めた、と読めます。
まとめ
- 仮想化は ハードウェアを仮想化するハイパーバイザ型 と、カーネルの景色を仮想化するコンテナ型 の二幹に大別される。
- ハイパーバイザは Type-1(HW直上) と Type-2(ホスト型) に分かれ、KVM は Type-1 寄りに分類する。
- x86 はトラップしない sensitive 命令ゆえ素朴な仮想化に失敗し、完全仮想化(無改変+バイナリ変換) と 準仮想化(ゲスト改変+ハイパーコール) が回避策として生まれた。
- VT-x / AMD-V が特権命令を、EPT / NPT がメモリ二段変換をハードウェアで解決し、無改変・高速な仮想化を成立させた。
- コンテナ はカーネル共有で最も軽いが隔離は最も弱く、Kata や gVisor が両幹の中間を埋めつつある。
OS Article
OS仮想化技術の系統(ハイパーバイザとコンテナ)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
仮想化
比較で見る軸
難易度: advanced / カテゴリ: OS / タグ数: 5
導入後に効く点
ハイパーバイザはType-1(ベアメタル)とType-2(ホスト型)に分かれ、x86では特権命令の問題をVT-xが、ページテーブル二重変換をEPTが解決しました。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- OS
- タグ数
- 5
判断チェックリスト
- 自社の用途が「仮想化 / ハイパーバイザ」に近いか確認する。
- 強みである「仮想化はハイパーバイザ型とコンテナ型に大別され、前者はハードウェアを、後者はカーネルの見え方を仮想化します。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。