VPS能否运行Proxmox?嵌套虚拟化检查方法
多数VPS服务商会隐藏vmx或svm标志。用kvm-ok一分钟检查,确认能否运行KVM或Proxmox虚拟机,并识别“装载KVM模块失败”等实际报错。
简短回答
嵌套虚拟化是指在虚拟机内部运行 hypervisor:您的 VPS 已经是一个 guest,您希望它继续托管自己的 guest。只有当服务商的 hypervisor 明确向您的实例暴露 CPU 的虚拟化扩展时,这种方式才可用。请检查 /proc/cpuinfo 中是否存在 vmx 标志(Intel)或 svm 标志(AMD)。如果两者都不存在,那么在 VPS 内进行任何配置都无法解决问题。
首先明确一点:Docker 不需要这些条件。 容器共享 VPS 的内核,从不接触 /dev/kvm。如果您的实际目标是“在服务器上运行多个容器化服务”,那么现有环境已经满足需求。只有在您需要使用第二个内核、搭建 Proxmox 实验环境、运行 Windows guest、运行 Firecracker microVM、使用 Android 模拟器、构建由真实 VM 组成的 Kubernetes 测试环境,或运行会启动 VM 镜像的 CI runner 时,才需要嵌套虚拟化。
实际嵌套的是什么
共有三层:
- L0,运行在物理服务器上的云服务商 hypervisor。您无法访问这一层。
- L1,您的 VPS。对 L0 来说,它只是一个 guest。
- L2,您要在 VPS 内运行的 VM。
硬件虚拟化在 Intel 上使用 VT-x(vmx 标志)和 EPT,在 AMD 上使用 AMD-V / SVM(svm)和 RVI/NPT。hypervisor 使用这些指令进入 guest 模式,并让 CPU 同时遍历两级页表。
这些机制都不是为可重入设计的,因此嵌套需要模拟:L1 执行 VMX 指令时会陷入 L0,由 L0 代替 L1 维护 L2 的影子结构。KVM 对此支持较好,但每次退出时都需要由 L0 执行额外工作,因此云服务商必须主动启用该功能。
要让 L2 使用硬件加速,以下两个条件必须同时满足:
- L0 的 KVM 模块使用
nested=1加载。 - L0 为您的 VPS 提供包含该标志的 CPU 模型:在 libvirt 中为
<cpu mode='host-passthrough'/>,在 Proxmox 中为cpu: host,在原始 QEMU 中为-cpu host。通用模拟模型(qemu64、kvm64)会隐藏vmx,即使全局已启用嵌套。
一分钟检查您的 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有一个文件经常被引用,但也经常被误解:
cat /sys/module/kvm_intel/parameters/nested # Y or N在您的 VPS 中,该文件表示您的 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_intel虚拟机运行时无法卸载模块,因此请先关闭客户机。
为什么大多数 VPS 主机默认关闭嵌套虚拟化
- 实时迁移。 向您提供
vmx,意味着暴露带有该标志的 CPU 模型;依赖这些 CPU 特性的虚拟机无法安全迁移到 CPU 不具备这些特性的机器。通过迁移客户来疏散节点的主机,一旦启用嵌套虚拟化,就会失去这种能力。 - 攻击面。 嵌套 VMX/SVM 路径属于内核虚拟化层中最复杂的代码,其 CVE 历史也反映了这一点。
- L0 可能不是 KVM。 如果
systemd-detect-virt输出vmware、xen或microsoft,那么嵌套规则由该虚拟化栈决定,而不是由 KVM 决定。
您的实例没有该标志?请联系支持团队(有些主机可按虚拟机单独启用),选择明确记录支持嵌套虚拟化的方案,或迁移到独立服务器。下文假设您在显示该标志的机器上拥有 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'无需图形会话。串行安装需要运行一段时间,因此请在持久化 shell 中启动;同样的 在 VPS 上保持 Claude Code 会话的 tmux 工作流,可在 SSH 连接中断后继续保持 virt-install 控制台连接。如果 --os-variant debian13 被拒绝,说明您的 osinfo-db 版本早于该发行版,请运行 osinfo-query os,并选择一个已存在的名称。--cpu host-passthrough 将 vmx 向下透传到 L2,仅当 L2 还需要继续进行虚拟化时才需要。使用 virsh autostart guest1 确保虚拟机能够安全启动。
磁盘和网卡使用的 virtio 总线并非装饰配置:模拟的 IDE 和 e1000 设备比 virtio 队列更频繁地陷入 hypervisor,而在嵌套虚拟化环境中,每次陷入都要支付两次开销。
网络:教程通常略过的部分
您的 VPS 只有一个公网 IP,并且位于会过滤未知 MAC 地址的网络设备之后。由此会产生两个后果。
将 L2 客户机桥接到公网通常无法工作。 将 br0 放到公网网卡上,为客户机分配独立的 MAC 地址后,您会看到 ARP 请求发出,但没有任何响应。因为提供商的交换机丢弃了来自未向您租用的 MAC 地址的帧。如果这是您的现象,请停止排查网桥;问题机制就是如此。
改用 NAT 网络。 libvirt 提供 default:virbr0、192.168.122.0/24,并通过 dnsmasq 分配租约,出站连接可立即使用。对于入站连接,请在 L1 上终止 TLS,然后将请求代理到内部服务。下面的证书路径来自 使用 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;
}
}先为客户机分配静态租约(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 客户机地址段都只需经过一个私有网络跃点即可到达。防火墙规则保持最小化,只允许 sudo ufw allow 22,80,443/tcp,其他一律禁止。如果启用 ufw 后客户机立即失去出站连接,通常是 /etc/default/ufw 中的 DEFAULT_FORWARD_POLICY="DROP" 配置导致的。将其设置为 ACCEPT,然后重新加载 ufw。
VPS 上的 Proxmox
Proxmox VE 9 的底层是 Debian 13,因此可以通过添加 pve-no-subscription 仓库和 proxmox-ve 软件包,将其安装到 Debian VPS 上。仓库和 keyring 配置行应以 Proxmox 当前官方文档为准;从旧博客文章复制的 URL 可能导致安装失败。在继续处理下面的网络配置之前,最好先确定 Proxmox 是否适合部署在租用的硬件上。家庭 Proxmox 主机与租用 VPS 的成本和能力对比已经完成了电力和硬件方面的计算,可以直接回答这个问题。
软件包不是难点。Proxmox 要求 vmbr0 桥接到物理 NIC,这会直接遇到上文所述的 MAC 过滤限制。VPS 上可行的结构是使用不连接物理端口的 NAT 或路由 vmbr0,让虚拟机和容器处于私有网段,并在主机上为需要公网访问的服务配置 DNAT 规则或反向代理。如果面向公网的服务是容器而不是虚拟机,使用 Traefik 从一个 Docker Compose 文件为多个应用提供入口可以完成相同的路由工作,并自动申请证书。先创建快照 /etc/network/interfaces:错误的网桥配置可能会让您无法访问一台未必提供控制台的主机。
性能表现:如实说明
嵌套虚拟化比单层虚拟化更慢,而且原因很明确,并非来自某个分散的开销:成本不在内存访问,而在退出处理。有了 EPT/NPT 后,L0 会为 L2 维护影子页表,普通内存读取可达到硬件速度。真正昂贵的是每次离开客户机模式的操作,包括 I/O、定时器中断、MMIO 和处理器间中断,因为 L2 退出由 L0 处理,还可能经由 L1 反射回去。对已在 RAM 中的数据执行 CPU 密集型任务时,性能接近原生;而系统调用、数据包和磁盘 I/O 占主导的工作负载则会明显受到多层虚拟化影响。
因此,应尽量使用 virtio 设备。还要注意,您的 qcow2 文件位于服务商已经虚拟化的磁盘上,相当于叠加了两层精简配置;此时,cache=none 会阻止相同的数据块同时存在于两个页缓存中。这里不提供基准测试数据:请在您自己的实例上测量您自己的工作负载。
故障模式及其对应的提示信息
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;将自己加入该组,然后启动新的登录 shell,因为组成员身份不会应用到已经运行的会话。
QEMU 启动时出现 kvm: Device or resource busy。另一个 hypervisor 模块占用了 CPU:运行 lsmod,查找 vboxdrv 或 VMware 模块,以及 kvm_intel,然后卸载不需要的模块。
从 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 加速,但客户机启用了 KVM 加速。修复嵌套虚拟化配置,或者取消该选项并接受仿真。
Android emulator:x86_64 emulation currently requires hardware acceleration! 再次检查 /dev/kvm,通常是组权限问题。
完全没有错误,但运行极慢。 未指定 accelerator flag 的 QEMU 会回退到 TCG,即软件 emulator。它能够正常工作,但速度很慢;原本按秒计算的启动时间会变成按分钟计算。显式传入 -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 snapshot-create-as guest1 snap1 --disk-only --atomic),让写入内容转移到覆盖层,同时复制此时保持静态的基础镜像,完成后再使用 virsh blockcommit 将其合并回去。将副本传输到 VPS 之外;保存在同一磁盘上的快照无法防范磁盘故障。
升级。 apt full-upgrade 会安装新的 kvm_intel/kvm_amd 模块,但正在运行的内核会继续使用旧模块,直到重启。保留之前的内核,并在每次内核变更后重新运行 kvm-ok:如果主机启动后没有 vmx,仍可通过另一个启动项恢复工作。
扩展到此为止。 只有一个公网 IP 时,所有 L2 服务都必须通过 L1 上的代理或 DNAT 规则访问公网。无法进行实时迁移。CPU 发生争用时,嵌套退出路径会最先受到影响。运行多个客户机的 hypervisor,其 RAM 已经全部分配给这些客户机;嵌套 VM 无法通过超额分配摆脱固定的资源限制。当实验环境超出这一规模时,解决方案不是继续增加嵌套层级,而是使用一台专用主机,在其中由您作为 L0 运行,这些限制也就不再适用。
FAQ
在 VPS 上运行 Docker 是否需要嵌套虚拟化?
不需要。容器共享 VPS 的内核,并且不会打开 /dev/kvm,因此没有 vmx 或 svm 标志的普通实例也可以正常运行 Docker 和 Docker Compose。只有在需要第二个内核时,才需要嵌套虚拟化,例如运行 Proxmox 实验环境、Windows 客户机、Firecracker microVM、Android 模拟器,或会启动 VM 镜像的 CI runner。
如何检查 VPS 是否支持嵌套虚拟化?
运行 grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u,然后从 cpu-checker 软件包中运行 kvm-ok。可用的实例会输出 vmx(Intel)或 svm(AMD);kvm-ok 会报告 KVM acceleration can be used;/dev/kvm 存在,且组为 kvm、权限模式为 660。不要根据 /sys/module/kvm_intel/parameters/nested 判断这个问题。该文件描述的是你自己的 KVM 模块,而不是提供商的 hypervisor 向你暴露的功能。
为什么大多数 VPS 提供商会禁用嵌套虚拟化?
暴露 vmx 就意味着向客户机提供带有该标志的 CPU 模型。依赖这些 CPU 功能的客户机无法实时迁移到不具备这些功能的主机上。提供商通常通过迁移客户实例来疏散节点,因此不能接受这一限制。嵌套 VMX/SVM 代码路径也有较长的 CVE 历史。一些主机仍可按 VM 请求启用该功能,另一些提供商则将嵌套虚拟化列为套餐功能。
我的嵌套 VM 在公网桥接网络上没有网络连接。问题在哪里?
提供商的交换机会丢弃来自未分配给你的 MAC 地址的帧。因此,桥接到公网网卡的 L2 客户机会发送 ARP,但收不到任何响应。不要继续排查 br0。改用 libvirt 的 NAT default 网络(virbr0、192.168.122.0/24),为客户机分配静态租约,然后在 VPS 本身通过反向代理或 DNAT 规则发布公网服务。
嵌套 VM 会慢多少?
开销主要发生在 VM exit,而不是内存访问上。启用 EPT/NPT 后,L2 内部的普通读写可以接近硬件速度;I/O、定时器中断、MMIO 和 IPI 则由 L0 处理,并可能需要经由 L1 返回。对已位于 RAM 中的数据执行 CPU 密集型任务时,性能通常接近原生;系统调用、网络包和磁盘密集型负载则会受到每一层的影响。所有设备都使用 virtio,并在客户机磁盘上使用 cache=none,然后根据自己的工作负载进行测试。