SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor

วิธีเช็ก VPS รองรับ Nested Virtualization เพื่อรัน Proxmox

ตรวจสอบว่า VPS ของคุณรองรับ Nested Virtualization หรือไม่ด้วยคำสั่ง kvm-ok พร้อมวิธีเช็ก flag vmx ใน cpuinfo เพื่อรัน Proxmox หรือ KVM ได้อย่างถูกต้องและแม่นยำ

คำตอบโดยสรุป

Nested virtualization คือการรัน hypervisor ซ้อนอยู่ภายในเครื่องเสมือน (virtual machine) อีกชั้นหนึ่ง กล่าวคือ VPS ของคุณเป็น guest อยู่แล้ว แต่คุณต้องการให้มันทำหน้าที่เป็น host เพื่อรัน guest ของตัวเองอีกที วิธีนี้จะใช้งานได้ก็ต่อเมื่อ hypervisor ของผู้ให้บริการตั้งใจเปิดเผยส่วนขยายการทำ virtualization ของ CPU ให้กับ instance ของคุณเท่านั้น ให้ตรวจสอบ /proc/cpuinfo ว่ามี flag vmx (สำหรับ Intel) หรือ svm (สำหรับ AMD) ปรากฏอยู่หรือไม่ หากไม่พบทั้งสองอย่าง การตั้งค่าใดๆ ภายใน VPS ก็จะไม่สามารถแก้ไขปัญหานี้ได้

ข้อควรทราบเบื้องต้น: Docker ไม่จำเป็นต้องใช้ฟีเจอร์นี้ คอนเทนเนอร์จะใช้ kernel ร่วมกับ VPS ของคุณและไม่เคยเรียกใช้งาน /dev/kvm หากเป้าหมายที่แท้จริงคือ "การรันหลายบริการในคอนเทนเนอร์บนเซิร์ฟเวอร์" คุณมีสิ่งที่จำเป็นครบถ้วนแล้ว การทำ nesting จะมีความสำคัญก็ต่อเมื่อคุณต้องการ kernel ชุดที่สอง, ห้องทดลอง Proxmox, Windows guest, Firecracker microVMs, Android emulator, Kubernetes testbed ที่เป็น VM จริงๆ หรือ CI runner ที่ต้องบูต VM image ขึ้นมาใช้งาน

การทำ Nested Virtualization คืออะไร

ประกอบด้วย 3 ชั้น:

  • L0, hypervisor ของผู้ให้บริการ ซึ่งทำงานบนฮาร์ดแวร์โดยตรง คุณไม่สามารถเข้าถึงชั้นนี้ได้
  • L1, VPS ของคุณ ซึ่งสำหรับ L0 แล้วถือเป็น guest ตัวหนึ่ง
  • L2, VM ที่คุณต้องการรันภายใน VPS ของคุณ

Hardware virtualization คือ VT-x (แฟล็ก vmx) ร่วมกับ EPT บน Intel หรือ AMD-V / SVM (svm) ร่วมกับ RVI/NPT บน AMD โดย hypervisor จะใช้คำสั่งเหล่านี้เพื่อเข้าสู่ guest mode และอนุญาตให้ CPU ประมวลผล page table สองชุดพร้อมกัน

เนื่องจากสถาปัตยกรรมเหล่านี้ไม่ได้ถูกออกแบบมาให้รองรับการทำงานซ้อนทับ (re-entrant) การทำ nesting จึงต้องใช้การจำลอง (emulation): เมื่อ L1 รันคำสั่ง VMX เช่น VMLAUNCH หรือ VMRESUME ระบบจะเกิด trap ไปยัง L0 ซึ่งจะทำหน้าที่จัดการโครงสร้าง shadow สำหรับ L2 แทน L1 ในกรณีของ CPU ที่รองรับ VMCS shadowing คำสั่ง VMREAD และ VMWRITE ของ L1 จะสามารถประมวลผลได้โดยไม่ต้องเกิด exit ซึ่งช่วยลดภาระงานส่วนใหญ่ลงได้ แต่ยังคงมีส่วนอื่นที่ต้องประมวลผลอยู่ KVM ทำงานในส่วนนี้ได้ดี แต่ L0 ยังคงต้องทำงานเพิ่มขึ้นในทุกครั้งที่เกิด exit นี่คือเหตุผลที่ผู้ให้บริการต้องเป็นผู้เปิดใช้งานฟีเจอร์นี้

