האם אפשר להריץ Proxmox על VPS? מדריך וירטואליזציה מקוננת
רוב ספקי ה-VPS מסתירים את דגל vmx. בדקו אם השרת שלכם תומך בווירטואליזציה מקוננת בעזרת הפקודה kvm-ok. למדו לזהות את הודעות השגיאה הנפוצות לפני התקנת Proxmox או KVM בתוך סביבת ענן.
תשובה קצרה
וירטואליזציה מקוננת (Nested virtualization) היא מצב שבו hypervisor רץ בתוך מכונה וירטואלית: ה-VPS שלכם הוא כבר אורח, ואתם מעוניינים שהוא יארח אורחים משלו. זה עובד רק כאשר ה-hypervisor של ספק הענן חושף במכוון את הרחבות הווירטואליזציה של ה-CPU למופע שלכם. בדקו את /proc/cpuinfo עבור הדגל vmx (עבור Intel) או svm (עבור AMD); אם אף אחד מהם לא מופיע, שום הגדרה שתבצעו בתוך ה-VPS לא תפתור זאת.
הבהרה מקדימה: Docker אינו זקוק לכל זה. מכולות (containers) משתפות את ה-kernel של ה-VPS שלכם ולעולם אינן ניגשות ל-/dev/kvm. אם המטרה האמיתית היא "להריץ כמה שירותים במכולות על השרת שלי", כבר יש לכם את כל מה שדרוש. וירטואליזציה מקוננת רלוונטית כאשר אתם זקוקים ל-kernel שני, מעבדת Proxmox, אורח Windows, מיקרו-מכונות Firecracker, אמולטור Android, סביבת בדיקות Kubernetes המבוססת על מכונות וירטואליות אמיתיות, או CI runners שמבצעים boot לתמונות של מכונות וירטואליות.
מהו הקינון (nesting) בפועל
קיימות שלוש שכבות:
- L0, ה-hypervisor של ספק התשתית, שרץ על החומרה הפיזית. אין לך גישה אליו.
- L1, ה-VPS שלך. עבור L0, זהו בסך הכל אורח (guest).
- L2, ה-VM שברצונך להריץ בתוך ה-VPS שלך.
וירטואליזציה של חומרה היא VT-x (הדגל vmx) בתוספת EPT במעבדי Intel, או AMD-V / SVM (svm) בתוספת RVI/NPT במעבדי AMD. ה-hypervisor משתמש בהוראות אלו כדי להיכנס למצב אורח (guest mode) וכדי לאפשר למעבד לעבור על שני טבלאות דפים (page tables) בו-זמנית.
אף אחת מהטכנולוגיות לא תוכננה להיות רה-אנטרנטית (re-entrant), לכן הקינון מבוצע באמצעות אמולציה: כאשר L1 מריץ הוראת VMX כגון VMLAUNCH או VMRESUME, מתבצע trap ל-L0, אשר מתחזק את מבני ה-shadow עבור L2 בשם L1. במעבדים עם VMCS shadowing, ניתן לבצע את הפקודות VMREAD ו-VMWRITE של L1 ללא יציאה (exit), מה שמפחית משמעותית את התעבורה הזו, אך לא את השאר. KVM מבצע זאת היטב, אך L0 נדרש לבצע עבודה נוספת בכל יציאה, וזו הסיבה שהספק חייב לאשר זאת מראש.
כאשר L0 הוא KVM, שני תנאים חייבים להתקיים כדי ש-L2 ירוץ בהאצה:
- מודול ה-KVM של L0 נטען עם
nested=1. - L0 מספק ל-VPS שלך מודל מעבד הכולל את הדגל,
<cpu mode='host-passthrough'/>ב-libvirt,cpu: hostב-Proxmox, או-cpu hostב-QEMU גולמי. מודל אמולציה גנרי (qemu64,kvm64) מסתיר אתvmxגם כאשר הקינון מופעל גלובלית.
ל-hypervisors אחרים יש מתג משלהם. Hyper-V, למשל, מבצע אמולציה להרחבות הווירטואליזציה עבור hypervisor מקונן בתוך ה-VMs שלו, אך רק ב-VMs שבהם הקינון הופעל באופן פרטני.
בדיקת ה-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מופע (instance) תקין מדפיס vmx או svm, הפקודה kvm-ok מציגה KVM acceleration can be used, והקובץ /dev/kvm קיים במצב root:kvm עם הרשאות 660. אם הדגל קיים אך צומת ההתקן (device node) חסר, טען את המודול ידנית ועיין בלוג הליבה (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 יכול להריץ רמה שלישית של וירטואליזציה (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הסרת המודול נדחית כל עוד מכונה וירטואלית פועלת, לכן יש לכבות תחילה את המכונות האורחות. אם מדובר במחשב שמארח Proxmox, הפעלת וירטואליזציה מקוננת ב־Proxmox VE 9 מסבירה את אותו שינוי ב־modprobe.d, וכן את הגדרת cpu: host לכל VM, שהופכת את הדגל לגלוי בתוך מכונה אורחת.
מדוע רוב ספקי ה-VPS משאירים זאת כבוי
- הגירה חיה (Live migration). מתן גישה ל-
vmxמשמעו חשיפת מודל מעבד שנושא את הדגל הזה; אורח שתלוי בתכונות מעבד אלו לא יוכל לעבור בצורה בטוחה למכונה שבה המעבד חסר אותן. מארח שמפנה צמתים על ידי הגירת לקוחות מוותר על יכולת זו ברגע שהוא מאפשר nesting. - שטח תקיפה. נתיבי ה-VMX/SVM המקוננים הם מהקוד המורכב ביותר בשכבת הווירטואליזציה של ה-kernel, עם היסטוריית CVE תואמת.
- ייתכן ש-L0 אינו KVM. אם
systemd-detect-virtמדפיסvmware,xenאוmicrosoft, חוקי ה-nesting הם של אותו stack, ולא של KVM.
אין דגל במופע (instance) שלכם? פנו לתמיכה (חלקם מאפשרים זאת ברמת ה-VM), בחרו תוכנית שמתעדת nesting, או עברו לשרת ייעודי (dedicated box). המשך מדריך זה מניח גישת root למכונה שמציגה את הדגל.
הרצת אורח L2 באמצעות 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'אין צורך בסשן גרפי. התקנה טורית (serial install) נמשכת זמן מה, לכן יש להפעיל אותה בתוך shell עמיד: אותו workflow של tmux ששומר על סשנים של Claude Code פעילים ב-VPS ישמור גם על קונסולת virt-install מחוברת במקרה של ניתוק SSH. אם --os-variant debian13 נדחה, ה-osinfo-db שלכם ישן מהגרסה הנדרשת; הריצו osinfo-query os ובחרו שם קיים. --cpu host-passthrough מעביר את vmx אל תוך ה-L2, פעולה הנחוצה רק אם ה-L2 נדרש לבצע וירטואליזציה בעצמו. הפכו את האורח לבטוח לאתחול באמצעות virsh autostart guest1.
אפיק ה-virtio בדיסק ובכרטיס הרשת אינו קישוט: התקני IDE ו-e1000 מדומים מבצעים trap אל ה-hypervisor בתדירות גבוהה בהרבה מתורי virtio. תחת וירטואליזציה מקוננת (nesting), יציאה (exit) ש-L0 אינו יכול להשלים בעצמו משתקפת כלפי מעלה אל ה-L1, שם הטיפול בה עלול לעורר יציאות נוספות משל עצמו.
רשתות: החלק שמדריכים נוטים לדלג עליו
לשרת ה-VPS שלכם יש כתובת IP ציבורית אחת והוא נמצא מאחורי תשתית המסננת כתובות MAC לא מוכרות. לכך יש שתי השלכות.
גישור (Bridging) של אורחי L2 לרשת הציבורית בדרך כלל לא יעבוד. אם תגדירו br0 על כרטיס הרשת הציבורי ותתנו לאורח כתובת MAC משלו, תראו שחבילות ARP יוצאות אך דבר לא חוזר; המתג של ספק התשתית משליך חבילות שמגיעות מכתובת MAC שלא הוקצתה לכם. אם זו הבעיה שאתם חווים, הפסיקו לנפות שגיאות ב-bridge; זהו המנגנון הקיים.
השתמשו ברשת NAT במקום. המערכת default מספקת virbr0, 192.168.122.0/24, וחלוקת כתובות באמצעות dnsmasq, כך שהתקשורת היוצאת עובדת מיד. עבור תקשורת נכנסת, בצעו TLS termination בשכבת ה-L1 ובצעו proxy פנימה; נתיבי התעודות להלן מגיעים מ-הנפקת תעודת 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;
}
}הקצו לאורח כתובת IP קבועה (virsh net-edit default) כדי שהכתובת בתוך ה-proxy_pass תישאר קבועה.
ממשקי ניהול צריכים להישאר מחוץ לאינטרנט: VNC בפורט 5900 וממשק ה-Web של Proxmox בפורט 8006 צריכים להאזין ל-loopback, וניתן להגיע אליהם דרך מנהרת SSH (ssh -N -L 8006:127.0.0.1:8006 you@your-vps) או דרך חיבור WireGuard VPN עצמי לתוך ה-VPS, מה שמאפשר גישה לכל טווח הכתובות של האורחים 192.168.122.0/24 במרחק קפיצה פרטית אחת. שמרו על ה-firewall מצומצם, sudo ufw allow 22,80,443/tcp, ולא מעבר לכך. אם האורחים מאבדים קישוריות יוצאת מיד לאחר הפעלת ufw, האשם הנפוץ הוא DEFAULT_FORWARD_POLICY="DROP" בתוך /etc/default/ufw; הגדירו אותו ל-ACCEPT וטענו מחדש את ufw.
Proxmox על גבי VPS
Proxmox VE 9 מבוסס על Debian 13, לכן התקנתו על גבי VPS עם Debian מתבצעת על ידי הוספת המאגר pve-no-subscription והחבילה proxmox-ve. יש להשתמש בשורות המאגר וקובץ ה-keyring מתוך התיעוד הרשמי והעדכני של Proxmox; כתובת URL המועתקת מפוסט בבלוג ישן עלולה להוביל לכשל בהתקנה. כדאי לשקול האם Proxmox אכן מתאים לחומרה מושכרת לפני שמשקיעים ערב שלם בהגדרות הרשת להלן, והמאמר השוואת עלויות ויכולות בין שרת Proxmox ביתי לבין VPS מושכר מציג את ניתוח הכוח והחומרה הנדרש לשאלה זו.
החבילות אינן החלק המורכב. Proxmox מצפה ל-vmbr0 המגשר על כרטיס רשת פיזי (NIC), מה שמוביל ישירות למבוי סתום מול סינון כתובות MAC. התצורה שעובדת ב-VPS היא vmbr0 מבוסס NAT או ניתוב ללא חיבור לפורט פיזי, כאשר האורחים נמצאים בטווח כתובות פרטי, ונעשה שימוש בחוקי DNAT או ב-reverse proxy על המארח עבור כל שירות ציבורי. כאשר השירותים החשופים לאינטרנט הם מכולות (containers) ולא מכונות וירטואליות (VMs), המדריך Traefik כחזית למספר יישומים מקובץ Docker Compose אחד מכסה את אותה משימת ניתוב עם תעודות אוטומטיות. בצעו Snapshot של /etc/network/interfaces תחילה: הגדרת גשר (bridge) שגויה תנעל אתכם מחוץ למכונה שייתכן ואין לכם גישה לקונסולה שלה.
ביצועים, בכנות
וירטואליזציה מקוננת (Nested) איטית יותר מוירטואליזציה ברמה אחת, והמנגנון לכך ספציפי ולא מפוזר: העלות נופלת על יציאות (exits) ועל תרגום כתובות, ולא על הוראות מעבד רגילות. כאשר EPT/NPT זמינים, ה-L0 מאחד את טבלאות הדפים של ה-L1 עבור ה-L2 ואת הטבלאות שלו לטבלת צל (shadow table) אחת, כך שפגיעה ב-TLB רצה במהירות חומרה. החמצה ב-TLB עולה ביוקר: החומרה סורקת את טבלת הדפים של האורח ואת טבלת הצל יחד, וכל שינוי שה-L1 מבצע בטבלאות שלו מחייב יציאה כדי שה-L0 יוכל לסנכרן מחדש את הצל. מה שהופך ליקר הוא כל פעולה שיוצאת ממצב אורח (guest mode), כגון I/O, פסיקות טיימר, MMIO, ופסיקות בין-מעבדיות, כיוון שיציאת L2 מטופלת על ידי ה-L0 ועשויה להשתקף חזרה דרך ה-L1. עבודה המוגבלת על ידי המעבד (CPU-bound) עם סט עבודה קטן נראית קרובה לביצועים טבעיים; סטים גדולים בזיכרון משלמים את מחיר ההחמצות ב-TLB, וכל מה שנשלט על ידי syscalls, חבילות רשת ו-I/O של דיסק מרגיש את השכבות.
לכן: השתמשו בהתקני virtio בכל מקום. קובץ ה-qcow2 שלכם יושב על דיסק שהספק כבר וירטואל, מה שיוצר שתי שכבות של thin-provisioning זו על גבי זו, כאשר cache=none בדיסק האורח מונע מאותם בלוקים לשבת בשני מטמוני דפים (page caches) בו-זמנית. אין כאן מספרי ביצועים (benchmarks): מדדו את עומס העבודה שלכם על ה-instance שלכם.
מצבי כשל והודעות שגיאה נפוצות
INFO: /dev/kvm does not exist / KVM acceleration can NOT be used מתוך kvm-ok. או שהמודול אינו טעון, או שהדגל אינו חשוף. בדקו תחילה את /proc/cpuinfo.
kvm: disabled by bios בתוך dmesg. על חומרה פיזית (bare metal), יש להפעיל את מתג VT-x/SVM ב-firmware. בתוך VPS, המשמעות היא ש-L0 אינו מעביר אליכם את ההרחבות, ושום פעולה בתוך ה-guest לא תשנה זאת.
modprobe: ERROR: could not insert 'kvm_intel': Operation not supported. למעבד שה-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 אחר תופס את המעבד: הריצו את 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 על מארח שאינו מסוגל לספק אותה. תקנו את ה-nesting, או בטלו את הסימון והשתמשו ב-emulation.
Android emulator: x86_64 emulation currently requires hardware acceleration! שוב /dev/kvm, בדרך כלל מדובר בבעיית הרשאות קבוצה.
אין שגיאה, אך הביצועים איטיים מאוד. QEMU ללא דגל האצה חוזר ל-TCG, האמולטור התוכנתי שלו. הוא פועל בצורה תקינה אך איטית; עליית מערכת שנמדדת בשניות הופכת לדקות. העבירו את -accel kvm במפורש, כדי ש-QEMU ייעצר עם שגיאה במקום לבצע אמולציה שקטה.
ה-guest נעלם באמצע הריצה. חפשו ב-dmesg את Out of memory: Killed process ... qemu-system-x86_64. אורח L2 הוא תהליך ב-L1, וה-OOM killer מתייחס אליו כאל כל תהליך אחר. ה-RAM של L2 נלקח מהקצאה קבועה של L1, ללא אפשרות "לשאול" משאבים מהמארח.
תפעול: גיבויים, שדרוגים ומגבלות
גיבויים. העתקת קובץ qcow2 של אורח פעיל מסתכנת ביצירת תמונה לא עקבית, כיוון שהאורח ממשיך לכתוב בזמן הקריאה. יש להריץ את virsh shutdown guest1, להמתין עד ש-virsh domstate guest1 ידווח על shut off (פקודת הכיבוי עלולה לחזור לפני שהאורח סיים לעצור), ורק אז להעתיק; לחלופין, ניתן ליצור snapshot חיצוני (virsh snapshot-create-as guest1 snap1 --disk-only --atomic) כך שהכתיבה תופנה ל-overlay בזמן שאתם מעתיקים את קובץ הבסיס הסטטי, ולאחר מכן למזג אותו חזרה באמצעות virsh blockcommit guest1 vda --active --pivot. העבירו את העותקים מחוץ ל-VPS; snapshot שנשמר על אותו דיסק אינו מספק הגנה כלל.
שדרוגים. הפקודה apt full-upgrade מתקינה מודולים חדשים של kvm_intel/kvm_amd, אך ה-kernel הפעיל ממשיך להשתמש בישנים עד לביצוע reboot. שמרו על ה-kernel הקודם מותקן והריצו מחדש את kvm-ok לאחר כל שינוי ב-kernel: מארח שעולה ללא vmx נמצא במרחק של כניסת boot אחת בלבד מחזרה לעבודה תקינה.
איפה זה מפסיק להתרחב. כתובת IP ציבורית אחת פירושה שכל שירות L2 מגיע לעולם דרך proxy או חוק DNAT ב-L1. העברה חיה (live migration) אינה אפשרית בתצורה זו. תחת עומס CPU, נתיב ה-nested exit הוא הראשון שמושפע. בנוסף, hypervisor עם כמה אורחים הוא מכונה שבה ה-RAM כבר הוקצה מראש; מכונות וירטואליות מקוננות אינן יכולות לבצע overcommit מעבר להקצאה קבועה. כאשר מעבדה גדלה מעבר ליכולות אלו, הפתרון אינו ערימה מקוננת גבוהה יותר, אלא שרת ייעודי שבו אתם ה-L0, ושם כל האמור לעיל אינו רלוונטי.
FAQ
האם אני זקוק ל-nested virtualization כדי להריץ Docker על גבי VPS?
לא. מכולות (containers) משתפות את ה-kernel של ה-VPS שלך ולעולם אינן פותחות /dev/kvm, לכן מופע (instance) רגיל ללא דגל vmx או svm יריץ Docker ו-Docker Compose ללא בעיות. וירטואליזציה מקוננת רלוונטית רק כאשר נדרש kernel שני: מעבדת Proxmox, אורח Windows, מיקרו-מכונות וירטואליות מסוג Firecracker, אמולטור Android, או CI runners שמאתחלים תמונות של מכונות וירטואליות.
כיצד אוכל לבדוק אם ה-VPS שלי תומך ב-nested virtualization?
הריצו את grep -o -E 'vmx|svm' /proc/cpuinfo | sort -u, ולאחר מכן את kvm-ok מחבילת cpu-checker. מופע תקין ידפיס vmx (עבור Intel) או svm (עבור AMD), הפקודה kvm-ok תדווח על KVM acceleration can be used, והקובץ /dev/kvm יהיה קיים עם קבוצה kvm והרשאות 660. התעלמו מ-/sys/module/kvm_intel/parameters/nested בהקשר זה; קובץ זה מתאר את מודול ה-KVM המקומי שלכם, ולא את מה שה-hypervisor של ספק השירות חשף עבורכם.
מדוע רוב ספקי ה-VPS משביתים את ה-nested virtualization?
חשיפת vmx משמעותה מתן דגם מעבד לאורח שנושא את הדגל המתאים. אורח התלוי בתכונות מעבד אלו לא יוכל לעבור הגירה חיה (live-migration) למכונה שחסרה אותן; ספק שירות המפנה צמתים על ידי העברת לקוחות מוותר על יכולת זו. נתיבי הקוד של VMX/SVM מקוננים נושאים גם היסטוריה ארוכה של CVE. חלק מהספקים מאפשרים זאת לכל מכונה וירטואלית לפי בקשה, ואחרים מתעדים וירטואליזציה מקוננת כפיצ'ר בתוכניות מסוימות.
למכונה הווירטואלית המקוננת שלי אין רשת ב-bridge הציבורי. מה הבעיה?
המתג (switch) של ספק השירות חוסם חבילות (frames) מכתובת MAC שלא הוקצתה לך. לכן, אורח L2 שמחובר ל-NIC הציבורי שולח ARP אך לא מקבל מענה. הפסיקו לנפות שגיאות ב-br0, השתמשו ברשת NAT של libvirt (default, virbr0, 192.168.122.0/24), העניקו לאורח כתובת סטטית, ופרסמו כל שירות ציבורי דרך reverse proxy או חוק DNAT על גבי ה-VPS עצמו.
עד כמה איטית מכונה וירטואלית מקוננת?
העלות נובעת מ-VM exits ומפעולות תרגום כתובות. כאשר EPT/NPT פעילים, פקודות ו-TLB hits בתוך L2 רצים במהירות חומרה, אך TLB miss גורם לסריקת טבלאות דפים נוספות, ופעולות I/O, פסיקות טיימר, MMIO ו-IPI מטופלות על ידי L0 ועשויות לעבור חזרה דרך L1. עומס עבודה המוגבל על ידי המעבד (CPU-bound) עם סט נתונים קטן ייראה קרוב לביצועים מקוריים; עומסי עבודה כבדים בזיכרון, או כאלו המבצעים הרבה syscalls, תעבורת רשת או פעולות דיסק, ירגישו את ההשפעה של כל שכבה. השתמשו בהתקני virtio בכל מקום וב-cache=none עבור דיסקים של האורח, ולאחר מכן מדדו את עומס העבודה הספציפי שלכם.