【入門編】 ネステッド仮想化(Nested Virtualization)のメカニズムとCPU仮想化支援命令の二重化 – クラウドインフラと仮想化ネットワーク実践ガイド

仮想マシンの中でVMが動く!?ネステッド仮想化の裏側とCPU仮想化支援命令(VT-x/AMD-V)の二重化メカニズムを世界一わかりやすく解説

みなさん、こんにちは!日夜クラウドインフラやKubernetesのネットワークと格闘しているSREライターです。

突然ですが、開発や検証の現場で「AWSやGCP上の仮想マシン(VM)の中に、さらにDockerやKVMを入れて、その中で仮想マシンを動かしたい!」と思ったことはありませんか?

「仮想マシンの中で、さらに仮想マシンを動かす」……まるでロシアの民芸品「マトリョーシカ」のようなこの技術を、ネステッド仮想化(Nested Virtualization)と呼びます。

「えっ、仮想化されたCPUの上で、さらにCPUの仮想化機能を動かすなんて可能なの?」「パケットやCPUの命令はどう処理されているの?」と疑問に思いますよね。

一見すると複雑で魔法のように思えるこの技術ですが、仕組みを紐解いていくと、「厳格な郵便配達の転送ルール」や「会社の決裁ルート」にそっくりなのです!

今回は、インフラやネットワークの勉強を始めたばかりの初学者のみなさんに向けて、小難しいCPU内部の動きやビット計算を「身近な現実世界の例え」に置き換えながら、一歩ずつ丁寧に解説していきますね。

最後には、Linux(KVM)でネステッド仮想化を有効化する実践的な設定手順も用意していますので、ぜひ最後まで一緒に学んでいきましょう!

—

1. ネステッド仮想化の全体像:「L0・L1・L2」の3層構造を知ろう!

ネステッド仮想化を理解するための第一歩として、まずは登場人物を整理しておきましょう。
専門用語では、ネステッド仮想化の世界を「L0(エルゼロ)」「L1(エルワン)」「L2(エルツー)」という階層(Layer)で呼びます。

文字だけだとピンとこないかもしれませんので、「巨大な総合商社」に例えてみましょう!

【物理マシン(L0 Hypervisor)】 = 本社社長
    │
    └──【第1階層のVM(L1 Guest / Hypervisor)】 = 支社(支社長)
            │
            └──【第2階層のVM(L2 Guest)】 = 現場の担当者

それぞれの役割を詳しく見てみましょう。

L0(Level 0):物理ハイパーバイザー(本社社長)

実際の物理サーバ(IntelやAMDの本物のCPU)の上で直接動いているハイパーバイザーです。AWSの Nitro や、物理マシンに入れた ESXi、KVM などがこれにあたります。本物のハードウェアリソース(CPUやメモリ)を握っている「一番の権限保持者(社長)」です。

L1(Level 1):第1階層の仮想マシン 兼 ハイパーバイザー(支社長)

L0の上で動いている仮想マシン(VM)です。しかし、ただのVMではありません。自分自身も内部でさらにVMを育てることができるよう、ハイパーバイザー(KVMなど)の機能を備えています。例えるなら、本社から権限を与えられた「支社長」のような存在ですね。

L2(Level 2):第2階層の仮想マシン(現場の担当者)

L1の中で動いている「孫VM」にあたる仮想マシンです。L2から見ると、自分が仮想マシンの上で動いているのか、本物の物理マシンの上で動いているのかは全く区別がつきません。現場で泥臭くタスクをこなす「現場の担当者」です。

—

2. そもそもCPU仮想化支援(VT-x / AMD-V)とは?

ここで一度、「物理CPUがハイパーバイザーを助ける仕組み」である VT-x(Intel) や AMD-V(AMD) についておさらいしておきましょう。

CPUには、OSのカーネルなどが使う強力な権限を持つ「カーネルモード(リング0)」と、一般的なアプリが使う制限された「ユーザーモード(リング3)」というモードがあります。

もし、仮想マシン(L1)が「メモリを直接書き換える」ような危険で強力な命令を実行しようとしたらどうなるでしょう?物理CPUは「おっと、君は本物のOSじゃないから勝手なことをしちゃダメだよ!」と拒否します。これを専門用語で CPU例外(Exception) や VM-Exit と呼びます。

役所の窓口で例えてみよう!

物理CPUとハイパーバイザーの関係は、「役所の受付窓口(CPU)」と「市民(VM)」の関係に似ています。