เมื่อ L0 คือ KVM จะต้องมีเงื่อนไข 2 ประการเพื่อให้ L2 ทำงานแบบเร่งความเร็ว (accelerated) ได้:

  1. โมดูล KVM ของ L0 ต้องถูกโหลดด้วย nested=1
  2. L0 ต้องกำหนด CPU model ให้กับ VPS ของคุณที่รองรับแฟล็กดังกล่าว โดยตั้งค่าเป็น <cpu mode='host-passthrough'/> ใน libvirt, cpu: host ใน Proxmox หรือ -cpu host ใน QEMU แบบ raw ทั้งนี้ CPU model แบบจำลองทั่วไป (qemu64, kvm64) จะซ่อน vmx เอาไว้ แม้ว่าจะมีการเปิดใช้งาน nesting ในระดับ global แล้วก็ตาม

Hypervisor อื่นๆ จะมีวิธีการตั้งค่าเฉพาะของตนเอง เช่น Hyper-V จะจำลอง virtualization extensions สำหรับ nested hypervisor ภายใน VM ของตน แต่จะทำได้เฉพาะใน VM ที่มีการเปิดใช้งาน nesting ไว้เป็นรายกรณีเท่านั้น

ตรวจสอบ 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 หากพบแฟล็กดังกล่าวแต่ไม่พบ device node ให้โหลดโมดูลด้วยตนเองและตรวจสอบ 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 ของคุณ ซึ่งเป็นตัวกำหนดว่า guest ระดับ L2 จะสามารถทำ nesting ซ้อนลงไปเป็นระดับที่สามได้หรือไม่ ค่านี้ไม่ได้ระบุว่า L0 ได้เปิดใช้งาน nesting ให้คุณหรือไม่ โดย /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

ระบบจะไม่อนุญาตให้ถอด module ขณะที่ VM กำลังทำงานอยู่ ดังนั้นให้ shut down guest ก่อน หากเครื่องนั้นเป็น Proxmox host ให้ดู การเปิดใช้ nested virtualization ใน Proxmox VE 9 ซึ่งครอบคลุมการเปลี่ยนแปลงใน modprobe.d แบบเดียวกัน รวมถึงการตั้งค่า cpu: host ระดับ per-VM ที่ทำให้ flag นี้มองเห็นได้ภายใน guest

เหตุผลที่ผู้ให้บริการ VPS ส่วนใหญ่ปิดการใช้งานฟีเจอร์นี้

  • การย้ายเครื่องแบบ Live migration: การส่งมอบ vmx ให้คุณหมายถึงการเปิดเผย CPU model ที่มี flag ดังกล่าว ซึ่ง guest ที่ต้องพึ่งพาฟีเจอร์ของ CPU เหล่านั้นจะไม่สามารถย้ายไปยังเครื่องที่ไม่มีฟีเจอร์เดียวกันได้อย่างปลอดภัย ผู้ให้บริการที่ใช้วิธีระบายโหลดออกจากโหนดด้วยการย้ายลูกค้า จะสูญเสียความสามารถนี้ทันทีที่เปิดใช้งาน nesting
  • พื้นที่เสี่ยงต่อการโจมตี (Attack surface): เส้นทางการทำงานของ nested VMX/SVM ถือเป็นส่วนของโค้ดที่ซับซ้อนที่สุดในชั้น virtualization ของ kernel และมีประวัติการพบช่องโหว่ (CVE) อยู่บ่อยครั้ง
  • L0 อาจไม่ใช่ KVM: หาก systemd-detect-virt แสดงผลลัพธ์เป็น vmware, xen หรือ microsoft กฎการทำ nesting จะเป็นไปตาม stack นั้นๆ ไม่ใช่ของ KVM

หาก instance ของคุณไม่มี flag ดังกล่าว ให้ติดต่อฝ่ายสนับสนุน (บางแห่งเปิดให้เป็นราย VM), เลือกแผนบริการที่ระบุว่ารองรับ nesting หรือย้ายไปใช้ dedicated box เนื้อหาหลังจากนี้จะถือว่าคุณมีสิทธิ์ root บนเครื่องที่แสดง flag ดังกล่าวแล้ว

