VPSでProxmoxは動く?入れ子状の仮想化の確認方法
VPS上でProxmoxなどの仮想マシンを動かすには、ホスト側でVMX/SVMフラグが公開されている必要があります。kvm-okコマンドを使って、お使いのVPSがNested virtualizationに対応しているか1分で確認しましょう。エラーが出る原因や、Dockerとの違いについても詳しく解説します。
結論
Nested virtualization(入れ子状の仮想化)とは、仮想マシン内でハイパーバイザを動作させることです。VPS自体がすでにゲストであり、その中でさらにゲストをホストする場合を指します。これは、プロバイダーのハイパーバイザが、インスタンスに対してCPUの仮想化拡張機能を意図的に公開している場合にのみ機能します。vmx flag (Intel) または svm (AMD) を /proc/cpuinfo で確認してください。どちらも表示されない場合、VPS内での設定変更では解決できません。
重要な注意点:Dockerにはこれらは一切不要です。 コンテナはVPSのカーネルを共有し、/dev/kvm には一切触れません。もし目的が「サーバー上のコンテナで複数のサービスを動かすこと」であれば、すでに必要な環境は整っています。Nested virtualization が必要になるのは、2つ目のカーネルを必要とする場合です。例として、Proxmoxラボ、Windowsゲスト、Firecracker microVMs、Androidエミュレータ、実VMによるKubernetesテストベッド、またはVMイメージを起動するCIランナーなどが挙げられます。
ネストの正体
3つのレイヤーがあります:
- L0 — ベアメタル上で動作するプロバイダーの hypervisor です。ユーザーにアクセス権はありません。
- L1 — 利用者の VPS です。L0 から見れば単なる guest です。
- L2 — VPS 内で実行しようとしている VM です。
ハードウェア仮想化には、Intel の場合は VT-x (vmx flag) と EPT、AMD の場合は AMD-V / SVM (svm) と RVI/NPT が必要です。hypervisor はこれらの命令を使用して guest mode へ移行し、CPU が同時に2つの page table を走査できるようにします。
これらは再帰的な動作(re-entrant)を想定して設計されていません。そのため、ネストはエミュレーションされます。L1 が VMX 命令を実行すると L0 にトラップされ、L0 が L1 の代わりに L2 用の shadow structures を維持します。KVM はこれを効率的に行いますが、L0 は exit のたびに余分な処理を行う必要があります。そのため、プロバイダー側での opt-in が必要になります。
L2 の加速(accelerated)には、以下の2つの条件が両方満たされる必要があります:
- L0 の KVM module が
nested=1付きでロードされていること。 - L0 が VPS に対して、該当する flag を持つ CPU model を提供していること。具体的には、libvirt では
<cpu mode='host-passthrough'/>、Proxmox ではcpu: host、生の QEMU では-cpu hostです。汎用の emulated model (qemu64,kvm64) では、ネストがグローバルに有効であってもvmxは隠蔽されます。
1分間でVPSの状態を確認する
# 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頻繁に引用され、誤解されやすいファイルが1つあります。
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が実行中の場合、モジュールの削除は拒否されます。先にゲストをシャットダウンしてください。
多くのVPSホストが機能を無効にしている理由
- Live migration.
vmxを有効にすると、その CPU flag を持つ CPU モデルが露出します。その CPU 機能に依存する guest は、それらを持たないマシンへ安全に migration できません。migration によってノードの負荷を分散するホストは、nesting を有効にした瞬間にこの機能を失います。 - Attack surface. nested VMX/SVM のパスは、kernel の virtualization layer において最も複雑なコードの一つであり、多くの CVE が報告されています。
- L0 may not be KVM. もし
systemd-detect-virtがvmware、xen、またはmicrosoftと出力した場合、nesting のルールは KVM ではなく、その stack のものになります。
インスタンスに flag がない場合は、サポートに問い合わせてください(VM ごとに有効化できる場合があります)。nesting が記載されているプランを選択するか、dedicated box へ移行してください。これ以降の説明は、そのマシンで flag が表示され、root 権限があることを前提としています。
libvirt を使用した L2 guest の実行
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 workflow を使用すれば、SSH接続が切断されても virt-install コンソールを維持できます。--os-variant debian13 が拒否される場合は、osinfo-db がリリースより前のバージョンです。osinfo-query os を実行し、存在する名前を選択してください。--cpu host-passthrough は vmx を L2 へ転送します。これは L2 自体が仮想化を行う場合にのみ必要です。virsh autostart guest1 を使用して guest をブート可能にしてください。
Disk および NIC の virtio バスは、単なる装飾ではありません。emulated IDE や e1000 デバイスは、virtio queue よりも頻繁に hypervisor へ trap します。ネスト環境では、すべての trap に二重のコストがかかります。
Networking: チュートリアルで省略されがちな点
VPSには1つの public IPがあり、未知の MAC address をフィルタリングする fabric の背後に配置されています。これにより、以下の2つの結果が生じます。
L2 guest を public network にブリッジしても、通常は動作しません。 public NIC に br0 を設定し、guest に独自の MAC address を割り当てると、ARP は送信されますが、応答は返ってきません。プロバイダーの switch は、リースされていない MAC address からのフレームを破棄するためです。この症状が発生する場合、bridge のデバッグを中止してください。これが仕様です。
代わりに NAT network を使用してください。 libvirt には default が含まれています: virbr0, 192.168.122.0/24, dnsmasq leases。これにより、即座に outbound 通信が可能になります。inbound 通信については、L1 で TLS を終端し、そこからプロキシしてください。以下の certificate path は Certbot を使用して Nginx で 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;
}
}まず guest に static lease (virsh net-edit default) を設定し、その proxy_pass 内の address を固定してください。
Management interface はインターネットから隔離してください。5900 の VNC と 8006 の Proxmox web UI は loopback に配置し、SSH tunnel (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) または VPS への self-hosted WireGuard VPN 経由でアクセスしてください。これにより、192.168.122.0/24 guest range 全体が 1 hop の private ネットワークになります。firewall は最小限に制限してください。sudo ufw allow 22,80,443/tcp のみを許可し、それ以外は許可しないでください。ufw を有効にした直後に guest の outbound 通信が切断される場合、一般的な原因は /etc/default/ufw 内の DEFAULT_FORWARD_POLICY="DROP" です。これを ACCEPT に設定し、ufw を reload してください。
VPS上でのProxmox
Proxmox VE 9のベースはDebian 13です。Debian VPSにpve-no-subscriptionリポジトリとproxmox-veパッケージを追加することでインストールできます。リポジストリとkeyringの行は、Proxmoxの公式ドキュメントから取得してください。古いブログ記事のURLを使用すると、インストールに失敗します。
パッケージの導入は難しくありません。Proxmoxはvmbr0を物理NICにブリッジすることを想定していますが、これは前述のMACフィルタリングの問題に直面します。VPSで動作する構成は、物理ポートを接続しないNATまたはルーティングされたvmbr0です。ゲストはプライベートレンジに配置し、公開サービスにはホスト側でDNATルールまたはリバースプロキシを使用してください。公開サービスがVMではなくコンテナである場合は、1つのDocker Composeファイルから複数のアプリを公開するTraefikを使用することで、自動証明書とともに同様のルーティングが可能です。まず/etc/network/interfacesのSnapshotを作成してください。ブリッジの設定を誤ると、コンソールにアクセスできないマシンからロックアウトされる可能性があります。
パフォーマンスの現状
Nested virtualizationは、Single-levelよりも低速です。その原因はメモリへのアクセスではなく、Exit(脱出)にあります。EPT/NPTが有効な場合、L0はL2用のShadow Page Tablesを保持するため、通常のメモリ読み取りはハードウェア速度で行われます。コストがかかるのは、Guest modeを抜けるすべての操作です。具体的には、I/O、Timer interrupts、MMIO、Inter-processor interruptsが該当します。L2 ExitはL0によって処理され、L1を経由して反映される可能性があるためです。RAM上のデータに対するCPU負荷の高い処理は、Nativeに近い速度で動作します。一方、Syscalls、Packet、Disk I/Oが支配的な処理では、レイヤーによる影響を顕著に感じることになります。
結論として、あらゆる場面でvirtioデバイスを使用してください。また、qcow2ファイルは、プロバイダーが既に仮想化しているディスク上に配置されます。これは2つのThin-provisioningレイヤーが重なっている状態です。Guest disk上のcache=noneは、同じブロックが2つのPage cacheに同時に存在することを防ぎます。ベンチマーク数値はここでは示しません。自身のインスタンスで、自身のワークロードを測定してください。
失敗パターンと表示される文字列
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used (kvm-okより)。モジュールがロードされていないか、flagが公開されていません。まず/proc/cpuinfoを確認してください。
kvm: disabled by bios (dmesg内)。ベアメタル環境の場合は、firmwareのVT-x/SVM設定を有効にしてください。VPS環境の場合は、L0がextensionを提供していません。guest側で設定を変更しても解決しません。
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でgroupがkvm、modeが660であることを確認してください。そのgroupにユーザーを追加した後、新しいlogin shellを起動してください。既存のsessionにはgroup membershipは反映されません。
QEMU起動時のkvm: Device or resource busy。別のhypervisor moduleがCPUを占有しています。lsmodを実行し、vboxdrvやVMware moduleがkvm_intelと一緒に表示されていないか確認してください。不要なものをunloadしてください。
virshからの/var/run/libvirt/libvirt-sock: No such file or directory。daemonが停止しています。sudo systemctl enable --now libvirtdを実行してください。
Proxmox: KVM virtualisation configured, but not available. KVM accelerationが有効ですが、hostがそれを提供できません。nestingを修正するか、チェックを外してemulationを使用してください。
Android emulator: x86_64 emulation currently requires hardware acceleration! 再び/dev/kvmの問題です。通常はgroupの問題です。
エラーは表示されませんが、動作が極端に遅い。 accelerator flagがないQEMUは、software emulatorであるTCGにフォールバックします。これは正常な動作ですが、非常に低速です。起動時間が秒単位から分単位に増大します。-accel kvmを明示的に指定してください。そうすれば、QEMUは静かにemulationするのではなく、エラーを出して停止します。
実行中にguestが消失する。 dmesgでOut of memory: Killed process ... qemu-system-x86_64を確認してください。L2 guestはL1上のprocessであり、OOM killerの対象となります。L2のRAMはL1の固定割り当てから消費されます。hostからメモリを借りることはできません。
運用: バックアップ、アップグレード、制限事項
バックアップ. 稼働中の guest の qcow2 をそのままコピーすると、イメージが破損します。virsh shutdown guest1 を使用してコピーするか、外部スナップショット (virsh snapshot-create-as guest1 snap1 --disk-only --atomic) を作成してください。これにより、書き込みは overlay へ転送され、静止した base をコピーできます。コピー完了後、virsh blockcommit で統合します。コピーしたデータは VPS の外部へ転送してください。同じディスク上のスナップショットでは、ディスク障害を防げません。
アップグレード. apt full-upgrade は新しい kvm_intel/kvm_amd モジュールをインストールしますが、稼働中の kernel は再起動するまで古いモジュールを保持します。以前の kernel をインストールしたままにし、kernel を変更するたびに kvm-ok を再実行してください。vmx がない状態で起動しても、ブートエントリを一つ追加すれば復旧可能です。
スケーラビリティの限界. 公開 IP が1つの場合、すべての L2 サービスは L1 上の proxy または DNAT ルールを経由して外部と通信します。Live migration は利用できません。CPU 競合が発生すると、nested exit パスが最初に影響を受けます。また、複数の guest を持つ hypervisor は、すでに RAM を消費した状態にあります。nested VM は、固定された割り当てに対して overcommit を行うことはできません。ラボの規模が拡大した際の解決策は、nested stack を深くすることではありません。L0 として動作し、これらの制限を受けない専用マシンを導入することです。
FAQ
VPSでDockerを動かすために、入れ子状の仮想化(nested virtualization)は必要ですか?
不要です。コンテナはVPSのkernelを共有し、/dev/kvm を開くことはありません。そのため、vmx や svm フラグがない通常のインスタンスでも、DockerおよびDocker Composeは正常に動作します。入れ子状の仮想化が必要になるのは、2つ目のkernelが必要な場合のみです。具体的には、Proxmoxのラボ、Windowsゲスト、Firecracker microVMs、Androidエミュレータ、またはVMイメージを起動するCIランナーなどが該当します。
VPSが入れ子状の仮想化をサポートしているか確認する方法は?
grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u を実行した後、cpu-checker パッケージの kvm-ok を実行してください。サポートされている場合、Intelなら vmx、AMDなら svm が出力されます。また、kvm-ok は KVM acceleration can be used を報告し、/dev/kvm がグループ kvm およびモード 660 で存在します。この質問に関しては /sys/module/kvm_intel/parameters/nested は無視してください。このファイルはプロバイダーのhypervisorが公開しているものではなく、自身のKVMモジュールについて記述しているためです。
なぜ多くのVPSプロバイダーは入れ子状の仮想化を無効にしているのですか?
vmx を公開することは、そのフラグを持つCPUモデルをゲストに渡すことを意味します。そのCPU機能に依存するゲストは、その機能を持たないCPUを搭載したマシンへライブマイグレーションすることができません。顧客を移動させてノードの負荷を分散させるプロバイダーにとって、これは不都合な機能です。また、入れ子状のVMX/SVMのコードパスには、多くのCVE履歴が存在します。リクエストに応じてVMごとに有効化できるホストもあれば、将来の計画機能として記載しているホストもあります。
入れ子状のVMがパブリックブリッジでネットワークに接続できません。原因は何ですか?
プロバイダーのスイッチは、割り当てられていないMACアドレスからのフレームを破棄します。そのため、パブリックNICにブリッジされたL2ゲストがARPを送信しても、応答は返ってきません。br0 のデバッグは止めて、libvirtのNAT default ネットワーク(virbr0, 192.168.122.0/24)を使用してください。ゲストには静的なリースを割り当て、パブリックな通信はVPS上のリバースプロキシまたはDNATルールを通じて公開してください。
入れ子状のVMはどの程度遅くなりますか?
パフォーマンス低下の主な要因は、メモリへのアクセスではなくVM exitsです。EPT/NPTが有効であれば、L2内部の通常の読み書きはハードウェア速度で行われます。一方で、I/O、タイマー割り込み、MMIO、IPIはL0によって処理され、L1を経由して戻される可能性があります。RAM上のデータに対するCPU負荷の高い処理は、ネイティブに近い速度で動作します。syscall、パケット処理、ディスクI/Oが重いワークロードでは、レイヤーごとのオーバーヘッドが顕著になります。すべての箇所でvirtioデバイスとゲストディスクへの cache=none を使用し、自身のワークロードで測定してください。