VPS 可以執行 Proxmox 嗎?巢狀虛擬化檢查
多數 VPS 供應商會隱藏 vmx 旗標。使用 kvm-ok 在 1 分鐘內檢查,了解能否執行 KVM 或 Proxmox guest,以及會看到的確切錯誤訊息。
簡短答案
巢狀虛擬化是指在虛擬機器內執行 hypervisor:您的 VPS 已經是 guest,而您希望它再託管自己的 guest。只有在供應商的 hypervisor 明確將 CPU 的虛擬化擴充功能公開給您的執行個體時,這項功能才會運作。請檢查 /proc/cpuinfo 是否有 vmx 旗標(Intel)或 svm 旗標(AMD);如果兩者都沒有,您在 VPS 內進行的任何設定都無法修正這個問題。
先釐清一點:Docker 不需要這些功能。 容器共用 VPS 的 kernel,且完全不會使用 /dev/kvm。如果實際需求是「在我的伺服器上於容器中執行數個服務」,您目前已有所需條件。需要巢狀虛擬化的情況,包括使用 第二個 kernel、建立 Proxmox 實驗環境、執行 Windows guest、使用 Firecracker microVM、執行 Android emulator、建立由實際 VM 組成的 Kubernetes 測試環境,或執行會啟動 VM 映像檔的 CI runner。
實際上是哪些層級在巢狀執行
共有 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。
這 2 種機制原本都不是為可重入設計,因此巢狀虛擬化必須透過模擬完成:L1 執行 VMX 指令時會 trap 到 L0,由 L0 代替 L1 維護 L2 的 shadow 結構。KVM 能有效處理這項工作,但每次 exit 都會增加 L0 的額外負載,因此供應商必須明確啟用此功能。
要讓 L2 使用硬體加速,以下 2 個條件都必須成立:
- L0 的 KVM module 必須以
nested=1載入。 - L0 必須提供帶有該 flag 的 CPU model 給您的 VPS:libvirt 使用
<cpu mode='host-passthrough'/>,Proxmox 使用cpu: host,raw QEMU 使用-cpu host。即使全域已啟用巢狀虛擬化,通用的模擬 CPU 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 存在。如果旗標存在,但裝置節點不存在,請手動載入模組,並查看 kernel log:
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 guest 是否能再巢狀執行第三層 guest。它不表示 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 執行期間無法移除模組,因此請先關閉 guest。
為什麼多數 VPS 主機商會關閉此功能
- 即時遷移。 提供
vmx代表必須公開包含該旗標的 CPU 型號;而依賴這些 CPU 功能的 guest,無法安全遷移到 CPU 不支援這些功能的機器。主機商若透過遷移客戶工作負載來清空節點,啟用巢狀虛擬化後就會失去這項彈性。 - 攻擊面。 巢狀 VMX/SVM 路徑屬於 kernel 虛擬化層中最複雜的程式碼之一,也有相應的 CVE 歷史。
- L0 不一定是 KVM。 如果
systemd-detect-virt顯示vmware、xen或microsoft,巢狀虛擬化規則就由該堆疊決定,而不是由 KVM 決定。
執行個體沒有該旗標嗎?請洽詢支援人員(部分主機商可針對個別 VM 啟用),選擇明確記載支援巢狀虛擬化的方案,或改用 dedicated box。以下內容假設您在顯示該旗標的機器上擁有 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'不需要圖形工作階段。序列安裝需要執行一段時間,因此請在持久化 shell 中啟動:相同的 可在 VPS 上維持 Claude Code 工作階段的 tmux 工作流程,可讓 virt-install console 在 SSH 連線中斷後仍保持連線。如果 --os-variant debian13 被拒絕,表示您的 osinfo-db 早於該版本的發行版本。請執行 osinfo-query os,並選擇一個現有的名稱。--cpu host-passthrough 會將 vmx 向下轉送至 L2,只有在 L2 也必須進一步執行虛擬化時才需要。使用 virsh autostart guest1 確保 guest 能安全開機。
磁碟與 NIC 上的 virtio bus 並非裝飾:模擬的 IDE 與 e1000 裝置比 virtio queues 更常陷入 hypervisor,而在巢狀虛擬化中,每次 trap 都必須付出兩次成本。
網路:教學通常略過的部分
您的 VPS 只有一個公用 IP,且位於會過濾未知 MAC 位址的網路架構後方。因此會產生兩個結果。
將 L2 guest 橋接到公用網路通常無法運作。 將 br0 設定在公用 NIC 上,並為 guest 指定自己的 MAC 位址。您會看到 ARP 封包送出,卻沒有任何回應,因為供應商的交換器會丟棄來自未租用給您的 MAC 位址之框架。如果出現這種現象,請停止除錯 bridge;這就是實際機制。
請改用 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;
}
}請先為 guest 設定靜態租約(virsh net-edit default),讓 proxy_pass 中的位址固定不變。
管理介面不應暴露在網際網路上:5900 上的 VNC 與 8006 上的 Proxmox Web UI 應繫結至 loopback,透過 SSH tunnel(ssh -N -L 8006:127.0.0.1:8006 you@your-vps)存取,或經由 在 VPS 中自架 WireGuard VPN 連線。如此一來,整個 192.168.122.0/24 guest 範圍只需經過一個私有網路躍點即可到達。防火牆規則請維持精簡,只允許 sudo ufw allow 22,80,443/tcp,其他一律拒絕。若啟用 ufw 後 guest 立即失去對外連線,通常是因為 DEFAULT_FORWARD_POLICY="DROP" 位於 /etc/default/ufw。請將其設為 ACCEPT,再重新載入 ufw。
VPS 上的 Proxmox
Proxmox VE 9 底層使用 Debian 13,因此可在 Debian VPS 上加入 pve-no-subscription repository 並安裝 proxmox-ve package。請從 Proxmox 官方目前的文件取得 repository 與 keyring 設定行。從舊部落格文章複製的 URL 可能會導致安裝失敗。在開始處理下方的網路設定前,應先確認 Proxmox 是否適合部署在租用硬體上。家用 Proxmox 主機與租用 VPS 的成本及能力比較已先完成電力與硬體的計算,可直接用來評估這個問題。
套件不是最困難的部分。Proxmox 預期 vmbr0 會橋接至實體 NIC,但這會直接遇到前述的 MAC filtering dead end。在 VPS 上可行的架構,是使用沒有連接實體埠的 NAT'd 或 routed vmbr0,讓 guest 位於 private range,並在 host 上設定 DNAT rules 或 reverse proxy,處理需要公開存取的服務。若對外服務是 container 而非 VM,使用 Traefik 從單一 Docker Compose 檔案代理多個 app可執行相同的 routing 工作,並自動管理憑證。先建立 Snapshot /etc/network/interfaces:錯誤的 bridge 定義可能會讓你無法連回沒有 console 存取權的機器。
效能:如實說明
巢狀虛擬化比單層虛擬化慢,而且原因很明確,不是各處都平均增加成本:成本不在記憶體存取,而在退出事件。 啟用 EPT/NPT 時,L0 會維護 L2 的陰影頁表,通常的記憶體讀取可維持硬體原生速度。真正昂貴的是每個離開 guest mode 的操作,包括 I/O、計時器中斷、MMIO 及處理器間中斷,因為 L2 exit 由 L0 處理,且可能再經由 L1 轉送回去。對已在 RAM 中的資料進行 CPU 密集型處理時,效能通常接近原生;但若工作負載主要由 syscall、封包與磁碟 I/O 構成,就會明顯受到多層虛擬化影響。
因此,應全面使用 virtio 裝置。此外,您的 qcow2 檔案位於供應商已虛擬化的磁碟上,等於疊加兩層 thin provisioning;當 guest 磁碟上的 cache=none 發生時,相同區塊可能同時存在於兩層 page cache 中。本文不提供基準測試數據,請在自己的 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 未將這些擴充功能交給您;您在 guest 中輸入任何指令都無法改變此狀況。
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported。 kernel 所看到的 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. guest 在無法提供 KVM 加速的 host 上啟用了 KVM 加速。請修正巢狀虛擬化設定,或取消勾選並接受模擬執行。
Android emulator:x86_64 emulation currently requires hardware acceleration! 再次檢查 /dev/kvm,通常是群組權限問題。
完全沒有錯誤,但所有作業都極其緩慢。 未指定 accelerator flag 的 QEMU 會退回使用 TCG,也就是軟體模擬器。這種方式可正常運作,但速度很慢;原本以秒計的開機時間會變成以分鐘計。請明確傳入 -accel kvm,讓 QEMU 在發生問題時停止並顯示錯誤,而不是靜默進行模擬。
guest 在執行期間消失。 請在 dmesg 中尋找 Out of memory: Killed process ... qemu-system-x86_64。L2 guest 是 L1 上的程序,OOM killer 會以一般程序的方式處理它。L2 的 RAM 取自 L1 的固定配置,無法向 host 借用記憶體。
操作說明:備份、升級與限制
備份。 複製執行中的 guest qcow2 會得到損毀的映像檔。請先執行 virsh shutdown guest1 再複製,或建立外部快照(virsh snapshot-create-as guest1 snap1 --disk-only --atomic),讓寫入內容轉向 overlay,同時複製目前已靜態化的基礎映像,之後再使用 virsh blockcommit 將變更合併回去。請將複本移出 VPS;儲存在同一磁碟上的快照無法提供實質保護。
升級。 apt full-upgrade 會安裝新的 kvm_intel/kvm_amd 模組,但執行中的 kernel 在重新開機前仍會使用舊模組。請保留上一版 kernel,並在每次變更 kernel 後重新執行 kvm-ok:若主機重新啟動後沒有 vmx,只需從另一個開機項目啟動即可恢復運作。
何時無法繼續擴充。 只有一個公開 IP 時,所有 L2 服務都必須透過 L1 上的 proxy 或 DNAT 規則連到外部網路。Live migration 不在可行選項之內。發生 CPU 競爭時,nested exit 路徑會最先受到影響。此外,擁有多個 guest 的 hypervisor 代表主機 RAM 已經被這些 guest 分配使用;nested VM 無法透過 overcommit 突破固定的資源配置。當實驗環境超出這些限制時,解決方案不是再增加 nested 層級,而是改用專用主機,讓你位於 L0,以上限制也就不再適用。
FAQ
執行 Docker 的 VPS 需要 nested virtualization 嗎?
不需要。容器共用 VPS 的 kernel,且不會開啟 /dev/kvm,因此沒有 vmx 或 svm flag 的一般 instance 也能正常執行 Docker 和 Docker Compose。只有在需要第二個 kernel 時,才會用到 nested virtualization,例如 Proxmox lab、Windows guest、Firecracker microVM、Android emulator,或會啟動 VM image 的 CI runner。
如何確認 VPS 支援 nested virtualization?
執行 grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u,接著從 cpu-checker package 執行 kvm-ok。可用的 instance 會顯示 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 等於提供帶有該 flag 的 CPU model。依賴這些 CPU feature 的 guest 無法 live migrate 到 CPU 不具備這些 feature 的 machine。會透過搬移客戶來排空 node 的 provider,因而必須放棄這項能力。nested VMX/SVM code path 也有長期的 CVE 紀錄。有些 host 仍可依每個 VM 的要求啟用此功能,另一些則將 nesting 列為方案功能。
nested VM 在 public bridge 上沒有網路。問題出在哪裡?
Provider 的 switch 會丟棄來自未向你租用之 MAC address 的 frame,因此 bridged 到 public NIC 的 L2 guest 送出 ARP 後不會收到回覆。不要再排查 br0,改用 libvirt 的 NAT default network(virbr0、192.168.122.0/24),為 guest 指定 static lease,並透過 VPS 本身的 reverse proxy 或 DNAT rule 發布公開服務。
nested VM 會慢多少?
效能成本發生在 VM exit,而不是 memory access。啟用 EPT/NPT 後,L2 內部的一般讀寫會以 hardware speed 執行;I/O、timer interrupt、MMIO 和 IPI 則由 L0 處理,可能還會經過 L1 往返。已在 RAM 中處理資料的 CPU-bound work 通常接近 native;system call、packet 和 disk 負載較高的 workload 則會感受到每一層的成本。所有地方都使用 virtio device,並在 guest disk 上啟用 cache=none,然後測量你自己的 workload。