การรัน L2 guest ด้วย 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'

ไม่จำเป็นต้องใช้ graphical session การติดตั้งผ่าน serial จะใช้เวลาสักพัก ดังนั้นให้เริ่มการติดตั้งภายใน persistent shell: เวิร์กโฟลว์ tmux ที่ช่วยให้เซสชัน Claude Code ทำงานต่อเนื่องบน VPS จะช่วยรักษาการเชื่อมต่อ virt-install console ไว้ได้แม้การเชื่อมต่อ SSH จะหลุด หาก --os-variant debian13 ถูกปฏิเสธ แสดงว่า osinfo-db ของคุณเก่ากว่าเวอร์ชันที่รองรับ ให้รัน osinfo-query os แล้วเลือกชื่อที่มีอยู่จริง --cpu host-passthrough จะส่งผ่าน vmx ลงไปยัง L2 ซึ่งจำเป็นเฉพาะในกรณีที่ L2 ต้องทำ virtualization ซ้อนอีกชั้นเท่านั้น ทำให้ guest บูตได้อย่างปลอดภัยด้วย virsh autostart guest1

บัส virtio บนดิสก์และ NIC ไม่ใช่แค่การตกแต่ง: อุปกรณ์ IDE และ e1000 แบบจำลองจะดึงการทำงาน (trap) ไปยัง hypervisor บ่อยกว่าคิวของ virtio มาก และภายใต้การทำ nesting นั้น การ exit ที่ L0 ไม่สามารถจัดการได้ด้วยตัวเองจะถูกส่งต่อไปยัง L1 ซึ่งการจัดการในระดับนั้นอาจกระตุ้นให้เกิดการ exit เพิ่มเติมขึ้นมาอีก

ระบบเครือข่าย: ส่วนที่บทเรียนทั่วไปมักข้ามไป

VPS ของคุณมี public IP หนึ่งหมายเลขและอยู่หลังโครงสร้างเครือข่ายที่คัดกรอง MAC address ที่ไม่รู้จัก ซึ่งส่งผลตามมา 2 ประการ

การทำ Bridging ให้ guest ระดับ L2 เชื่อมต่อกับ public network มักจะใช้งานไม่ได้ หากคุณใส่ br0 บน public NIC และกำหนด MAC address ให้ guest เอง คุณจะพบว่า ARP request ถูกส่งออกไปแต่ไม่มีการตอบกลับ เนื่องจาก switch ของผู้ให้บริการจะทิ้งเฟรมที่มาจาก MAC address ที่ไม่ได้มีการเช่าใช้งาน หากคุณพบอาการนี้ ให้หยุดการแก้ไขปัญหาที่ bridge เพราะนี่คือกลไกการทำงานของระบบ

ให้ใช้ NAT network แทน libvirt มาพร้อมกับ default: virbr0, 192.168.122.0/24, และ dnsmasq สำหรับการแจกจ่าย IP ซึ่งช่วยให้การเชื่อมต่อขาออกใช้งานได้ทันที สำหรับการเชื่อมต่อขาเข้า ให้ทำ TLS termination ที่ L1 แล้วใช้ proxy ส่งต่อเข้ามา โดยเส้นทางของ certificate ที่ระบุไว้ด้านล่างมาจาก การออกใบรับรอง Let's Encrypt ด้วย Certbot บน 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;
    }
}

กำหนด static lease ให้ guest ก่อน (virsh net-edit default) เพื่อให้ที่อยู่ใน proxy_pass นั้นคงที่

อินเทอร์เฟซสำหรับจัดการระบบต้องไม่เปิดเผยบนอินเทอร์เน็ต: VNC บนพอร์ต 5900 และ Proxmox web UI บนพอร์ต 8006 ควรอยู่บน loopback เท่านั้น โดยเข้าถึงผ่าน SSH tunnel (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) หรือผ่าน การเชื่อมต่อ WireGuard VPN เข้าสู่ VPS ซึ่งจะทำให้ช่วง IP ของ guest 192.168.122.0/24 อยู่ห่างออกไปเพียงหนึ่ง private hop เท่านั้น ให้จำกัดการตั้งค่า firewall ให้แคบที่สุด โดยเปิดเฉพาะ sudo ufw allow 22,80,443/tcp เท่านั้น หาก guest สูญเสียการเชื่อมต่อขาออกทันทีหลังจากที่คุณเปิดใช้งาน ufw สาเหตุที่พบบ่อยคือ DEFAULT_FORWARD_POLICY="DROP" ในไฟล์ /etc/default/ufw ให้ตั้งค่าเป็น ACCEPT แล้วโหลด ufw ใหม่

