ネストされた仮想化
ネストされた仮想化を使うと、仮想マシン(以下、ネストの外側の guest を「L1」と呼びます)の中でさらに仮想マシンを動かせます。Linux guest で KVM を動かしたり、Windows で Hyper-V や WSL2 を有効にしたりできます。keelOS では既定でオフで、仮想マシンごとに個別にオンにします。この章では、オンにすると何ができて何ができないか、どんな制限があるかを説明します。
1. 使えるもの
次のものは、keelOS で実際に動作を確認しています。
- Linux guest の KVM:Debian に
qemu-system-x86を入れ、その中でさらに仮想マシン(L2)を起動。起動と停止を何度繰り返しても問題ありません。 - Windows 10 の Hyper-V:Hyper-V を入れて再起動すると hypervisor が正常に起動し、その中で第 2 世代の仮想マシンを作って Linux を起動できます。
- Windows 10 の WSL2:
wsl --import … --version 2でディストリビューションをインポートし、起動と停止を 10 回繰り返して、すべて成功しました。
項目ごとの確認はまだですが、原理的に同じ KVM や Hyper-V の機能に頼るものとして、Firecracker のような KVM ベースの microVM(Linux guest 内)と Docker Desktop(WSL2 または Hyper-V に依存)があります。問題があったときは、現象をお知らせください。
2. まだ使えないもの
- AMD ホスト:hyp の上で動く Intel ホストだけが対象です。AMD ホストではこのスイッチはグレーアウトされ、横に理由が表示されます。
- Windows の VBS、メモリ整合性(HVCI):ネストを有効にした guest で Windows の Hyper-V は起動しますが、HVCI はまだ使えません(さらに多くの CPU 機能と IOMMU 機能が必要です)。Windows 11 と Windows Server はまだ試していません。
- ライブマイグレーション、ストレージプール間のライブ移動:ネストを有効にした仮想マシンでは、現時点では使えません(サスペンドと reload は可能です。§3 を参照。コールド移行は専用の確認をしていません)。
- PCI パススルー:ネストとは同時に使えません。パススルーデバイスのある仮想マシンではスイッチがグレーアウトされ、ネストを有効にした仮想マシンでは PCI デバイスを追加するボタンがグレーアウトされます。
- keelOS の Hyper-V 拡張:Windows テンプレートは通常、性能向上のために Hyper-V 拡張を guest に渡します。ネストを有効にした Windows guest は自分自身の Hyper-V を動かすので、この拡張は既定では渡されません。手作業で
"hyperv": trueと書くと拒否されます。 - kcell:ネストは有効にできません。
3. サスペンド、reload、アップグレード
ホストは、ネストを有効にした仮想マシンの CPU 状態(「内側のどの仮想マシンを実行しているか」を含む)もまとめてチェックポイントに保存します。
- サスペンドと再開は、ほかの仮想マシンと同じです。 再開後、L1 の KVM、Hyper-V、WSL2、およびその中で動いていた仮想マシンは、再起動なしにそのまま動き続けます。
- ホストの reload 時には、サスペンドされて reload 後に再開されます。 ほかの仮想マシンと同じです。一覧では reload 時の動作が「サスペンド」と表示されます。
- 例外:新しいバージョンが試用中のとき(アップグレード後、アップグレードを確定を押す前。アップグレードの章を参照)。このとき、ホストは古いバージョンの形式でチェックポイントを書きますが、古い形式にはこれらの状態が入りません。そのため、サスペンドできません。稼働中は、ホストの reload、再起動、スロットの切り替えが拒否され、ページ(システム → アップグレード、システム → メンテナンス)にこの仮想マシンが一覧表示され、横にオフにするボタンが付きます。一覧の reload 時の動作は「root reload 時にシャットダウン(ネストされた仮想化)」と表示され、
keel vm listではpoweroff (nested)と表示されます。アップグレードを確定すると、これらの制限はなくなります。 - この種のチェックポイントを読めない古いバージョンのスロットへの切り替えは拒否されます(先にこの仮想マシンをシャットダウンしてください)。
4. 有効にする方法
Web:
- 仮想マシンで変更したい仮想マシンを押し、編集を押します(新規作成のときは、ウィザードの最後のステップ、または「カスタム」のデバイスのセクションです)。
- デバイスセクションで、この VM の中でさらに仮想マシンを動かす(ネストされた仮想化)にチェックを入れます。下に上記の制限が小さな文字で書かれています。
- 保存します。設定は仮想マシンの次回のコールドスタートから有効になります。稼働中の仮想マシンは、いったんシャットダウンして起動し直してください。

スイッチがグレーアウトされている場合は、横に理由が書かれています。ホストが keelOS の hyp 上で動いていない、ホストが AMD CPU である、ホストの hypervisor モジュールが古い(keelOS をアップグレードしてください)、またはこの仮想マシンに PCI パススルーデバイスがある、のいずれかです。
コマンドライン:新規作成時に --nested を付けます。既存の仮想マシンでは config.json に "nested": true と書きます。
keel vm create --alias lab --vcpus 4 --ram 8G --disk 60G --nested
keel vm list の RELOAD 列は、この種の仮想マシンでは suspend と表示されます(試用期間中は poweroff (nested)。§3 を参照)。
5. 使うときのポイント
- L1 に十分な CPU とメモリを割り当ててください。 内側の仮想マシンのメモリは L1 のメモリから確保されます。Windows は Hyper-V を入れると、Windows 自身が Hyper-V の「ルートパーティション」になります。
- Windows:Hyper-V のインストール後に 1 回再起動が必要です。再起動後、
systeminfoに「ハイパーバイザーが検出されました」と表示されますが、これは正常です。 - 性能:L2(内側の仮想マシン)が VM exit するたびに、root と hyp の間を約 16 回往復します。測定した規模は 1 回あたり数十マイクロ秒です(テスト機では約 32 マイクロ秒)。ページフォールトが多い負荷(コンパイル、fork が多いもの)は、ネストされた EPT により大幅に速くなります(テスト機では、fork が多い負荷はネストされた EPT なしの場合より 22 倍、ページフォールトが多い負荷は 44 倍速くなりました)。一方、VM exit が多い負荷(I/O や割り込みが多いもの)は、exit のたびにこのコストがかかるので、L1 で直接動かすより遅くなります。実験、開発、テスト環境には向いていますが、本番の仮想化基盤としては使わないでください。
6. トラブルシューティング
- 保存時に
nested virtualization and passthrough devices cannot be combinedと表示される:先に PCI デバイスを外すか、ネストをオフにしてください。 - 保存時に
… the Hyper-V enlightenments cannot be combined yetと表示される:config.json に"hyperv": trueが入っているので、削除してください。 - ホストの reload またはアップグレードが
runs with nested virtualization … shut it down firstで拒否される:新しいバージョンがまだ試用中です(またはホストの vmm モジュールが古い)。一覧に出た仮想マシンをシャットダウンするか、先にアップグレードを確定してください。 - L1 で
kvm_intelをロードしてもept=Yにならない:ホストの vmm モジュールが新しいことを確認してください(システム → アップグレードでバージョンを確認)。
詳細とテスト記録は、設計文書 docs/69 にあります。