VPS에서 Proxmox 설치 및 중첩 가상화 가능 여부
VPS에서 Proxmox를 실행하려면 CPU의 vmx 또는 svm 플래그가 활성화되어야 합니다. kvm-ok 명령어로 지원 여부를 즉시 확인하고, 가상화 지원이 안 될 때 발생하는 오류를 해결하는 방법을 확인하십시오.
The short answer
Nested virtualization is a hypervisor running inside a virtual machine: your VPS is already a guest, and you want it to host guests of its own. It works only when your provider's hypervisor deliberately exposes the CPU's virtualization extensions to your instance — check /proc/cpuinfo for the vmx flag (Intel) or svm (AMD), and if neither appears, nothing you configure inside the VPS will fix it.
One expectation-setter first: Docker does not need any of this. Containers share your VPS kernel and never touch /dev/kvm. If the real goal is "run several services in containers on my server", you already have what you need. Nesting matters when you want a second kernel — a Proxmox lab, a Windows guest, Firecracker microVMs, an Android emulator, a Kubernetes testbed of real VMs, or CI runners that boot VM images.
실제 중첩되는 대상
세 가지 계층:
- L0 — 베어 메탈 위에서 실행되는 제공업체의 hypervisor입니다. 사용자는 이에 대한 접근 권한이 없습니다.
- L1 — 사용자의 VPS입니다. L0 입장에서 L1은 단순한 guest입니다.
- L2 — VPS 내부에서 실행하려는 VM입니다.
Hardware virtualization은 Intel의 경우 VT-x (vmx flag) 및 EPT, AMD의 경우 AMD-V / SVM (svm) 및 RVI/NPT를 사용합니다. Hypervisor는 이 instruction들을 사용하여 guest mode로 진입하고, CPU가 동시에 두 개의 page table을 탐색할 수 있도록 합니다.
두 기술 모두 재진입(re-entrant)을 목적으로 설계되지 않았으므로, nesting은 emulation됩니다. L1이 VMX instruction을 실행하면 L0로 trap이 발생하며, L0는 L1을 대신하여 L2를 위한 shadow structures를 유지합니다. KVM은 이를 잘 수행하지만, L0가 모든 exit 시점에 추가 작업을 수행해야 합니다. 이것이 제공업체가 이 기능을 선택적으로 제공해야 하는 이유입니다.
가속된 L2를 위해서는 다음 두 가지 조건이 모두 충족되어야 합니다:
- L0의 KVM module이
nested=1와 함께 로드되어야 합니다. - L0가 사용자의 VPS에 해당 flag를 포함하는 CPU model을 할당해야 합니다. libvirt에서는
<cpu mode='host-passthrough'/>, Proxmox에서는cpu: host, raw QEMU에서는-cpu host를 사용합니다. 일반적인 emulated model (qemu64,kvm64)은 nesting이 전역적으로 활성화되어 있어도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다음 파일은 자주 인용되지만 잘못 해석되는 경우가 많습니다.
cat /sys/module/kvm_intel/parameters/nested # Y or NVPS 내부의 이 설정은 사용자의 KVM 모듈 설정이며, L2 게스트가 3단계 중첩(nesting)을 수행할 수 있는지 여부를 결정합니다. 이 설정은 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를 제공하면 해당 flag를 가진 CPU 모델이 노출됩니다. 이 CPU 기능에 의존하는 guest는 해당 기능이 없는 CPU를 가진 머신으로 안전하게 migration될 수 없습니다. 고객을 migration하여 노드를 비우는 호스트는 nesting을 활성화하는 즉시 이 기능을 포기해야 합니다. - Attack surface. nested VMX/SVM 경로는 커널의 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 워크플로를 사용하면 SSH 연결이 끊겨도 virt-install 콘솔을 계속 연결할 수 있습니다. 만약 --os-variant debian13가 거부되면, 사용 중인 osinfo-db 버전이 출시 이전 버전인 것입니다. osinfo-query os을 실행하여 존재하는 이름을 선택하십시오. --cpu host-passthrough은 vmx을 L2로 전달하며, 이는 L2가 다시 가상화를 수행해야 하는 경우에만 필요합니다. virsh autostart guest1을 사용하여 guest를 부팅 가능하게 만드십시오.
디스크와 NIC의 virtio 버스는 단순한 장식이 아닙니다. 에뮬레이션된 IDE 및 e1000 장치는 virtio 큐보다 하이퍼바이저로의 trap을 훨씬 더 자주 발생시키며, 중첩 가상화 환경에서는 모든 trap에 대해 두 번의 비용이 발생합니다.
Networking: 튜토리얼에서 생략된 내용
VPS에는 하나의 public IP가 있으며, 알 수 없는 MAC address를 필터링하는 fabric 뒤에 위치합니다. 이로 인해 두 가지 결과가 발생합니다.
L2 guest를 public network에 bridging하는 방식은 대개 작동하지 않습니다. public NIC에 br0를 설정하고 guest에 고유 MAC을 할당하면, ARP 요청은 전송되지만 응답이 돌아오지 않습니다. provider의 switch가 할당되지 않은 MAC의 frame을 드롭하기 때문입니다. 이 현상이 발생한다면 bridge 디버깅을 중단하십시오. 이것은 시스템의 메커니즘입니다.
대신 NAT network를 사용하십시오. libvirt는 default인 virbr0, 192.168.122.0/24 및 dnsmasq lease를 제공하므로 외부 연결이 즉시 가능합니다. 외부에서 들어오는 연결의 경우, L1에서 TLS를 종료한 후 proxy를 통해 전달하십시오. 아래의 certificate 경로는 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;
}
}proxy_pass 내의 주소가 고정되도록 guest에 먼저 static lease(virsh net-edit default)를 부여하십시오.
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가 한 단계의 private hop 거리에 있게 됩니다. 방화벽 규칙은 sudo ufw allow 22,80,443/tcp만 허용하도록 최소화하십시오. ufw를 활성화한 직후 guest의 외부 연결이 끊긴다면, 일반적인 원인은 /etc/default/ufw의 DEFAULT_FORWARD_POLICY="DROP"입니다. 이를 ACCEPT으로 설정한 후 ufw를 reload하십시오.
VPS에서의 Proxmox
Proxmox VE 9은 내부적으로 Debian 13을 사용합니다. 따라서 Debian VPS에 pve-no-subscription repository와 proxmox-ve package를 추가하여 설치할 수 있습니다. Proxmox 공식 문서에서 repository 및 keyring 라인을 가져오십시오. 오래된 블로그 포스트에서 복사한 URL은 설치를 실패하게 만듭니다.
패키지 설치는 어렵지 않습니다. Proxmox는 vmbr0이 물리 NIC에 브리지(bridged)되어 있기를 기대합니다. 이는 앞서 언급한 MAC-filtering 문제로 이어집니다. VPS에서 작동하는 방식은 물리 포트가 연결되지 않은 NAT 또는 라우팅 방식의 vmbr0을 사용하는 것입니다. 게스트는 프라이빗 대역을 사용하며, 외부 공개 서비스는 호스트에서 DNAT 규칙 또는 리버스 프록시를 사용해야 합니다. 공개 서비스가 VM가 아닌 컨테이너인 경우, 하나의 Docker Compose 파일에서 여러 앱을 관리하는 Traefik을 사용하여 자동 인증서와 함께 동일한 라우팅 작업을 수행할 수 있습니다. 먼저 /etc/network/interfaces 스냅샷을 생성하십시오. 잘못된 브리지 설정은 콘솔 접속 권한이 없는 상태에서 서버 접속을 차단할 수 있습니다.
성능에 관한 솔직한 설명
Nested 방식은 Single-level 방식보다 느립니다. 원인은 특정 메커니즘에 있습니다. 비용이 발생하는 지점은 메모리 액세스가 아니라 Exit입니다. EPT/NPT가 활성화되어 있으면 L0는 L2를 위한 Shadow Page Table을 유지하며, 일반적인 메모리 읽기는 하드웨어 속도로 수행됩니다. 비용이 발생하는 작업은 Guest Mode를 벗어나는 모든 작업입니다. I/O, Timer Interrupts, MMIO, Inter-processor Interrupts 등이 이에 해당합니다. L2 Exit은 L0에서 처리되며, L1을 거쳐 다시 전달될 수 있기 때문입니다. RAM에 이미 로드된 데이터를 처리하는 CPU Bound 작업은 Native 성능과 유사합니다. 반면 Syscalls, Packet, Disk I/O가 주를 이루는 작업은 계층 구조로 인한 성능 저하가 체감됩니다.
따라서 모든 곳에 virtio 장치를 사용하십시오. 또한 qcow2 파일은 제공업체가 이미 가상화한 디스크에 저장됩니다. 이는 두 개의 Thin-provisioning 계층이 쌓인 구조입니다. 이로 인해 Guest Disk의 cache=none는 동일한 블록이 두 개의 Page Cache에 동시에 존재하는 상황을 방지합니다. 벤치마크 수치는 제공하지 않습니다. 본인의 인스턴스에서 직접 워크로드를 측정하십시오.
Failure modes, and the strings you will see
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used (kvm-ok 발생). 모듈이 로드되지 않았거나 flag가 노출되지 않은 상태입니다. 먼저 /proc/cpuinfo을 확인하십시오.
kvm: disabled by bios (dmesg 발생). Bare metal 환경이라면 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이 적용되지 않습니다.
kvm: Device or resource busy (QEMU 시작 시 발생). 다른 hypervisor module이 CPU를 점유하고 있습니다. lsmod을 실행하여 vboxdrv 또는 VMware module이 kvm_intel과 함께 있는지 확인하고, 불필요한 module을 unload하십시오.
/var/run/libvirt/libvirt-sock: No such file or directory (virsh 발생). daemon이 중지되었습니다: sudo systemctl enable --now libvirtd.
Proxmox: KVM virtualisation configured, but not available. 가속 기능을 지원하지 않는 host에서 guest의 KVM acceleration이 체크된 경우입니다. 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는 이를 일반 process와 동일하게 취급합니다. L2 RAM은 L1의 고정 할당량에서 사용되므로, host로부터 추가로 빌려올 수 없습니다.
Operating it: backups, upgrades, limits
Backups. 실행 중인 guest의 qcow2를 복사하면 이미지가 손상됩니다. virsh shutdown guest1를 사용하여 복사하거나, 외부 snapshot(virsh snapshot-create-as guest1 snap1 --disk-only --atomic)을 생성하십시오. snapshot을 생성하면 쓰기 작업이 overlay로 전환되며, 그동안 정적인 base 이미지를 복사할 수 있습니다. 복사가 끝나면 virsh blockcommit를 사용하여 다시 병합하십시오. 복사된 파일을 VPS 외부로 전송하십시오. 동일한 disk에 저장된 snapshot은 장애로부터 보호할 수 없습니다.
Upgrades. apt full-upgrade은 새로운 kvm_intel/kvm_amd 모듈을 설치하지만, 실행 중인 kernel은 재부팅 전까지 이전 모듈을 유지합니다. 이전 kernel을 설치된 상태로 유지하고, kernel이 변경될 때마다 kvm-ok을 다시 실행하십시오. vmx 없이 호스트가 부팅되면, 다시 정상 작동하기까지 단 한 번의 boot entry만 남게 됩니다.
Where this stops scaling. 공용 IP가 하나뿐이므로 모든 L2 서비스는 L1의 proxy 또는 DNAT rule을 통해 외부와 통신합니다. Live migration은 지원되지 않습니다. CPU contention이 발생하면 nested exit path에서 가장 먼저 성능 저하가 나타납니다. 여러 guest를 실행하는 hypervisor는 이미 RAM을 모두 사용한 상태입니다. nested VM은 고정된 할당량에 대해 overcommit를 수행할 수 없습니다. 실험 환경이 커질 경우, nested stack을 더 높이는 것은 해결책이 아닙니다. 대신 사용자가 L0 권한을 갖는 전용 장비를 사용하는 것이 정답입니다.
FAQ
VPS에서 Docker를 실행하려면 중첩 가상화(nested virtualization)가 필요한가요?
아니요. 컨테이너는 VPS의 커널을 공유하며 /dev/kvm를 열지 않습니다. 따라서 vmx 또는 svm 플래그가 없는 일반 인스턴스에서도 Docker와 Docker Compose가 정상적으로 작동합니다. 중첩 가상화는 Proxmox 실습 환경, Windows 게스트, Firecracker microVMs, Android 에뮬레이터 또는 VM 이미지를 부팅하는 CI 러너와 같이 두 번째 커널이 필요한 경우에만 필요합니다.
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 모듈을 설명합니다.
왜 대부분의 VPS 제공업체는 중첩 가상화를 비활성화하나요?
vmx을 노출한다는 것은 해당 플래그를 가진 CPU 모델을 게스트에게 전달함을 의미합니다. 해당 CPU 기능에 의존하는 게스트는 해당 기능이 없는 CPU를 가진 머신으로 라이브 마이그레이션될 수 없습니다. 고객을 이동시켜 노드를 비우는 방식의 제공업체는 이 기능을 포기합니다. 또한 중첩 VMX/SVM 코드 경로는 긴 CVE 이력을 가지고 있습니다. 일부 호스트는 요청 시 VM별로 이 기능을 활성화해주며, 다른 호스트는 중첩 가상화를 유료 기능으로 문서화합니다.
중첩된 VM의 공용 브리지(public bridge)에 네트워크가 없습니다. 무엇이 문제인가요?
제공업체의 스위치는 사용자에게 할당되지 않은 MAC 주소의 프레임을 차단합니다. 따라서 공용 NIC에 브리지된 L2 게스트는 ARP를 전송해도 응답을 받지 못합니다. br0 디버깅을 중단하십시오. libvirt의 NAT default 네트워크(virbr0, 192.168.122.0/24)를 사용하고, 게스트에 정적 할당(static lease)을 부여하십시오. 공용 서비스는 VPS 자체에서 리버스 프록시 또는 DNAT 규칙을 통해 게시하십시오.
중첩된 VM은 얼마나 더 느린가요?
성능 저하는 메모리 액세스가 아닌 VM exit에서 발생합니다. EPT/NPT가 활성화되어 있으면 L2 내부의 일반적인 읽기 및 쓰기는 하드웨어 속도로 실행됩니다. 반면 I/O, 타이머 인터럽트, MMIO 및 IPI는 L0에서 처리되며 L1을 통해 다시 전달될 수 있습니다. RAM에 있는 데이터를 처리하는 CPU 집약적 작업은 네이티브와 유사하게 보입니다. 그러나 syscall, 패킷 및 디스크 작업이 많은 워크로드는 모든 계층의 영향을 받습니다. 모든 곳에 virtio 장치를 사용하고 게스트 디스크에 cache=none를 적용한 후 실제 워크로드를 측정하십시오.