การใช้งาน Proxmox บน VPS

Proxmox VE 9 มีพื้นฐานมาจาก Debian 13 ดังนั้นจึงสามารถติดตั้งบน Debian VPS ได้โดยการเพิ่ม repository pve-no-subscription และแพ็กเกจ proxmox-ve ให้คัดลอกบรรทัด repository และ keyring จากเอกสารประกอบฉบับปัจจุบันของ Proxmox โดยตรง เนื่องจาก URL ที่คัดลอกมาจากบล็อกเก่าอาจทำให้การติดตั้งล้มเหลว ควรพิจารณาให้ถี่ถ้วนก่อนว่าการเช่าฮาร์ดแวร์เพื่อรัน Proxmox นั้นคุ้มค่าหรือไม่ ก่อนที่จะเสียเวลาทั้งคืนไปกับการตั้งค่าเครือข่ายที่ซับซ้อน และ การเปรียบเทียบต้นทุนและความสามารถระหว่างการใช้ Proxmox ที่บ้านกับ VPS ที่เช่ามา เป็นบทสรุปของคำถามดังกล่าวที่ได้คำนวณเรื่องพลังงานและฮาร์ดแวร์ไว้ให้แล้ว

ส่วนของแพ็กเกจไม่ใช่เรื่องยาก Proxmox ต้องการ vmbr0 ที่ทำ bridge เข้ากับ physical NIC ซึ่งมักจะติดปัญหาเรื่อง MAC-filtering ที่กล่าวไปข้างต้น รูปแบบที่ใช้งานได้จริงบน VPS คือการใช้ vmbr0 แบบ NAT หรือ routed โดยไม่ต้องเชื่อมต่อกับพอร์ตจริง ให้ guest อยู่ในวงเครือข่ายส่วนตัว (private range) และใช้กฎ DNAT หรือ reverse proxy บน host สำหรับบริการที่ต้องการเปิดสู่สาธารณะ ในกรณีที่บริการที่เปิดสู่สาธารณะเป็น container แทนที่จะเป็น VM บทความเรื่อง Traefik สำหรับจัดการแอปพลิเคชันหลายตัวจากไฟล์ Docker Compose เดียว จะครอบคลุมงานด้านการกำหนดเส้นทาง (routing) แบบเดียวกันพร้อมการจัดการ certificate อัตโนมัติ ให้ทำ Snapshot /etc/network/interfaces ไว้ก่อนเสมอ เพราะการกำหนดค่า bridge ที่ผิดพลาดอาจทำให้คุณถูกตัดขาดจากเครื่องที่ไม่มีคอนโซลให้เข้าถึงได้

ประสิทธิภาพตามความเป็นจริง

การทำ Nested virtualization นั้นช้ากว่าระดับเดียว และกลไกที่ส่งผลกระทบนั้นมีความเฉพาะเจาะจง ไม่ใช่การลดทอนประสิทธิภาพโดยรวม: ต้นทุนจะเกิดขึ้นที่การ exit และการแปลที่อยู่หน่วยความจำ (address translation) ไม่ใช่ที่คำสั่งทั่วไป เมื่อมี EPT/NPT อยู่ L0 จะรวม page table ของ L1 สำหรับ L2 เข้ากับตารางของตนเองเป็น shadow table ชุดเดียว ทำให้เมื่อเกิด TLB hit การทำงานจะเร็วเท่าความเร็วฮาร์ดแวร์ แต่หากเกิด TLB miss จะมีต้นทุนสูงขึ้น เพราะฮาร์ดแวร์ต้องไล่ดู page table ของ guest และ shadow table ไปพร้อมกัน และทุกการเปลี่ยนแปลงที่ L1 ทำกับตารางของตนเองจะบังคับให้เกิด exit เพื่อให้ L0 ทำการ resync shadow table สิ่งที่ทำให้เกิดภาระงานสูงคือทุกการดำเนินการที่ออกจาก guest mode เช่น I/O, timer interrupts, MMIO, inter-processor interrupts เนื่องจาก L2 exit จะถูกจัดการโดย L0 และอาจต้องส่งสะท้อนกลับผ่าน L1 งานที่เน้น CPU และมี working set ขนาดเล็กจะมีความเร็วใกล้เคียงกับ native ส่วนงานที่มี working set ในหน่วยความจำขนาดใหญ่จะต้องรับภาระจาก TLB miss และงานใดก็ตามที่เน้น syscall, แพ็กเก็ตเครือข่าย และ disk I/O จะได้รับผลกระทบจากจำนวนเลเยอร์ที่เพิ่มขึ้น