1. 通常の手続き(通常の計算など): 市民(VM)は窓口を通さず、自分で書類(CPUの計算)を進められます。
2. 特別な手続き(ハードウェアへのアクセスなど): 市民(VM)が「マイナンバーを発行したい!」と特別な申請をしようとすると、受付窓口(CPU)が「ストップ!それは職員(ハイパーバイザー)を通してください!」と制止します(これが VM-Exit です)。
3. 処理の代行: 職員(ハイパーバイザー)が代わりに手続きを処理し、終わったら「はい、できましたよ」と市民(VM)に結果を返します(これを VM-Entry と呼びます)。

この「VM-Exit(中断してハイパーバイザーへ交代)」と「VM-Entry(VMへ処理を戻す)」のバトンタッチを超高速に行う仕組みこそが、CPU仮想化支援命令(VT-x / AMD-V)なのです!

—

3. ネステッド仮想化の核心:CPU例外とVM-Exitの「二重化」メカニズム

さて、ここからが本題です!

L2(孫VM)が特別な命令を実行したとき、物理CPU(L0)とL1ハイパーバイザーはどのように連携しているのでしょうか?

普通に考えると、L2(孫VM)が何かやらかした時、一番外側にいる物理CPU(L0)が最初にそれを検知します。しかし、物理CPU(L0)は「L2の存在」を直接知らないのです。物理CPUから見れば、単に「L1というVMが何か命令を出してきたな」としか見えません。

そこで、CPU仮想化支援命令の二重化(Nested VT-x / AMD-V)という技が登場します。

パケットや命令がどのように伝達されるのか、「特急郵便の転送」の流れで追ってみましょう!

【L2 (孫VM)】が特製命令(VMCSアクセスなど)を実行!
      │
      ▼
【物理CPU (L0)】が検知して「VM-Exit」が発生!
      │ 「むむっ、これはL1(支社長)宛ての報告だな!」
      ▼
【L0 Hypervisor】が受け取り、L1へ「仮想的なVM-Exit」を転送(Trapping)
      │
      ▼
【L1 Hypervisor】が「自分が投げた命令の処理」としてL2の代わりに処理を実行!
      │
      ▼
【L0 Hypervisor】を経由して【L2 (孫VM)】に「完了!」と返事(VM-Entry)

ステップ1:物理CPU(L0)によるトラップ(捕獲)

L2(孫VM)が特権命令を実行すると、ハードウェアである物理CPU(L0)で本物の VM-Exit が発生します。一時的にL2の動作がストップし、制御権がL0ハイパーバイザーに移動します。

ステップ2:L0ハイパーバイザーの「神の目」判断

L0ハイパーバイザーは、CPUの管理領域(VMCSと呼ばれる設定シートのようなもの)を確認します。
「なるほど、いまVM-Exitを起こしたのはL1じゃなくて、L1の中で動いているL2だな。そしてこの命令は、L1が処理すべき内容だ!」と見抜くのです。

ステップ3:L1への「仮想VM-Exit」の注入(シャドウ化)

L0ハイパーバイザーは、L1に対して「へいL1さん、君の部下(L2)が特権命令を出したから処理してね!」と、あたかも本物のハードウェアからVM-Exitが起きたかのように装ってイベントを伝えます。

ステップ4:L1の処理と復帰

L1ハイパーバイザーは「了解!L2の代わりに処理するよ」と作業をこなし、終わったらL2を再開させます(VM-Entry)。

このように、L0ハイパーバイザーと物理CPUがタッグを組み、「VM-Exitを横取りしてL1に見せかける(シャドウイング)」ことで、L1は自分が物理マシン上にいると錯覚し、無事にL2を動かすことができるのです!

一歩一歩追いかけると、とても健気にCPUとハイパーバイザーがバトンリレーをしていることが分かりますよね。

—

4. 実践編:Linux (KVM) でネステッド仮想化を有効化してみよう!

仕組みが理解できたら、実際のLinux環境(UbuntuやRHELなど)でネステッド仮想化が使えるかどうかを確認し、有効化する設定を行ってみましょう!

実務の開発環境やテスト環境構築でもそのまま使える手順ですよ。

手順1:現在のネステッド仮想化の有効状態を確認する

まずは、お使いのLinux(L0マシン)でネステッド機能が有効になっているかターミナルで確認します。

以下のコマンドを打ってみましょう。

# Intel製CPUの場合の確認コマンド
cat /sys/module/kvm_intel/parameters/nested

# AMD製CPUの場合の確認コマンド
cat /sys/module/kvm_amd/parameters/nested

画面に Y または 1 と表示されれば、すでに有効になっています!
もし N や 0 と表示された場合は、まだ無効化されているので、次の手順で有効化しましょう。

—

手順2:ネステッド仮想化を有効化する設定ファイルを作成する

Linuxのカーネルモジュールにパラメータを渡すため、設定ファイルを作成します。

