VPSでネスト仮想化してProxmoxを実行できる?
VPSでProxmoxやKVMのゲストを動かせるか、1分でkvm-okを使って確認できます。vmxまたはsvmフラグが隠されている場合のエラー文字列も紹介します。
短い回答
ネスト仮想化とは、仮想マシン内でハイパーバイザーを実行することです。VPS はすでにゲストであり、その中で独自のゲストをホストする構成です。これは、プロバイダーのハイパーバイザーが CPU の仮想化拡張機能をインスタンスに明示的に公開している場合に限って動作します。/proc/cpuinfo で vmx フラグ (Intel) または svm (AMD) を確認してください。どちらも表示されない場合、VPS 内でどのような設定をしても解決できません。
まず、期待値を調整しておきます。Docker にこの機能は必要ありません。 コンテナは VPS のカーネルを共有し、/dev/kvm に触れることもありません。実際の目的が「自分のサーバーで複数のサービスをコンテナで実行する」ことであれば、すでに必要なものは揃っています。ネスト仮想化が必要になるのは、別のカーネル、Proxmox の検証環境、Windows ゲスト、Firecracker microVM、Android エミュレーター、実 VM を使う Kubernetes のテスト環境、または VM イメージを起動する CI runner を実行する場合です。
実際に何が入れ子になっているのか
3 つの層があります。
- L0 は、物理マシン上で動作するプロバイダーのハイパーバイザーです。ここにはアクセスできません。
- L1 は、使用している VPS です。L0 から見ると、単なるゲストです。
- L2 は、VPS 内で実行したい VM です。
ハードウェア仮想化では、Intel の場合、VT-x(vmx フラグ)と EPT を使用します。AMD の場合は、AMD-V / SVM(svm)と RVI/NPT を使用します。ハイパーバイザーはこれらの命令を使ってゲストモードに入り、CPU が 2 つのページテーブルを同時にたどれるようにします。
どちらも再入可能な実行を前提に設計されていないため、入れ子構成ではエミュレーションが必要です。L1 が VMLAUNCH や VMRESUME などの VMX 命令を実行すると、処理は L0 にトラップします。L0 は L1 に代わって L2 用のシャドー構造を管理します。VMCS shadowing に対応する CPU では、L1 の VMREAD と VMWRITE を exit なしで処理できます。そのため、この通信の大部分は削減できますが、すべてがなくなるわけではありません。KVM はこの処理に適しています。ただし、exit のたびに L0 が追加処理を行うため、プロバイダー側で有効化する必要があります。
L0 が KVM の場合、アクセラレーションされた L2 を実行するには、次の 2 つの条件を両方満たす必要があります。
- L0 の KVM モジュールが
nested=1を指定してロードされていること。 - L0 が、フラグを備えた CPU モデルを VPS に提供していること。libvirt では
<cpu mode='host-passthrough'/>、Proxmox ではcpu: host、raw QEMU では-cpu hostに該当します。汎用のエミュレート CPU モデル(qemu64、kvm64)では、入れ子構成がグローバルに有効でもvmxが隠されます。
他のハイパーバイザーには、それぞれ独自の切り替え方法があります。たとえば Hyper-V は、VM 内の入れ子ハイパーバイザー向けに仮想化拡張機能をエミュレートします。ただし、入れ子構成を個別に有効化した VM に限られます。
VPS を 1 分で確認する
# 1. Are you in a VM, and under what?
systemd-detect-virt # kvm, vmware, xen, microsoft, or "none" on metal
# 2. Does the CPU expose the extensions to you?
grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u
lscpu | grep -i -E 'virtual|hypervisor'
# 3. The definitive check
sudo apt update && sudo apt install -y cpu-checker
kvm-ok
# 4. The device node the whole stack depends on
ls -l /dev/kvm使用可能なインスタンスでは vmx または svm が表示され、kvm-ok は KVM acceleration can be used を示し、/dev/kvm は root:kvm モード 660 で存在します。フラグが存在するのにデバイスノードがない場合は、モジュールを手動でロードしてカーネルログを確認します。
sudo modprobe kvm_intel # or kvm_amd
sudo dmesg | tail -n 20常に引用され、広く誤解されているファイルがあります。
cat /sys/module/kvm_intel/parameters/nested # Y or NVPS 内では、これは 自身の KVM モジュールの設定です。L2 ゲストが第 3 レベルをネストできるかどうかを制御します。L0 がネストを有効にしたかどうかは示しません。その確認には /proc/cpuinfo と kvm-ok を使用します。nested パラメーターは、自分が完全に所有するマシンで設定する項目です。
echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm-nested.conf
sudo modprobe -r kvm_intel && sudo modprobe kvm_intelVM の実行中はモジュールの削除が拒否されるため、先にゲストをシャットダウンします。そのマシンが Proxmox ホストの場合は、Proxmox VE 9 で nested virtualization を有効にするで、同じ modprobe.d の変更に加えて、ゲスト内でフラグを認識できるようにする VM ごとの cpu: host 設定を説明しています。
ほとんどの VPS ホスティング事業者が無効にしている理由
- ライブマイグレーション。
vmxを提供するには、そのフラグを持つ CPU モデルを公開する必要があります。その CPU 機能に依存するゲストは、それらの機能を持たない CPU のマシンへ安全に移行できません。顧客のノードをマイグレーションして排出するホストでは、ネスティングを有効にした時点でこの運用ができなくなります。 - 攻撃対象領域。 ネストされた VMX/SVM の処理経路は、カーネルの仮想化層でも特に複雑なコードであり、それに見合う CVE の履歴があります。
- L0 が KVM とは限りません。
systemd-detect-virtがvmware、xen、またはmicrosoftを出力する場合、ネスティングの規則は KVM ではなく、そのスタックの規則に従います。
インスタンスにフラグが表示されない場合は、サポートに問い合わせてください。一部の事業者では VM ごとに有効化できます。ネスティングを明記したプランを選ぶか、専用サーバーへ移行してください。以降は、フラグが表示されるマシンで root を使用していることを前提とします。
libvirt で L2 ゲストを実行する
sudo apt install -y qemu-system-x86 libvirt-daemon-system virtinst ovmf
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt,kvm "$USER" # log out and back in
virt-install \
--name guest1 \
--memory 2048 \
--vcpus 2 \
--cpu host-passthrough \
--disk path=/var/lib/libvirt/images/guest1.qcow2,size=20,format=qcow2,bus=virtio \
--network network=default,model=virtio \
--os-variant debian13 \
--location https://deb.debian.org/debian/dists/trixie/main/installer-amd64/ \
--graphics none \
--console pty,target_type=serial \
--extra-args 'console=ttyS0,115200n8'グラフィカルセッションは必要ありません。シリアルインストールには時間がかかるため、永続シェル内で開始してください。同じ VPS 上の Claude Code セッションを維持する tmux ワークフローにより、SSH 接続が切断されても virt-install コンソールへの接続を維持できます。--os-variant debian13 が拒否される場合は、使用中の osinfo-db がそのリリースより古いためです。osinfo-query os を実行し、存在する名前を選択してください。--cpu host-passthrough は vmx を L2 に渡します。これは、L2 がさらに仮想化を行う必要がある場合にだけ必要です。virsh autostart guest1 を使用して、ゲストが安全に起動できるようにします。
ディスクと NIC における virtio バスは、単なる装飾ではありません。エミュレートされた IDE デバイスや e1000 デバイスでは、virtio キューよりも頻繁にハイパーバイザーへのトラップが発生します。ネスト環境では、L0 が単独で処理できない exit が L1 に反映されます。L1 での処理によって、さらに独自の exit が発生する場合があります。
ネットワーク: チュートリアルで省略されがちな部分
VPS にはパブリック IP が 1 つあり、不明な MAC アドレスをフィルタリングするネットワーク基盤の背後にあります。ここから、2 つの結果が生じます。
L2 ゲストをパブリックネットワークにブリッジしても、通常は動作しません。 br0 をパブリック NIC に配置し、ゲストに独自の MAC を割り当てると、ARP が送信されても応答が返らない状態になります。プロバイダーのスイッチが、リースしていない MAC アドレスからのフレームを破棄するためです。この症状が出た場合は、ブリッジのデバッグを続けないでください。原因はこの仕組みにあります。
代わりに NAT ネットワークを使用してください。 libvirt には default が付属します。virbr0、192.168.122.0/24、dnsmasq のリースが利用でき、外向きの通信はすぐに動作します。内向きの通信では、L1 で TLS を終端してからプロキシします。以下の証明書パスは Nginx で Certbot を使用して Let's Encrypt 証明書を発行する の手順に基づいています。
server {
listen 443 ssl;
server_name lab.example.com;
ssl_certificate /etc/letsencrypt/live/lab.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lab.example.com/privkey.pem;
location / {
proxy_pass http://192.168.122.50:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}最初にゲストへ静的リースを割り当ててください (virsh net-edit default)。これにより、proxy_pass 内のアドレスが変わらなくなります。
管理インターフェースはインターネットに公開しないでください。5900 の VNC と 8006 の Proxmox Web UI は loopback にバインドし、SSH トンネル (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) 経由でアクセスします。または、VPS 内に自己ホスト型 WireGuard VPN を構築する 方法を使用します。これにより、192.168.122.0/24 ゲスト範囲全体へ、プライベートネットワーク上の 1 ホップで到達できます。ファイアウォールは狭く保ち、sudo ufw allow 22,80,443/tcp だけを許可してください。それ以外は許可しません。ufw を有効にした直後にゲストの外向き通信が失われた場合、通常の原因は /etc/default/ufw 内の DEFAULT_FORWARD_POLICY="DROP" です。ACCEPT に設定してから、ufw を再読み込みしてください。
VPS 上の Proxmox
Proxmox VE 9 の基盤は Debian 13 です。そのため、Debian VPS にインストールするには pve-no-subscription リポジトリと proxmox-ve パッケージを追加します。リポジトリと keyring の行は、Proxmox の公式ドキュメントにある現行の内容を使用してください。古いブログ記事からコピーした URL では、インストールに失敗します。そもそも Proxmox をレンタルハードウェアで運用すべきかは、以下のネットワーク設定に時間をかける前に決めておく価値があります。自宅の Proxmox 機とレンタル VPS のコストおよび機能の比較では、電力とハードウェアの計算を済ませたうえで、この問題を検討しています。
難しいのはパッケージではありません。Proxmox は vmbr0 を物理 NIC にブリッジする構成を想定しているため、上記の MAC フィルタリングによる行き詰まりに直結します。VPS で機能する構成は、物理ポートを割り当てない NAT またはルーティングされた vmbr0、プライベート範囲に配置したゲスト、そして外部公開するサービス用にホストへ設定した DNAT ルールまたはリバースプロキシです。外部公開するサービスが VM ではなくコンテナの場合は、1 つの Docker Compose ファイルから複数のアプリの前段に Traefik を置く構成で、同じルーティング処理を自動証明書付きで実現できます。最初に /etc/network/interfaces のスナップショットを取得してください。ブリッジ定義を誤ると、コンソールを利用できない可能性があるマシンから締め出されます。
性能を正直に述べる
Nested は single-level より遅くなります。その仕組みは広範ではなく、明確です。コストが発生するのは、通常の命令ではなく、exit とアドレス変換です。 EPT/NPT がある場合、L0 は L1 の L2 用ページテーブルと自身のページテーブルを 1 つの shadow table に統合します。そのため、TLB hit はハードウェア速度で処理されます。TLB miss ではコストが増えます。ハードウェアは guest のページテーブルと shadow table を同時に走査し、L1 が自身のページテーブルを変更するたびに exit が発生して、L0 が shadow table を再同期します。高コストになるのは、guest mode を離れるすべての操作です。I/O、タイマー割り込み、MMIO、プロセッサ間割り込みなどが該当します。L2 の exit は L0 が処理し、L1 を経由して返される場合があります。小さなワーキングセットで CPU に負荷をかける処理は native に近い性能になります。一方、大きなメモリ上のワーキングセットでは TLB miss のコストが増え、syscall、パケット、ディスク I/O が支配的な処理では各層の影響が現れます。
つまり、デバイスにはすべて virtio を使用します。さらに、qcow2 ファイルはプロバイダーがすでに仮想化したディスク上にあります。thin provisioning の層が 2 つ重なり、cache=none によって guest disk 上の同じブロックが 2 つのページキャッシュに同時に保持される状態を防ぎます。ここではベンチマーク結果を示しません。使用する workload を、使用する instance 上で測定してください。
障害パターンと表示される文字列
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used が kvm-ok から表示されます。モジュールが読み込まれていないか、フラグが公開されていません。まず /proc/cpuinfo を確認してください。
kvm: disabled by bios が dmesg に表示されます。ベアメタルでは、ファームウェアで VT-x/SVM の切り替えを有効にしてください。VPS 内で表示される場合は、L0 が拡張機能をゲストに渡していないという意味です。ゲスト内で入力する操作によって変更することはできません。
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported です。 カーネルが認識している CPU に vmx がありません。これも L0 側の判断です。
Could not access KVM kernel module: Permission denied です。 ハードウェアではなく、権限の問題です。ls -l /dev/kvm のグループは kvm、モードは 660 になっている必要があります。自分をそのグループに追加し、新しいログインシェルを起動してください。すでに実行中のセッションには、グループメンバーシップの変更は適用されません。
QEMU の起動時に kvm: Device or resource busy が表示されます。別のハイパーバイザーモジュールが CPU を保持しています。lsmod を実行し、kvm_intel とともに vboxdrv または VMware のモジュールを探してください。使用しないモジュールをアンロードします。
virsh から /var/run/libvirt/libvirt-sock: No such file or directory が表示されます。デーモンが停止しています。sudo systemctl enable --now libvirtd を実行してください。
Proxmox: KVM virtualisation configured, but not available. KVM アクセラレーションが、対応できないホスト上のゲストで有効になっています。ネスト構成を修正するか、設定を無効にしてエミュレーションを使用してください。
Android emulator: x86_64 emulation currently requires hardware acceleration! /dev/kvm と同じです。通常はグループ設定の問題です。
エラーはまったく表示されず、すべての処理が極端に遅い。 アクセラレーターフラグなしで QEMU を実行すると、ソフトウェアエミュレーターである TCG にフォールバックします。動作は正しいものの速度が遅く、数秒で完了するブートが数分かかるようになります。-accel kvm を明示的に指定してください。これにより、QEMU は黙ってエミュレーションに切り替えず、エラーで停止します。
ゲストが実行中に突然消える。 dmesg で Out of memory: Killed process ... qemu-system-x86_64 を確認してください。L2 ゲストは L1 上のプロセスであり、OOM killer は他のプロセスと同じように扱います。L2 の RAM は L1 に固定割り当てされたメモリから確保され、ホストから借用することはありません。
運用: バックアップ、アップグレード、制限
バックアップ。 実行中のゲストの qcow2 をコピーすると、不整合のあるイメージになるおそれがあります。読み取り中もゲストが書き込みを続けるためです。virsh shutdown guest1 を実行し、virsh domstate guest1 が shut off を報告するまで待ってからコピーしてください。シャットダウンコマンドは、ゲストがまだ停止処理中でも戻ることがあります。別の方法として、外部スナップショット(virsh snapshot-create-as guest1 snap1 --disk-only --atomic)を取得し、書き込みをオーバーレイへ振り分けて、静止したベースをコピーします。その後、virsh blockcommit guest1 vda --active --pivot で変更を統合します。コピーは VPS の外部へ転送してください。同じディスク上のスナップショットでは、ディスク障害から保護できません。
アップグレード。 apt full-upgrade は新しい kvm_intel/kvm_amd モジュールをインストールしますが、実行中の kernel は再起動するまで古いモジュールを使い続けます。以前の kernel はインストールしたままにし、kernel を変更するたびに kvm-ok を再実行してください。再起動後に vmx なしで起動しても、別の boot entry を選べば復旧できます。
この構成の限界。 公開 IP が 1 つしかないため、すべての L2 サービスは L1 上の proxy または DNAT ルールを経由して外部に到達します。ライブマイグレーションも利用できません。CPU が競合すると、nested の exit path が最初に影響を受けます。また、複数のゲストを持つ hypervisor は、RAM をすでに割り当て済みのマシンです。nested VM では、固定された割り当てを overcommit で補うことはできません。ラボがこの構成の規模を超えた場合、解決策は nested stack をさらに深くすることではありません。L0 になる専用マシンへ移行すれば、これらの制限は適用されません。
FAQ
Docker を VPS で実行するために、Nested virtualization は必要ですか?
いいえ。コンテナは VPS のカーネルを共有し、/dev/kvm を開くこともありません。そのため、vmx や svm フラグのない通常のインスタンスでも、Docker と Docker Compose は問題なく動作します。Nested virtualization が必要になるのは、2 つ目のカーネルを実行する場合だけです。たとえば、Proxmox の検証環境、Windows ゲスト、Firecracker microVM、Android エミュレーター、VM イメージを起動する CI runner などです。
VPS が Nested virtualization をサポートしているか確認するにはどうすればよいですか?
grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u を実行し、続けて kvm-ok を cpu-checker パッケージから実行します。使用可能なインスタンスでは、vmx(Intel)または svm(AMD)が表示され、kvm-ok は KVM acceleration can be used を返します。また、/dev/kvm が group kvm、mode 660 で存在します。この質問では /sys/module/kvm_intel/parameters/nested は無視してください。そのファイルが示すのは独自の KVM module であり、provider の hypervisor が公開した機能ではありません。
ほとんどの VPS provider が Nested virtualization を無効にしているのはなぜですか?
vmx を公開すると、そのフラグを持つ CPU model をゲストに渡すことになります。その CPU 機能に依存するゲストは、CPU が対応していないマシンへ live migration できません。customer を移動して node を停止する provider では、この機能を有効にすると移行性が失われます。Nested VMX/SVM の code path には、長期にわたる CVE の履歴もあります。一部の host では要求に応じて VM 単位で有効にできます。また、nesting を plan の機能として明記している provider もあります。
Nested VM が public bridge 上でネットワークに接続できません。何が問題ですか?
Provider の switch は、割り当てていない MAC address からの frame を破棄します。そのため、public NIC に bridge 接続した L2 guest が ARP を送信しても、応答を受信できません。br0 の調査は中止し、libvirt の NAT default network(virbr0、192.168.122.0/24)を使用してください。guest には static lease を割り当て、public に公開するものは VPS 自体の reverse proxy または DNAT rule 経由で公開します。
Nested VM はどの程度遅くなりますか?
オーバーヘッドは VM exit と address translation で発生します。EPT/NPT が有効な場合、L2 内の命令実行と TLB hit は hardware speed で動作します。ただし、TLB miss では追加の page table をたどる必要があり、I/O、timer interrupt、MMIO、IPI は L0 が処理し、L1 経由で送り返されることがあります。小さな working set を使う CPU-bound 処理は native に近い性能になります。一方、大きな in-memory working set や syscall、packet、disk に負荷が集中する処理では、各層のオーバーヘッドが現れます。すべてのデバイスで virtio を使用し、ゲストの disk では cache=none を設定してから、自分の workload を測定してください。