ดังนั้น: ควรใช้ virtio devices ในทุกจุด และไฟล์ qcow2 ของคุณที่อยู่บนดิสก์ซึ่งผู้ให้บริการทำ virtualization ไว้แล้วนั้น คือการซ้อนทับของเลเยอร์ thin-provisioning สองชั้น ซึ่งการใช้ cache=none บน guest disk จะช่วยป้องกันไม่ให้บล็อกข้อมูลเดียวกันถูกเก็บไว้ใน page cache สองที่พร้อมกัน ทั้งนี้ไม่มีตัวเลข benchmark ในที่นี้: โปรดวัดผลจาก workload ของคุณบน instance ของคุณเอง

รูปแบบความล้มเหลวและข้อความที่คุณจะพบ

INFO: /dev/kvm does not exist / KVM acceleration can NOT be used จาก kvm-ok อาจเกิดจากโมดูลไม่ได้ถูกโหลด หรือไม่ได้เปิดใช้งาน flag ให้ตรวจสอบ /proc/cpuinfo เป็นอันดับแรก

kvm: disabled by bios ใน dmesg หากเป็นเครื่อง bare metal ให้สลับเปิด VT-x/SVM ใน firmware หากเป็น VPS หมายความว่า L0 ไม่ได้ส่งต่อส่วนขยาย (extensions) มาให้ ซึ่งการตั้งค่าใดๆ ใน guest ก็ไม่สามารถแก้ไขปัญหานี้ได้

modprobe: ERROR: could not insert 'kvm_intel': Operation not supported CPU ที่ kernel มองเห็นไม่มี vmx ซึ่งเป็นผลจากการตัดสินใจของ L0 เช่นกัน

Could not access KVM kernel module: Permission denied เป็นปัญหาเรื่องสิทธิ์ ไม่ใช่ฮาร์ดแวร์ ls -l /dev/kvm ควรแสดงกลุ่ม kvm และโหมด 660 ให้เพิ่มผู้ใช้ของคุณเข้ากลุ่มดังกล่าวแล้วเริ่ม login shell ใหม่ เนื่องจากสถานะการเป็นสมาชิกกลุ่มจะไม่มีผลกับ session ที่กำลังทำงานอยู่

kvm: Device or resource busy เมื่อ QEMU เริ่มทำงาน เกิดจากมี hypervisor โมดูลอื่นยึด CPU ไว้ ให้รัน lsmod แล้วมองหา vboxdrv หรือโมดูลของ VMware ที่ทำงานอยู่คู่กับ kvm_intel จากนั้นให้ 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. guest มีการเปิดใช้งาน KVM acceleration บน host ที่ไม่รองรับ ให้แก้ไขการทำ nesting หรือยกเลิกการเลือกตัวเลือกดังกล่าวแล้วยอมรับการทำงานแบบ emulation

Android emulator: x86_64 emulation currently requires hardware acceleration! เกิดจาก /dev/kvm เช่นเดิม ซึ่งมักเป็นปัญหาเรื่องกลุ่มผู้ใช้

ไม่มีข้อความผิดพลาดแต่ทำงานช้ามาก QEMU ที่ไม่มี flag ตัวเร่งความเร็วจะถอยกลับไปใช้ TCG ซึ่งเป็น software emulator แม้จะทำงานได้ถูกต้องแต่จะช้ามาก การบูตที่ปกติใช้เวลาไม่กี่วินาทีอาจกลายเป็นหลายนาที ให้ระบุ -accel kvm อย่างชัดเจน เพื่อให้ QEMU หยุดทำงานและแสดงข้อความผิดพลาดแทนที่จะทำงานแบบ emulation ไปเรื่อยๆ อย่างเงียบเชียบ

