Wirtualizacja zagnieżdżona na VPS: jak sprawdzić Proxmox?
Większość dostawców VPS blokuje flagę vmx. Sprawdź dostępność wirtualizacji komendą kvm-ok w minutę. Poznaj błędy, które wystąpią przy braku wsparcia dla uruchomienia KVM.
Krótka odpowiedź
Wirtualizacja zagnieżdżona to hiperwizor działający wewnątrz maszyny wirtualnej: Twój VPS jest już gościem, a Ty chcesz, aby hostował własne instancje. Rozwiązanie to działa tylko wtedy, gdy hiperwizor dostawcy celowo udostępnia rozszerzenia wirtualizacji procesora dla Twojej instancji. Sprawdź /proc/cpuinfo pod kątem flagi vmx (Intel) lub svm (AMD). Jeśli żadna z nich się nie pojawia, żadna konfiguracja wewnątrz VPS nie rozwiąże problemu.
Najpierw wyjaśnienie oczekiwań: Docker nie potrzebuje żadnego z tych rozwiązań. Kontenery współdzielą jądro systemu Twojego VPS i nigdy nie korzystają z /dev/kvm. Jeśli rzeczywistym celem jest „uruchomienie kilku usług w kontenerach na serwerze”, masz już wszystko, czego potrzebujesz. Zagnieżdżanie jest istotne, gdy potrzebujesz drugiego jądra, laboratorium Proxmox, gościa Windows, mikro-VM Firecracker, emulatora Androida, środowiska testowego Kubernetes opartego na rzeczywistych maszynach wirtualnych lub runnerów CI, które uruchamiają obrazy VM.
Czym w rzeczywistości jest zagnieżdżanie
Trzy warstwy:
- L0, hiperwizor dostawcy, działający na fizycznym sprzęcie. Brak dostępu do tej warstwy.
- L1, Twój VPS. Dla L0 jest to jedynie gość.
- L2, maszyna wirtualna uruchamiana wewnątrz VPS.
Wirtualizacja sprzętowa to VT-x (flaga vmx) oraz EPT w architekturze Intel, lub AMD-V / SVM (svm) oraz RVI/NPT w architekturze AMD. Hiperwizor wykorzystuje te instrukcje, aby przejść w tryb gościa i umożliwić procesorowi jednoczesną obsługę dwóch tablic stron.
Żadne z tych rozwiązań nie zostało zaprojektowane jako reentrant, dlatego zagnieżdżanie jest emulowane: gdy L1 wykonuje instrukcję VMX, następuje przechwycenie do L0, który w imieniu L1 utrzymuje struktury cieniowe dla L2. KVM realizuje to poprawnie, jednak L0 wykonuje dodatkową pracę przy każdym wyjściu, dlatego dostawca musi wyrazić zgodę na taką konfigurację.
Aby uzyskać akcelerację dla L2, muszą zostać spełnione dwa warunki:
- Moduł KVM w L0 musi zostać załadowany z parametrem
nested=1. - L0 musi udostępnić dla VPS model procesora, który przenosi tę flagę:
<cpu mode='host-passthrough'/>w libvirt,cpu: hostw Proxmox,-cpu hostw surowym QEMU. Generyczny model emulowany (qemu64,kvm64) ukrywavmx, nawet jeśli zagnieżdżanie jest włączone globalnie.
Sprawdź swój VPS w jedną minutę
# 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/kvmUżyteczna instancja wyświetla vmx lub svm, kvm-ok zwraca KVM acceleration can be used, a /dev/kvm istnieje jako root:kvm w trybie 660. Jeśli flaga jest obecna, ale węzeł urządzenia nie, załaduj moduł ręcznie i odczytaj dziennik jądra:
sudo modprobe kvm_intel # or kvm_amd
sudo dmesg | tail -n 20Jeden plik jest stale cytowany i powszechnie błędnie interpretowany:
cat /sys/module/kvm_intel/parameters/nested # Y or NWewnątrz Twojego VPS jest to ustawienie Twojego modułu KVM i określa ono, czy gość L2 może zagnieździć trzeci poziom. Nie mówi ono nic o tym, czy L0 włączyło zagnieżdżanie dla Ciebie; /proc/cpuinfo oraz kvm-ok odpowiadają na to pytanie. Parametr nested to przełącznik, który ustawiasz na maszynie, której jesteś pełnym właścicielem:
echo 'options kvm_intel nested=1' | sudo tee /etc/modprobe.d/kvm-nested.conf
sudo modprobe -r kvm_intel && sudo modprobe kvm_intelUsuwanie modułu jest odrzucane, gdy uruchomiona jest maszyna wirtualna, dlatego najpierw wyłącz gości.
Dlaczego większość dostawców VPS wyłącza tę funkcję
- Migracja na żywo. Udostępnienie
vmxoznacza ekspozycję modelu procesora posiadającego tę flagę. Gość zależny od tych funkcji procesora nie może zostać bezpiecznie przeniesiony na maszynę, której procesor ich nie posiada. Host, który opróżnia węzły poprzez migrację klientów, traci tę możliwość w momencie włączenia zagnieżdżonej wirtualizacji. - Powierzchnia ataku. Ścieżki zagnieżdżonego VMX/SVM należą do najbardziej złożonych fragmentów kodu w warstwie wirtualizacji jądra i posiadają odpowiednią historię podatności CVE.
- L0 może nie być KVM. Jeśli
systemd-detect-virtzwracavmware,xenlubmicrosoft, zasady zagnieżdżania są narzucane przez ten stos, a nie przez KVM.
Brak flagi na instancji? Należy skontaktować się z pomocą techniczną (niektórzy dostawcy włączają ją dla poszczególnych maszyn wirtualnych), wybrać plan z udokumentowaną obsługą zagnieżdżania lub przenieść się na serwer dedykowany. Dalsza część poradnika zakłada posiadanie uprawnień root na maszynie, na której flaga jest widoczna.
Uruchamianie gościa L2 przy użyciu libvirt
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'Sesja graficzna nie jest wymagana. Instalacja przez port szeregowy trwa pewien czas, dlatego należy ją uruchomić wewnątrz trwałej powłoki: ten sam przepływ pracy w tmux, który utrzymuje sesje Claude Code na VPS pozwala zachować połączenie z konsolą virt-install nawet po zerwaniu sesji SSH. Jeśli --os-variant debian13 zostanie odrzucone, oznacza to, że osinfo-db jest starsze niż wydanie; należy uruchomić osinfo-query os i wybrać istniejącą nazwę. --cpu host-passthrough przekazuje vmx do wnętrza L2, co jest wymagane tylko wtedy, gdy L2 musi z kolei pełnić rolę wirtualizatora. Należy zabezpieczyć rozruch gościa za pomocą virsh autostart guest1.
Magistrala virtio dla dysku i karty sieciowej nie jest zbędnym dodatkiem: emulowane urządzenia IDE oraz e1000 wywołują pułapki (traps) w hypervisorze znacznie częściej niż kolejki virtio, a w przypadku zagnieżdżonej wirtualizacji każda pułapka jest obsługiwana dwukrotnie.
Sieć: element pomijany w poradnikach
Twój VPS posiada jeden publiczny adres IP i znajduje się za infrastrukturą filtrującą nieznane adresy MAC. Wynikają z tego dwie konsekwencje.
Mostkowanie gości L2 do sieci publicznej zazwyczaj nie działa. Umieszczenie br0 na publicznej karcie sieciowej i nadanie gościowi własnego adresu MAC spowoduje wysłanie zapytań ARP, na które nie otrzymasz odpowiedzi; przełącznik dostawcy odrzuca ramki pochodzące z adresu MAC, którego nie przydzielił. Jeśli to jest Twój objaw, przerwij debugowanie mostka; tak działa ten mechanizm.
Zastosuj sieć NAT. libvirt dostarcza default: virbr0, 192.168.122.0/24, dzierżawy dnsmasq, ruch wychodzący działa natychmiast. W przypadku ruchu przychodzącego należy zakończyć TLS na L1 i przekierować go przez proxy; ścieżki certyfikatów poniżej pochodzą z wydawania certyfikatu Let's Encrypt za pomocą Certbot na Nginx:
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;
}
}Najpierw nadaj gościowi statyczną dzierżawę (virsh net-edit default), aby adres w pliku proxy_pass pozostał niezmienny.
Interfejsy zarządzania powinny pozostać niedostępne z Internetu: VNC na porcie 5900 oraz interfejs webowy Proxmox na porcie 8006 powinny działać na interfejsie loopback, osiągalne przez tunel SSH (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) lub poprzez własny serwer WireGuard VPN na VPS, co sprawia, że cała podsieć gości 192.168.122.0/24 znajduje się w zasięgu jednego przeskoku prywatnego. Utrzymuj zaporę sieciową w restrykcyjnej konfiguracji, sudo ufw allow 22,80,443/tcp, nic więcej. Jeśli goście tracą łączność wychodzącą zaraz po włączeniu ufw, typową przyczyną jest DEFAULT_FORWARD_POLICY="DROP" w pliku /etc/default/ufw; ustaw tę wartość na ACCEPT i przeładuj ufw.
Proxmox na VPS
Proxmox VE 9 opiera się na systemie Debian 13, dlatego instalację na VPS z systemem Debian przeprowadza się poprzez dodanie repozytorium pve-no-subscription oraz pakietu proxmox-ve. Należy pobrać linie dotyczące repozytorium oraz klucza z aktualnej dokumentacji Proxmox; adres URL skopiowany ze starego wpisu na blogu spowoduje błąd instalacji. Kwestię zasadności instalacji Proxmox na wynajętym sprzęcie warto rozważyć przed poświęceniem wieczoru na konfigurację sieci, a porównanie kosztów i możliwości serwera Proxmox w domu oraz wynajętego VPS zawiera zestawienie, w którym obliczenia dotyczące zasilania i sprzętu zostały już wykonane.
Instalacja pakietów nie stanowi głównego wyzwania. Proxmox wymaga interfejsu vmbr0 zmostkowanego z fizyczną kartą sieciową, co prowadzi bezpośrednio do problemów z filtrowaniem adresów MAC opisanych powyżej. Rozwiązaniem działającym na VPS jest zastosowanie interfejsu vmbr0 typu NAT lub routowanego, bez przypisanej karty fizycznej, z maszynami wirtualnymi w prywatnej podsieci oraz regułami DNAT lub reverse proxy na hoście dla usług publicznych. W przypadkach, gdy usługi wystawione na zewnątrz są kontenerami, a nie maszynami wirtualnymi, Traefik obsługujący wiele aplikacji z jednego pliku Docker Compose realizuje to samo zadanie routingu z automatyczną obsługą certyfikatów. Przed przystąpieniem do prac należy wykonać snapshot /etc/network/interfaces: błędna definicja mostka może spowodować utratę dostępu do maszyny, do której konsoli użytkownik może nie mieć wglądu.
Wydajność w ujęciu rzeczywistym
Wirtualizacja zagnieżdżona jest wolniejsza niż jednostopniowa, a mechanizm tego zjawiska jest konkretny, a nie rozproszony: koszt nie wynika z dostępu do pamięci, lecz z operacji wyjścia (exits). Dzięki obecności EPT/NPT, L0 utrzymuje cieniowe tablice stron (shadow page tables) dla L2, a standardowe odczyty z pamięci odbywają się z prędkością sprzętową. Kosztowne stają się operacje wymagające opuszczenia trybu gościa (guest mode), takie jak I/O, przerwania zegarowe, MMIO czy przerwania międzyprocesorowe, ponieważ wyjście z L2 jest obsługiwane przez L0 i może być przekazywane z powrotem przez L1. Praca obciążająca CPU, operująca na danych już znajdujących się w RAM, przebiega z wydajnością zbliżoną do natywnej; wszystko, w czym dominują syscalls, pakiety sieciowe oraz I/O dyskowe, odczuwa wpływ warstw wirtualizacji.
Zalecenie: stosuj urządzenia virtio wszędzie, gdzie to możliwe. Plik qcow2 znajduje się na dysku, który dostawca już zwirtualizował, co oznacza nałożenie na siebie dwóch warstw thin-provisioning, gdzie cache=none na dysku gościa zapobiega przechowywaniu tych samych bloków danych jednocześnie w dwóch pamięciach podręcznych stron (page caches). W tym miejscu nie podajemy wyników benchmarków: zmierz wydajność własnego obciążenia na własnej instancji.
Tryby awarii i komunikaty błędów
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used z kvm-ok. Moduł nie jest załadowany lub flaga nie jest udostępniona. W pierwszej kolejności sprawdź /proc/cpuinfo.
kvm: disabled by bios w dmesg. Na serwerze fizycznym należy przełączyć opcję VT-x/SVM w oprogramowaniu układowym (firmware). Wewnątrz VPS oznacza to, że L0 nie przekazuje rozszerzeń i żadna konfiguracja wewnątrz systemu gościa tego nie zmieni.
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported. Procesor widziany przez jądro nie posiada vmx, co również wynika z decyzji podjętej na poziomie L0.
Could not access KVM kernel module: Permission denied. Problem z uprawnieniami, nie ze sprzętem. ls -l /dev/kvm powinno wskazywać grupę kvm oraz tryb 660; dodaj użytkownika do tej grupy i uruchom nową powłokę logowania, ponieważ przynależność do grupy nie aktualizuje się dla już uruchomionej sesji.
kvm: Device or resource busy podczas uruchamiania QEMU. Inny moduł hiperwizora zajmuje procesor: uruchom lsmod, wyszukaj vboxdrv lub moduły VMware obok kvm_intel i wyładuj ten, który nie jest wymagany.
/var/run/libvirt/libvirt-sock: No such file or directory z virsh. Demon nie działa: sudo systemctl enable --now libvirtd.
Proxmox: KVM virtualisation configured, but not available. Gość ma włączoną akcelerację KVM na hoście, który jej nie zapewnia. Napraw zagnieżdżanie (nesting) lub wyłącz tę opcję i zaakceptuj emulację programową.
Emulator Android: x86_64 emulation currently requires hardware acceleration! Ponownie /dev/kvm, zazwyczaj problem z uprawnieniami grupy.
Brak błędów, ale wydajność jest bardzo niska. QEMU bez flagi akceleratora przełącza się na TCG, czyli emulację programową. Działa poprawnie, ale wolno; czas rozruchu liczony w sekundach zmienia się w minuty. Przekaż jawnie -accel kvm, aby QEMU zakończyło działanie z błędem zamiast cichej emulacji.
Gość znika w trakcie pracy. Sprawdź dmesg pod kątem Out of memory: Killed process ... qemu-system-x86_64. Gość L2 jest procesem na poziomie L1, więc mechanizm OOM killer traktuje go jak każdy inny proces. Pamięć RAM dla L2 pochodzi ze sztywnej alokacji L1, bez możliwości pobierania zasobów z hosta.
Obsługa: kopie zapasowe, aktualizacje, limity
Kopie zapasowe. Kopiowanie pliku qcow2 działającego gościa skutkuje uszkodzonym obrazem. Należy albo virsh shutdown guest1 i wykonać kopię, albo utworzyć zewnętrzny snapshot (virsh snapshot-create-as guest1 snap1 --disk-only --atomic), dzięki czemu operacje zapisu zostaną przekierowane do pliku nakładki (overlay), podczas gdy kopiowana jest statyczna baza, a następnie scalić go za pomocą virsh blockcommit. Kopie należy przesyłać poza VPS; snapshot na tym samym dysku nie zapewnia żadnej ochrony.
Aktualizacje. apt full-upgrade instaluje nowe moduły kvm_intel/kvm_amd, jednak działające jądro korzysta ze starych do momentu restartu. Należy zachować poprzednią wersję jądra i ponownie uruchamiać kvm-ok po każdej zmianie jądra: host, który uruchomi się bez vmx, będzie wymagał jedynie wyboru odpowiedniego wpisu w bootloaderze, aby przywrócić sprawność.
Granice skalowalności. Jeden publiczny adres IP oznacza, że każda usługa L2 dociera do świata przez proxy lub regułę DNAT na poziomie L1. Migracja na żywo (live migration) nie jest dostępna. W przypadku rywalizacji o zasoby CPU, ścieżka wyjścia z wirtualizacji (nested exit) odczuwa to jako pierwsza. Hypervisor z kilkoma gośćmi to maszyna, której pamięć RAM została już przydzielona; zagnieżdżone maszyny wirtualne nie mogą nadmiarowo przydzielać pamięci (overcommit) ponad ustalony limit. Gdy laboratorium wyrośnie z tych ograniczeń, rozwiązaniem nie jest rozbudowa zagnieżdżonego stosu, lecz dedykowana maszyna, na której użytkownik znajduje się na poziomie L0 i powyższe ograniczenia nie mają zastosowania.
FAQ
Czy do uruchomienia Docker na VPS wymagana jest wirtualizacja zagnieżdżona?
Nie. Kontenery współdzielą jądro systemu operacyjnego VPS i nigdy nie otwierają /dev/kvm, więc standardowa instancja bez flagi vmx lub svm poprawnie obsługuje Docker oraz Docker Compose. Wirtualizacja zagnieżdżona jest wymagana tylko w przypadku uruchamiania drugiego jądra: laboratorium Proxmox, gościa Windows, mikro-maszyn Firecracker, emulatora Androida lub runnerów CI, które uruchamiają obrazy VM.
Jak sprawdzić, czy VPS obsługuje wirtualizację zagnieżdżoną?
Uruchom grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u, a następnie kvm-ok z pakietu cpu-checker. Poprawnie skonfigurowana instancja wyświetla vmx (Intel) lub svm (AMD), kvm-ok raportuje KVM acceleration can be used, a /dev/kvm istnieje z grupą kvm i uprawnieniami 660. W kontekście tego pytania należy zignorować /sys/module/kvm_intel/parameters/nested, ponieważ plik ten opisuje lokalny moduł KVM, a nie funkcje udostępnione przez hypervisor dostawcy.
Dlaczego większość dostawców VPS wyłącza wirtualizację zagnieżdżoną?
Udostępnienie vmx oznacza przekazanie gościowi modelu procesora z tą flagą. Gość zależny od tych funkcji procesora nie może zostać poddany migracji na żywo (live migration) na maszynę, której procesor ich nie posiada. Dostawcy przenoszący klientów między węzłami rezygnują z tej funkcji. Ścieżki kodu VMX/SVM dla wirtualizacji zagnieżdżonej mają również długą historię podatności CVE. Niektórzy dostawcy włączają tę funkcję na żądanie, a inni oferują ją w ramach wybranych planów.
Moja zagnieżdżona maszyna wirtualna nie ma sieci na publicznym moście. Co jest przyczyną?
Przełącznik dostawcy odrzuca ramki z adresu MAC, który nie został przydzielony, dlatego gość L2 zmostkowany do publicznej karty sieciowej wysyła ARP i nie otrzymuje odpowiedzi. Należy zaprzestać debugowania br0, użyć sieci NAT default w libvirt (virbr0, 192.168.122.0/24), nadać gościowi statyczną dzierżawę i publikować usługi przez reverse proxy lub regułę DNAT na samym VPS.
O ile wolniejsza jest zagnieżdżona maszyna wirtualna?
Koszt wydajnościowy dotyczy wyjść z maszyny wirtualnej (VM exits), a nie dostępu do pamięci. Przy aktywnym EPT/NPT, standardowe operacje odczytu i zapisu wewnątrz L2 działają z prędkością sprzętową, podczas gdy operacje I/O, przerwania zegara, MMIO oraz IPI są obsługiwane przez L0 i mogą być przekazywane przez L1. Praca obciążająca procesor na danych znajdujących się w pamięci RAM jest zbliżona do natywnej; obciążenia intensywnie korzystające z wywołań systemowych, pakietów i dysku odczuwają każdą warstwę. Należy używać urządzeń virtio oraz cache=none dla dysków gościa, a następnie przeprowadzić pomiary dla własnego obciążenia.