# Intel製CPUの場合の設定(/etc/modprobe.d/kvm_intel.conf を作成)
sudo bash -c 'echo "options kvm_intel nested=1" > /etc/modprobe.d/kvm_intel.conf'

# AMD製CPUの場合の設定(/etc/modprobe.d/kvm_amd.conf を作成)
sudo bash -c 'echo "options kvm_amd nested=1" > /etc/modprobe.d/kvm_amd.conf'

—

手順3:KVMモジュールを再読み込みして設定を反映する

作成した設定を読み込ませるため、KVMモジュールを一度アンロード(停止)してリロード(再開)します。

※注意:L1上で動いている既存のVMがある場合は、一時停止しますのでご注意ください。

# KVMモジュールを一度解除して、再読み込みします (Intelの場合)
sudo modprobe -r kvm_intel
sudo modprobe kvm_intel

# 再度、有効になったか確認します('Y' または '1' が返ってくれば成功です!)
cat /sys/module/kvm_intel/parameters/nested

—

手順4:L1仮想マシンを立ち上げる際のQEMU/libvirt設定

L1となる仮想マシンを起動する際、「物理CPUの仮想化命令(VT-x/AMD-V)をそのままL1 VMの中にパススルー(通過)させる」という設定が必要になります。

virsh や libvirt をお使いの場合は、VMのXML設定ファイル(virsh edit <VM名>)で以下のようにCPUモードを設定します。

<!-- 仮想マシンの設定XMLファイルの一部 -->
<domain type='kvm'>
  <name>L1-Hypervisor-VM</name>
  
  <!-- 物理CPUの機能をそのままVM内部に見せる passthrough 設定 -->
  <cpu mode='host-passthrough' check='none'>
    <!-- トラブル防止のため、トポロジー(コア数など)を安全に渡します -->
    <topology sockets='1' dies='1' cores='4' threads='1'/>
  </cpu>
  
  <!-- (その他の設定は省略) -->
</domain>

直接 qemu-system-x86_64 コマンドラインで起動する場合は、以下のように -cpu host オプションを付与すればOKです!

# QEMUで物理CPUの機能をそのままパススルーしてL1 VMを起動する例
qemu-system-x86_64 \
  -enable-kvm \
  -cpu host \
  -m 8G \
  -smp 4 \
  -hda /var/lib/libvirt/images/l1-guest.qcow2 \
  -vnc :1

これで、L1 VMの中でさらに virt-host-validate コマンドを実行したり、docker run や minikube start --driver=kvm2 を実行して、孫VM(L2)を元気に動かす準備が整いました!

—

5. まとめ:ネステッド仮想化が切り拓くモダンインフラの世界

今回は、ネステッド仮想化(Nested Virtualization)の基本概念から、CPU例外・VM-Exitの伝達メカニズム、そして実際のLinuxでの有効化手順までを一歩ずつ解説してきました。

内容をもう一度軽く振り返ってみましょう!

  • L0・L1・L2の3層構造: 物理マシン(L0)、VM兼ハイパーバイザー(L1)、孫VM(L2)の関係性。
  • VM-Exitのバトンタッチ: L2が出した特権命令をL0がキャッチ(Trapping)し、L1宛ての「仮想VM-Exit」として転送する二重化の工夫。
  • 設定の要点: Linuxカーネルモジュールで nested=1 を指定し、VM起動時に host-passthrough でCPU機能をパススルーさせる。

ネステッド仮想化は現場でどう使われている?

「VMの中でVMを動かすなんて、ただの技術者の趣味じゃないの?」と思われるかもしれません。しかし現在、現場では以下のような重要な用途で大活躍しています!

1. Kubernetes(k8s)のローカル・CI/CD開発環境: クラウド上のVMの中で、さらにKVMを使ってKindやMinikube、OpenShiftのマルチノードクラスタを再現する。
2. クラウド移行(マイグレーション)の検証: オンプレミスのVMware環境を、AWS(EC2 bare metal / Metalインスタンス以外)やGCPのVMの上にそのまま持ってきて検証する。
3. ハンズオン・教育環境の構築: 受講生にVMを1台配り、その中で自由にハイパーバイザーの構築やトラブルシューティングを体験してもらう。

少し難しそうに見える低レイヤーのネットワークやCPUの仕組みも、順を追ってイメージを掴んでいけば、決して恐れる必要はありません。

インフラやネットワークの世界は、知れば知るほど「よくできているなぁ!」と感銘を受ける面白い仕掛けに満ちています。

ぜひみなさんも、手元の検証環境でネステッド仮想化を設定し、マトリョーシカのようにVMの中でVMが動く感動を味わってみてくださいね!

また次の記事でお会いしましょう!

コメント

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