guest หายไปในระหว่างการทำงาน ให้ตรวจสอบ dmesg เพื่อหา Out of memory: Killed process ... qemu-system-x86_64 เนื่องจาก L2 guest เป็นเพียง process หนึ่งบน L1 ตัว OOM killer จึงจัดการกับมันเหมือน process อื่นๆ โดย RAM ของ L2 จะถูกดึงมาจากส่วนที่ L1 จัดสรรไว้เท่านั้น ไม่มีการยืมทรัพยากรจาก host โดยตรง

การใช้งาน: การสำรองข้อมูล การอัปเกรด และข้อจำกัด

การสำรองข้อมูล การคัดลอกไฟล์ qcow2 ของ guest ที่กำลังทำงานอยู่มีความเสี่ยงที่จะได้อิมเมจที่ไม่สมบูรณ์ เนื่องจาก guest ยังคงเขียนข้อมูลอยู่ตลอดเวลาในขณะที่คุณอ่านไฟล์ ให้เลือกใช้วิธีรัน virsh shutdown guest1 แล้วรอจนกว่า virsh domstate guest1 จะรายงานสถานะ shut off (คำสั่ง shutdown อาจส่งค่ากลับก่อนที่ guest จะหยุดทำงานจริง) แล้วจึงค่อยคัดลอก หรือใช้วิธีทำ external snapshot (virsh snapshot-create-as guest1 snap1 --disk-only --atomic) เพื่อให้การเขียนข้อมูลเปลี่ยนไปลงที่ไฟล์ overlay แทน ในขณะที่คุณคัดลอกไฟล์ base ที่หยุดนิ่งแล้ว จากนั้นจึงรวมไฟล์กลับด้วย virsh blockcommit guest1 vda --active --pivot ทั้งนี้ต้องย้ายไฟล์สำรองออกจาก VPS เสมอ เพราะการเก็บ snapshot ไว้บนดิสก์ลูกเดิมไม่สามารถป้องกันความเสียหายใดๆ ได้

การอัปเกรด apt full-upgrade จะติดตั้งโมดูล kvm_intel/kvm_amd ใหม่ แต่ kernel ที่กำลังทำงานอยู่จะยังคงใช้โมดูลเดิมจนกว่าคุณจะรีบูตเครื่อง ให้คง kernel เวอร์ชันก่อนหน้าไว้และรัน kvm-ok ใหม่ทุกครั้งหลังมีการเปลี่ยนแปลง kernel หากโฮสต์บูตขึ้นมาโดยไม่มี vmx คุณจะสามารถกู้คืนระบบได้ทันทีเพียงแค่เลือกบูตจากรายการเดิม

จุดที่ระบบนี้ขยายต่อไม่ได้ การมี public IP เพียงหนึ่งหมายความว่าบริการ L2 ทุกตัวต้องเข้าถึงโลกภายนอกผ่าน proxy หรือกฎ DNAT บน L1 เท่านั้น การทำ live migration จึงไม่สามารถทำได้ ภายใต้สภาวะที่มีการแย่งชิงทรัพยากร CPU เส้นทาง nested exit จะเป็นส่วนแรกที่ได้รับผลกระทบ และ hypervisor ที่มี guest หลายตัวคือเครื่องที่ถูกจัดสรร RAM ไปจนหมดแล้ว VM แบบซ้อนทับไม่สามารถทำ overcommit เพื่อเพิ่มทรัพยากรเกินกว่าที่กำหนดไว้ได้ เมื่อห้องปฏิบัติการของคุณเติบโตจนเกินขีดจำกัดนี้ คำตอบไม่ใช่การเพิ่มความซับซ้อนของ stack ที่ซ้อนทับกัน แต่คือการย้ายไปใช้เครื่องเซิร์ฟเวอร์แยกต่างหากที่คุณเป็น L0 ซึ่งข้อจำกัดเหล่านี้จะไม่มีผลอีกต่อไป

FAQ

ฉันจำเป็นต้องใช้ nested virtualization เพื่อรัน Docker บน VPS หรือไม่?

