האם אפשר להריץ 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 לתמונות של מכונות וירטואליות.
מהי למעשה היררכיית הקינון
קיימות שלוש שכבות:
- L0, ה־hypervisor של ספק התשתית, הפועל על החומרה הפיזית. אין לך גישה אליו.
- L1, ה־VPS שלך. עבור L0, זוהי רק מכונה אורחת.
- L2, המכונה הווירטואלית (VM) שברצונך להריץ בתוך ה־VPS שלך.
וירטואליזציה מבוססת חומרה היא VT-x (הדגל vmx) בתוספת EPT במעבדי Intel, או AMD-V / SVM (svm) בתוספת RVI/NPT במעבדי AMD. ה־hypervisor משתמש בהוראות אלו כדי להיכנס למצב אורח (guest mode) ולאפשר למעבד לעבור על שתי טבלאות דפים בו-זמנית.
אף אחת מהטכנולוגיות הללו לא תוכננה להיות רה-אנטרנטית (re-entrant), לכן הקינון מבוצע באמצעות אמולציה: כאשר L1 מבצע הוראת VMX, מתבצע trap ל־L0, אשר מנהל את מבני הנתונים המוצלים (shadow structures) עבור L2 בשמו של L1. מודול KVM מבצע זאת היטב, אך L0 נדרש לבצע עבודה נוספת בכל יציאה (exit), וזו הסיבה שהספק חייב לאשר זאת מראש.
כדי להריץ L2 מואץ, חייבים להתקיים שני תנאים:
- מודול ה־KVM של L0 טעון עם
nested=1. - L0 מספק ל־VPS שלך מודל מעבד הכולל את הדגל המתאים:
<cpu mode='host-passthrough'/>ב־libvirt,cpu: hostב־Proxmox, או-cpu hostב־QEMU גולמי. מודל אמולציה גנרי (qemu64,kvm64) מסתיר אתvmxגם כאשר הקינון מופעל גלובלית.
בדיקת ה-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הסרת מודול נדחית כל עוד מכונה וירטואלית (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'אין צורך בסשן גרפי. התקנה טורית נמשכת זמן מה, לכן יש להפעיל אותה בתוך shell עמיד: אותו תהליך עבודה עם 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), כל trap כזה משולם פעמיים.
רשתות: החלק שמדריכים נוטים לדלג עליו
לשרת ה-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 מתחזק טבלאות דפים (shadow page tables) עבור L2, וקריאות זיכרון רגילות מתבצעות במהירות חומרה. מה שהופך ליקר הוא כל פעולה שמוציאה את המערכת ממצב guest, כגון I/O, פסיקות טיימר, MMIO, ופסיקות בין-מעבדיות (inter-processor interrupts), שכן יציאה מ-L2 מטופלת על ידי L0 ועלולה לעבור השתקפות חזרה דרך L1. עבודה אינטנסיבית למעבד (CPU-bound) על נתונים שכבר נמצאים ב-RAM נראית קרובה לביצועים טבעיים; כל פעולה שנשלטת על ידי syscalls, חבילות רשת ו-I/O של דיסק תרגיש את השכבות.
לכן: השתמשו בהתקני virtio בכל מקום. קובץ ה-qcow2 שלכם נמצא על דיסק שהספק כבר וירטואל, מה שיוצר שתי שכבות של thin-provisioning זו על גבי זו, כאשר cache=none בדיסק ה-guest מונע מאותם בלוקים לשבת בשני מטמוני דפים (page caches) בו-זמנית. אין כאן מספרי benchmark: מדדו את עומס העבודה שלכם על ה-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 בזמן שהאורח (guest) פעיל תניב תמונה פגומה. יש לבצע virsh shutdown guest1 לפני ההעתקה, או ליצור snapshot חיצוני (virsh snapshot-create-as guest1 snap1 --disk-only --atomic) כך שהכתיבות יופנו לקובץ overlay בזמן שאתם מעתיקים את קובץ הבסיס הסטטי, ולאחר מכן למזג אותו חזרה באמצעות virsh blockcommit. העבירו את העותקים מחוץ ל-VPS; snapshot על אותו דיסק אינו מספק הגנה כלל.
שדרוגים. הפקודה apt full-upgrade מתקינה מודולים חדשים של kvm_intel/kvm_amd, אך ה-kernel הפעיל ממשיך להשתמש בישנים עד לביצוע reboot. שמרו את ה-kernel הקודם מותקן והריצו שוב את kvm-ok לאחר כל שינוי ב-kernel: מארח שעולה ללא vmx ניתן להחזרה למצב תקין באמצעות בחירה ב-boot entry הקודם.
מגבלות ה-scaling. כתובת IP ציבורית אחת משמעותה שכל שירות L2 מגיע לעולם דרך proxy או חוק DNAT ב-L1. העברת מכונות חיות (Live migration) אינה אפשרית בתצורה זו. תחת עומס CPU, נתיב ה-nested exit הוא הראשון להיפגע. היפרוויזור עם כמה אורחים הוא מכונה שזיכרון ה-RAM שלה כבר הוקצה במלואו; מכונות וירטואליות מקוננות (nested VMs) אינן יכולות לבצע overcommit מעבר להקצאה קבועה. כאשר המעבדה גדלה מעבר ליכולות אלו, הפתרון אינו ערימה מקוננת גבוהה יותר, אלא שרת ייעודי שבו אתם ה-L0, ושם מגבלות אלו אינן חלות.
FAQ
האם אני זקוק ל-nested virtualization כדי להריץ Docker על גבי VPS?
לא. מכולות משתפות את ה-kernel של ה-VPS שלך ולעולם אינן פותחות את /dev/kvm, לכן מופע רגיל ללא דגל vmx או svm מריץ Docker ו-Docker Compose ללא בעיות. וירטואליזציה מקוננת רלוונטית רק כאשר נדרש kernel שני: מעבדת Proxmox, אורח Windows, מיקרו-מכונות וירטואליות מסוג Firecracker, אמולטור Android, או CI runners שמבצעים boot לתמונות VM.
כיצד אוכל לבדוק אם ה-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. חלק מהספקים עדיין מאפשרים זאת לכל VM לפי בקשה, ואחרים מתעדים וירטואליזציה מקוננת כפיצ'ר בתוכניות מסוימות.
ל-VM המקונן שלי אין רשת ב-bridge הציבורי. מה הבעיה?
ה-switch של הספק משליך חבילות (frames) מכתובת MAC שלא הוקצתה לכם, לכן אורח L2 שמחובר ל-NIC הציבורי שולח ARP ולא מקבל מענה. הפסיקו לנפות שגיאות ב-br0, השתמשו ברשת NAT של libvirt מסוג default (virbr0, 192.168.122.0/24), תנו לאורח כתובת סטטית, ופרסמו כל שירות ציבורי דרך reverse proxy או חוק DNAT על ה-VPS עצמו.
עד כמה איטי VM מקונן?
העלות נובעת מ-VM exits, ולא מגישה לזיכרון. כאשר EPT/NPT פעילים, קריאות וכתיבות רגילות בתוך L2 רצות במהירות חומרה, בעוד ש-I/O, פסיקות טיימר, MMIO ו-IPI מטופלים על ידי L0 ועשויים לעבור דרך L1. עבודה אינטנסיבית למעבד על נתונים שכבר נמצאים ב-RAM קרובה לביצועים טבעיים; עומסי עבודה כבדים ב-syscall, חבילות רשת ודיסק ירגישו כל שכבה. השתמשו בהתקני virtio בכל מקום וב-cache=none בדיסקים של האורח, ולאחר מכן מדדו את עומס העבודה הספציפי שלכם.