ไม่จำเป็น คอนเทนเนอร์ใช้ kernel ร่วมกับ VPS ของคุณและไม่เคยเปิดใช้งาน /dev/kvm ดังนั้น instance ปกติที่ไม่มี flag vmx หรือ svm จึงสามารถรัน Docker และ Docker Compose ได้ตามปกติ การทำ nesting จะสำคัญก็ต่อเมื่อคุณต้องการ kernel ชุดที่สอง เช่น การทำ Proxmox lab, การรัน Windows guest, Firecracker microVMs, Android emulator หรือ CI runners ที่ต้องบูต VM image

ฉันจะตรวจสอบได้อย่างไรว่า VPS ของฉันรองรับ nested virtualization?

ให้รันคำสั่ง grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u แล้วตามด้วย kvm-ok จากแพ็กเกจ cpu-checker หาก instance ใช้งานได้จะแสดงผลเป็น vmx (สำหรับ Intel) หรือ svm (สำหรับ AMD) โดย kvm-ok จะรายงานค่า KVM acceleration can be used และต้องมีไฟล์ /dev/kvm อยู่ในกลุ่ม kvm ด้วยโหมด 660 สำหรับคำถามนี้ให้ละเว้น /sys/module/kvm_intel/parameters/nested ไปได้เลย เพราะไฟล์นั้นอธิบายถึง KVM module ของตัวคุณเอง ไม่ใช่สิ่งที่ hypervisor ของผู้ให้บริการเปิดเผยให้คุณเห็น

ทำไมผู้ให้บริการ VPS ส่วนใหญ่ถึงปิดใช้งาน nested virtualization?

การเปิดเผย vmx หมายถึงการส่งมอบ CPU model ที่มี flag ดังกล่าวให้กับ guest ซึ่งหาก guest นั้นต้องพึ่งพาฟีเจอร์ของ CPU เหล่านั้น จะไม่สามารถทำ live-migration ไปยังเครื่องที่ไม่มี CPU ดังกล่าวได้ ผู้ให้บริการที่ต้องย้ายลูกค้าไปมาระหว่างโหนดเพื่อจัดการโหลดจึงไม่สามารถทำเช่นนั้นได้ นอกจากนี้ code path ของ nested VMX/SVM ยังมีประวัติช่องโหว่ CVE มาอย่างยาวนาน ผู้ให้บริการบางรายอาจเปิดใช้งานให้เป็นรายกรณีเมื่อมีการร้องขอ หรือระบุไว้เป็นฟีเจอร์ในบางแพ็กเกจ

ทำไม nested VM ของฉันถึงไม่มีเครือข่ายบน public bridge?

สวิตช์ของผู้ให้บริการจะทิ้งเฟรมที่มาจาก MAC address ซึ่งไม่ได้ถูกกำหนดให้คุณ ดังนั้น guest ที่เป็น L2 ซึ่งเชื่อมต่ออยู่บน public NIC จะส่ง ARP ออกไปแต่ไม่ได้รับการตอบกลับ ให้หยุดแก้ไขปัญหาที่ br0 แล้วหันไปใช้เครือข่าย NAT default ของ libvirt (virbr0, 192.168.122.0/24) แทน โดยกำหนด static lease ให้กับ guest และเผยแพร่บริการสู่สาธารณะผ่าน reverse proxy หรือกฎ DNAT บนตัว VPS เอง

nested VM ทำงานช้าลงแค่ไหน?

ภาระงานจะเกิดขึ้นที่ VM exits และการแปลที่อยู่หน่วยความจำ (address translation) เมื่อเปิดใช้งาน EPT/NPT คำสั่งและการเข้าถึง TLB ภายใน L2 จะทำงานด้วยความเร็วระดับฮาร์ดแวร์ แต่หากเกิด TLB miss ระบบจะต้องไล่ดู page table เพิ่มเติม รวมถึงงานด้าน I/O, timer interrupts, MMIO และ IPI จะถูกจัดการโดย L0 และอาจต้องส่งกลับผ่าน L1 งานที่เน้น CPU และมี working set ขนาดเล็กจะทำงานได้ใกล้เคียงกับ native แต่สำหรับงานที่มี working set ในหน่วยความจำขนาดใหญ่ หรือภาระงานที่เน้น syscall, packet และ disk จะได้รับผลกระทบจากทุกเลเยอร์ ให้ใช้ virtio devices ในทุกส่วนและใช้ cache=none บน disk ของ guest จากนั้นจึงวัดผลจากภาระงานจริงของคุณเอง