XEN Update: Unterschied zwischen den Versionen
(80 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 5: | Zeile 5: | ||
===== Was zeichnet XEN als Hypervisor aus ===== | ===== Was zeichnet XEN als Hypervisor aus ===== | ||
* '''Typ 1''' Hypervisor | |||
* alt = '''ausgereift''' (Erfahrung, hat sich bewährt) | * alt = '''ausgereift''' (Erfahrung, hat sich bewährt) | ||
* klein = '''sicher''' (einfach, weniger Fehler) und '''stabil''' (weniger Code, weniger Fehler) | * klein = '''sicher''' (einfach, weniger Fehler) und '''stabil''' (weniger Code, weniger Fehler) | ||
* Modular = '''unabhängig''' (OS) und '''flexibel''' (Einsatzszenarien) | * Modular = '''unabhängig''' (OS) und '''flexibel''' (Einsatzszenarien) | ||
* Breite '''Hardware Unterstützung''' (ARM, Embedded, Cloud/IoT usw.) | * Breite '''Hardware Unterstützung''' (ARM, Embedded, Cloud/IoT usw.) | ||
Zeile 65: | Zeile 65: | ||
cat $CONFIGNAME | awk '{if ($1 !~ /#/) print $1}' | while read PCI ; do | cat $CONFIGNAME | awk '{if ($1 !~ /#/) print $1}' | while read PCI ; do | ||
[ -n "$PCI" ] && xl pci-assignable-remove -r | [ -n "$PCI" ] && xl pci-assignable-remove -r "$PCI" | ||
done | done | ||
</pre> | </pre> | ||
Zeile 79: | Zeile 79: | ||
memory = 256 | memory = 256 | ||
vcpus = 1 | vcpus = 1 | ||
driver_domain = 1 | driver_domain = 1 | ||
disk = [ 'phy:/dev/ssd/Domain-N-disk,xvda,w', 'phy:/dev/ssd/Domain-N-swap,xvdb,w' ] | disk = [ 'phy:/dev/ssd/Domain-N-disk,xvda,w', 'phy:/dev/ssd/Domain-N-swap,xvdb,w' ] | ||
vif = [ 'ip=192.168.1.4, bridge=xenbr0' ] | vif = [ 'ip=192.168.1.4, bridge=xenbr0' ] | ||
pci = [ '00:19.0' ] # Ethernet controller: Intel | pci = [ '00:19.0' ] # Ethernet controller: Intel | ||
# PV | |||
#type = 'pv' | |||
#bootloader = 'pygrub' | |||
# HVM / PVHVM | |||
type = 'hvm' | |||
#boot = 'dc' # d=cdrom, c=Harddisk | |||
keymap = 'de' | |||
vnc = 1 | |||
#vnclisten = '0.0.0.0' | |||
#vncpasswd = '' | |||
serial = 'pty' | |||
usb = 1 | |||
usbdevice = 'tablet' | |||
</pre> | </pre> | ||
Zeile 108: | Zeile 123: | ||
auto xenbr0 | auto xenbr0 | ||
iface xenbr0 inet static inherits xenbridge | iface xenbr0 inet static inherits xenbridge | ||
bridge_ports none | |||
address 192.168.1.5/24 | address 192.168.1.5/24 | ||
gateway 192.168.1.4 | gateway 192.168.1.4 | ||
dns-nameserver 192.168.178.1 | |||
</pre> | </pre> | ||
Die '''Network Driver Domain''' ist jetzt die einzige Verbindung der Dom0 zur Aussenwelt. In den meisten Fällen muss daher in | Die '''Network Driver Domain''' ist jetzt die einzige Verbindung der Dom0 zur Aussenwelt. In den meisten Fällen muss daher in der DriverDomain '''IP-Forwarding''' aktiviert werden, damit die Dom0 sich mit dem Netzwerk verbinden kann. Je nach Netzwerk-Design muss auf dem Internet-Router eine zusätzliche '''Route''' zur Dom0 mit Domain-N als Gateway eingerichtet werden. Eine ''Outgoing NAT'' Regel für die Dom0 in Richtung Internet muss natürlich ebenfalls aktiv sein. | ||
<pre> | <pre> | ||
sysctl -w net.ipv4.ip_forward=1 | sysctl -w net.ipv4.ip_forward=1 | ||
Zeile 120: | Zeile 137: | ||
net.ipv4.ip_forward=1 | net.ipv4.ip_forward=1 | ||
</pre> | </pre> | ||
'''Alternativ''' kann man die Dom0 auch über eine ''Network-Proxy'' Konfiguration an das LAN anbinden. Das habe ich auf meinem Notebook als Testsystem gemacht, da sich das Wireless Device nicht zu einer Bridge hinzufügen lässt, wie ich es mit dem Ethernet Device üblicherweise mache. Diese Konfiguration werde ich hier demnächst noch ergänzen. Dabei ist aufgfallen, dass die kaum verwendeten XEN-Scripten ''vif-route'' und ''vif-nat'' Fehler enthalten, da sie vereinzelt den Befehl ''ifconfig'' noch nicht durch dessen Nachfolger ''ip'' ersetzt haben. | |||
''' | '''Andernfalls''' kann man die Dom0 natürlich auch von einem '''internem Update-Mirror''' mit Updates versorgen. Dann braucht die Dom0 keine Verbindung mehr zum Internet. Sofern Domain-N selbst als Mirror dient, braucht man auch kein IP-Forwarding, und die Dom0 ist NUR von der Domain-N aus erreichbar. | ||
==== Driver Domain: Konfiguration ==== | ==== Driver Domain: Konfiguration ==== | ||
Zeile 200: | Zeile 218: | ||
</pre> | </pre> | ||
Jede virtuelle Maschine die unsere Domain-N als Network-Backend benutzt, erzeugt hier dynamisch ein neues virtuelles Netzwerkinterface '' | Jede virtuelle Maschine die unsere Domain-N als Network-Backend benutzt, erzeugt hier dynamisch ein neues virtuelles Netzwerkinterface ''vifX.Y'', wobei X die ID der XEN-VM entspricht, und Y der Interface-ID. Den Namen kann man aber in der XEN Konfiguration der VM mit dem Parameter ''vifname'' frei definieren (das funktioniert meiner Erfahrung nach nicht mit HVM DomUs). | ||
Diese dynamisch erzeugten Interfaces müssen automatisch der Bridge br_lan hinzugefügt werden. Das kann auf zwei Arten erfolgen: | Diese dynamisch erzeugten Interfaces müssen automatisch der Bridge br_lan hinzugefügt werden. Das kann auf zwei Arten erfolgen: | ||
# man definiert die entsprechenden statischen Einträge in /etc/network/interfaces | # man definiert die entsprechenden statischen Einträge in /etc/network/interfaces | ||
Zeile 219: | Zeile 237: | ||
Lösung zu 2) dynamische Konfiguration mittels '''xl devd''' | Lösung zu 2) dynamische Konfiguration mittels '''xl devd''' | ||
Der Daemon der diese Aufgabe erledigt wird mittels ''xl devd'' gestartet. Daher müssen die XEN-Utils installiert sein, was wir schon vorhin erledigt haben. | Der Daemon der diese Aufgabe erledigt wird mittels ''xl devd'' gestartet. Daher müssen die XEN-Utils installiert sein, was wir schon vorhin erledigt haben. Hierbei ist zu beachten, dass die Version von xen-utils identisch zur Version der Dom0 ist, da ja der xenstore der Dom0 gelesen wird. | ||
<pre> | <pre> | ||
xl devd | xl devd | ||
Zeile 255: | Zeile 273: | ||
</pre> | </pre> | ||
Nach dem Start einer neuen wurde | Nach dem Start einer neuen VM wurde deren virtuelles Interface automatisch mit der Backend-Bridge verbunden: | ||
<pre> | <pre> | ||
Domain-N:~# brctl show | Domain-N:~# brctl show | ||
bridge name bridge id STP enabled interfaces | bridge name bridge id STP enabled interfaces | ||
br_lan 8000.6805ca23181e no enp0s0 | br_lan 8000.6805ca23181e no enp0s0 | ||
vif2.0 | |||
</pre> | </pre> | ||
Der entsprechende Eintrag in der XEN Konfiguration für die VM lautet: | Der entsprechende Eintrag in der XEN Konfiguration für die VM lautet: | ||
<pre> | <pre> | ||
vif = [ ' | vif = [ 'backend=Domain-N, bridge=br_lan' ] | ||
</pre> | </pre> | ||
Die Option ''vifname=<mein name>'' funktioniert meiner Erfahrung nach übrigens nicht im HVM Modus, weshalb ich diese nicht mehr verwende. Da der Befehl '''xl devd''' die mit jedem Start einer VM wechselnden vif-Namen mit obiger Konfiguration (''allow-hotplug /vif*'') trotzdem der Bridge hinzufügen kann, brauche ich keinen eigenen statischen Namen mehr festlegen, wie ich es in dem folgenden Screenshot noch getan hatte (''vif_bullseye''). | |||
[[Datei:Domain-N bullseye.jpg]] | [[Datei:Domain-N bullseye.jpg]] | ||
==== Dom0: XEN VM Start-/Stop- Reihenfolge ==== | ==== Dom0: XEN VM Start-/Stop- Reihenfolge ==== | ||
Nachdem zukünftig alle VMs von der Driver Domain abhängig sind, um Netzwerkverbindung zu erhalten, müssen wir uns noch um die Startreihenfolge kümmern. Beim Runterfahren des gesamten Systems sollte die Driver Domain auch erst nach allen anderen VMs runterfahren. Hierzu passen wir innerhalb der Dom0 das File '''xendomains''' an, welches alle VMs automatisch startet und auch | Nachdem zukünftig alle VMs von der Driver Domain abhängig sind, um Netzwerkverbindung zu erhalten, müssen wir uns noch um die Startreihenfolge kümmern. Beim Runterfahren des gesamten Systems sollte die Driver Domain auch erst nach allen anderen VMs runterfahren. Hierzu passen wir innerhalb der Dom0 das File '''xendomains''' an, welches alle VMs automatisch startet und auch stoppt. | ||
Die Idee ist, dass wir ein 2.tes Start-/Stop- File '''xendomains.local''' anlegen, welches alle VMs die nicht die Driver Domain Domain-N, eine Firewall (opnsense) oder ein File-Server sind zuerst stoppen, dann den File-Server und anschliessend die Firewall stoppen, bevor das normale ''xendomains'' Skript alle restlichen virtuellen Maschinen runterfährt, welches jetzt nur noch die Driver Domain Domain-N sein sollte. | Die Idee ist, dass wir ein 2.tes Start-/Stop- File '''xendomains.local''' anlegen, welches alle VMs die nicht die Driver Domain Domain-N, eine Firewall (opnsense) oder ein Domain/File-Server sind zuerst stoppen, dann den Domain/File-Server und anschliessend die Firewall stoppen, bevor das normale ''xendomains'' Skript alle restlichen virtuellen Maschinen runterfährt, welches jetzt nur noch die Driver Domain Domain-N sein sollte. | ||
Hier ist das zusätzliche Dom0 [[ Init-Skript xendomains.local | Init-Skript '''/etc/init.d/xendomains.local''' ]] zum stoppen der VMs in vorgegebener Reihenfolge. | Hier ist das zusätzliche Dom0 [[ Init-Skript xendomains.local | Init-Skript '''/etc/init.d/xendomains.local''' ]] zum stoppen der VMs in vorgegebener Reihenfolge. | ||
Zeile 298: | Zeile 318: | ||
'''Xenproject.org''': ''"PVHVM and PVH can be thought of as features and not modes. The choices are PV or HVM, which describes how the instance boots, and your choice may be influenced by the features available. Currently, on EC2, PVH is not available, but PVHVM is: so the best choice for Linux (in general) would be booting a "HVM" instance with PVHVM enabled (eg, setting CONFIG_XEN_PVHVM)."'' | '''Xenproject.org''': ''"PVHVM and PVH can be thought of as features and not modes. The choices are PV or HVM, which describes how the instance boots, and your choice may be influenced by the features available. Currently, on EC2, PVH is not available, but PVHVM is: so the best choice for Linux (in general) would be booting a "HVM" instance with PVHVM enabled (eg, setting CONFIG_XEN_PVHVM)."'' | ||
Mein '''XEN VM Template''' listet alle verschiedenen Varianten, im Beispiel ist die PVH Variante aktiv, die anderen sind auskommentiert: | |||
<pre> | |||
name = 'buster' | |||
memory = 1024 | |||
cpus = '1-3' | |||
#driver_domain = 1 | |||
# PVH, benötigt entweder bootloader oder kernel option | |||
type = 'pvh' | |||
bootloader = 'pygrub' | |||
#kernel = 'kernel/buster/vmlinuz' | |||
# HVM / PVHVM | |||
#type = 'hvm' | |||
#boot = 'dc' # d=cdrom, c=Harddisk | |||
keymap = 'de' | |||
vnc = 1 | |||
vnclisten = '0.0.0.0' | |||
vncpasswd = '' | |||
serial = 'pty' | |||
usb = 1 | |||
usbdevice = 'tablet' | |||
# PV - PVGRUB, benötigt ein grub-image (mit grub-mkimage erstellt) | |||
#type = 'pv' | |||
#kernel = 'pvgrub/grub-x86_64-xen.bin' | |||
# PV - pygrub | |||
#type = 'pv' | |||
#bootloader = 'pygrub' | |||
disk = [ | |||
'phy:/dev/vg/buster-disk,xvda,w' | |||
] | |||
vif = [ 'vifname=buster, script=vif-bridge_qlen, bridge=xenbr0, backend=Domain-0' ] | |||
</pre> | |||
Auf meinem '''7 Jahre alten Core i5''' System (2x CPU plus Hyperthreading) mit 16GB RAM zeigt folgendes '''xentop''' wie effektiv XEN Virtualiserung implementiert: | |||
Vier VMs, wobei 3x im (PV)HVM Modus laufen und 1x der PVH Modus zum Einsatz kommt, lassen die Dom0 mit nur einer CPU (von vier insgesamt) bei 1-2% Load rumdümpeln. | |||
[[Datei:XENtop.jpg]] | |||
Sobald der Kernel der UCS System den PVH Modus unterstützt werde ich diese auch im PVH Modus betreiben. Die UCS Systeme basieren leider noch auf Debian 9, dessen Kernel ist noch nicht für PVH geeignet. Damit werden 2 QEmu Prozesse in der Dom0 ersatzlos verschwinden. Sobald ich die FreeBSD basierte OPNSense Firewall auch im PVH Modus betreibe, sind drei von vier QEmu Prozessen obsolet. | |||
[[Datei:XENlist qemu.jpg]] | |||
Als letzter Schritt kann seit XEN 4.11 auch die '''Dom0''' mittels die Option '''dom0=pvh''' im '''PVH Modus''' gestartet werden. | |||
Auf meinem produktivem System werde ich das aber erst nach einem ausführlichen Test aktivieren, da in Zeiten von Homeoffice und Homeschooling ungeplante Ausfallzeiten ziemlichen Ärger produzieren würden. | |||
==== PVHVM / HVM ==== | ==== PVHVM / HVM ==== | ||
PVHVM ist die klassische Standard HVM Variante die bis Dato für Windows-VMs verwendet werden: In das OS der VM werden optimierte XEN-Treiber installiert, die eine Paravirtualisierte Schnittstelle zum XEN-Backend zur Verfügung stellen um eine bessere Performance zu erzielen. | PVHVM ist die klassische Standard HVM Variante die bis Dato für Windows-VMs verwendet werden: In das OS der VM werden optimierte XEN-Treiber installiert, die eine Paravirtualisierte Schnittstelle zum XEN-Backend zur Verfügung stellen um eine bessere Performance zu erzielen. | ||
OPNSense verfügt mit FreeBSD als zugrunde liegendem Betriebssystem bereits über die notwendigen XEN PV-Treiber, daher muss keine Emulation für Disk- und Netzwerkressourcen verwendet werden | OPNSense verfügt mit FreeBSD als zugrunde liegendem Betriebssystem bereits über die notwendigen XEN PV-Treiber, daher muss keine Emulation für Disk- und Netzwerkressourcen verwendet werden. | ||
<pre> | <pre> | ||
Zeile 308: | Zeile 385: | ||
memory = '2048' | memory = '2048' | ||
cpus = ' | cpus = '1-3' | ||
type = 'hvm' | type = 'hvm' | ||
Zeile 327: | Zeile 404: | ||
on_crash = 'destroy' | on_crash = 'destroy' | ||
</pre> | </pre> | ||
Das ist also der zweit beste XEN Modus um OPNSense in einer VM zu betreiben. Noch performanter ist der PVH Modus, der als nächstes betrachtet wird. | Das ist also theoretisch der zweit beste XEN Modus um OPNSense in einer VM zu betreiben. Noch performanter ist der PVH Modus, der als nächstes betrachtet wird. In der Realität ist derzeit meist noch der HVM Modus zu bevorzugen, da PVH noch nicht einzelne offene Punkte auf der ToDo Liste stehen hat, bevor alle Szenarien damit funktionieren. | ||
XenProject.org<ref>https://wiki.xenproject.org/wiki/PV_on_HVM</ref>: ''"PV on HVM is a mixture of paravirtualization and full hardware virtualization. The primary goal of PV on HVM is to boost performance of fully virtualized HVM guests through use of specially optimized paravirtual device drivers (also called PVHVM or PV-on-HVM drivers).'' | XenProject.org<ref>https://wiki.xenproject.org/wiki/PV_on_HVM</ref>: ''"PV on HVM is a mixture of paravirtualization and full hardware virtualization. The primary goal of PV on HVM is to boost performance of fully virtualized HVM guests through use of specially optimized paravirtual device drivers (also called PVHVM or PV-on-HVM drivers).'' | ||
Zeile 336: | Zeile 413: | ||
==== PVH ==== | ==== PVH ==== | ||
Der PVH Modus ist laut xenproject.org der Königsweg für VMs | Der PVH Modus ist laut xenproject.org der Königsweg für VMs, da kein Domain Model mehr benötigt wird. Es werden jeweils die Vorteile von HVM und PV Modus genutzt. Das bedingt allerdings, dass der zu ladende Kernel PVH fähig ist. Bei meiner OPNSense Firewall die auf FreeBSD basiert ist das der Fall, weshalb ich es weiter unten ausprobiert habe. | ||
Wenn ich die vorhandenen Informationen richtig deute, ist PVH der geplante Standard-Modus für DomU. Bis es soweit ist, sind allerdings noch ein paar Probleme zu lösen: | |||
* '''PVGRUB''' funktioniert (derzeit) nicht im PVH Modus | |||
* zum Starten der VM wird deren '''Kernel''' verwendet (''bootloader='pygrub' '' oder ''kernel=<kernel>'' Option verwenden) | |||
* der Kernel muss PVH '''unterstützen''' (Linux >= 4.11) | |||
* '''PCI-Devices''' können (noch) nicht in die DomU gereicht werden | |||
* '''Dom0''' in PVH Mode ist ebenfalls (noch) experimentell und läuft noch nicht rund | |||
''xenproject.org:''<ref>https://xenbits.xen.org/people/royger/fosdem2014.pdf</ref> | ''xenproject.org:''<ref>https://xenbits.xen.org/people/royger/fosdem2014.pdf</ref> | ||
{| | {| | ||
| | | | ||
|- | |- | ||
| '''PVH technical Overview''' | | '''PVH technical Overview''' | ||
Zeile 366: | Zeile 450: | ||
* Native IOPL. | * Native IOPL. | ||
|} | |} | ||
===== PVH Linux Konfiguration ===== | ===== PVH Linux Konfiguration ===== | ||
Mein Owncloud Server in der DMZ mit | Vorraussetzung ist einen Kernel der den PVH Modus unterstützt, wie Linux Kernel ab Version 4.11. Mein Owncloud Server auf Basis von Buster (Kernel 4.19) läuft in der DMZ stabil mit folgendem Standard Konfigurationsfile und pygrub als bootloader, damit ich mich nicht um den Kernel zum booten kümmern brauche: | ||
<pre> | <pre> | ||
name = 'owncloud' | name = 'owncloud' | ||
memory = 2560 | memory = 2560 | ||
cpu = ' | cpu = '1-3' | ||
type = 'pvh' | type = 'pvh' | ||
Zeile 417: | Zeile 477: | ||
===== PVH FreeBSD Konfiguration ===== | ===== PVH FreeBSD Konfiguration ===== | ||
Die Problematik liegt hier | Die Problematik liegt hier weniger bei dem PVH Modus selbst, sondern schlicht beim Mix aus Linux Dom0 und FreeBSD DomU. FreeBSD lässt sich derzeit im PVH Modus nur über den Kernel booten. Ich muss also zuerst den Kernel in die Dom0 kopieren, um ihn zum booten in der Dom 0 zu starten, ein Verfahren wie beim Bootloader pygrub. Diesen habe ich bisher leider nicht selbst dazu bewegen können, den FreeBSD Kernel und dessen Partition zu finden und zu starten. Ein manuelles Skript dazu wird deshalb weiter unten aufgezeigt. Grub(-XEN) unterstützt leider (warum eigentlich?) mit PV weder chainloading noch die kfreebsd option um FreeBSD zu starten. | ||
Ein | |||
Da im PVH Modus (derzeit) kein PCI-Device wie meine Netzwerkkarte in die DomU gereicht werden kann, werde ich die OPNSense Firewall trotzdem im PVHVM Modus betreiben. | |||
Unter Debian Buster (XEN 4.11) funktionieren virtuelle Netzwerkinterfaces problemlos. Auf meinem Testsystem mit Debian Bullseye (XEN 4.14) bekomme ich derzeit allerdings kein einziges Paket über die virtuelle Netzwerkschnittstelle übertragen, FreeBSD bzw. OPNSense deaktiviert das virtuelle Interface beim booten leider. | |||
XEN OPNsense (FreeBSD) PVH Konfiguration: | XEN OPNsense (FreeBSD) PVH Konfiguration: | ||
Zeile 433: | Zeile 493: | ||
kernel = '/root/xen/kernel/opnsense/kernel' # load FreeBSD kernel direct | kernel = '/root/xen/kernel/opnsense/kernel' # load FreeBSD kernel direct | ||
extra = 'vfs.root.mountfrom=ufs:/dev/gpt/rootfs vfs.root.mountfrom.options=rw module_path="/boot/kernel;/boot/modules"' | extra = 'vfs.root.mountfrom=ufs:/dev/gpt/rootfs vfs.root.mountfrom.options=rw module_path="/boot/kernel;/boot/modules"' | ||
# oder ufs:/dev/ufs/OPNSense mit MBR Partitionierung | |||
# Disk | # Disk | ||
disk = [ 'phy:/dev/vg/opnsense-disk,xvda,w' ] | disk = [ 'phy:/dev/vg/opnsense-disk,xvda,w' ] | ||
Zeile 446: | Zeile 506: | ||
</pre> | </pre> | ||
OPNSense | OPNSense bzw. die FreeBSD Firewall Implementierung ''PF'' (Paket Filter) benötigt folgende Anpassung der Netzwerkschnittstellen: '''Tx off'''. | ||
Dafür verwende ich folgendes angepasstes '''vif-bridge_TxOff''' Skript: | Dafür verwende ich folgendes angepasstes '''vif-bridge_TxOff''' Skript (''ethtool'' vorher installieren nicht vergessen): | ||
<pre> | <pre> | ||
#!/bin/bash | #!/bin/bash | ||
Zeile 526: | Zeile 586: | ||
xen create ${CONFIG_DIR}/${VM}${VM_CFG} | xen create ${CONFIG_DIR}/${VM}${VM_CFG} | ||
</pre> | </pre> | ||
Das funktioniert soweit, ich kann OPNSense im PVH Modus starten. Allerdings gibt es beim runterfahren ein lästiges Problem: Der OPNSense Kernel beendet die VM nicht vollständig, wartet am Ende auf einen Tastendruck | Das funktioniert soweit, ich kann OPNSense im PVH Modus starten. | ||
Allerdings gibt es beim runterfahren ein lästiges Problem: Der OPNSense Kernel beendet die VM nicht vollständig, wartet am Ende auf einen Tastendruck, und xentop zeigt dabei 100% cpu load an :-( | |||
<pre> | <pre> | ||
... | ... | ||
Zeile 545: | Zeile 608: | ||
</pre> | </pre> | ||
===== PVH Dom0 Konfiguration ===== | |||
''Xen Project 4.11 adds experimental PVH Dom0 support by calling Xen via dom0=pvh on the command line. Running a PVH Dom0 removes approximately 1 million lines of QEMU code from Xen Project’s computing base shrinking the attack surface of Xen Project based systems. | |||
Enabling a PVH Dom0 requires a PVH Dom0 capable Linux or FreeBSD. Patches for each operating system are currently being upstreamed and should be available in the next Linux and FreeBSD versions.'' | |||
'''/etc/default/grub.d/xen''' | |||
<pre> | <pre> | ||
GRUB_CMDLINE_XEN="dom0_mem=1536M,max:1536M dom0_max_vcpus=1-1 dom0_vcpus_pin dom0=pvh loglvl=all" | |||
</pre> | </pre> | ||
Debian 11 (Bullseye) Dom0 in PVH mode startet, XEN bringt aber noch einen Hinweis auf ''Experimental Mode''. Ausserdem zeigt xentop eine Auslastung der Dom0 von 100% an, während auch top 65% anzeigt. Es zeigt sich, dass der PVH Modus der "neueste" Modus ist, der tatsächlich noch experimentellen Charakter aufweist und noch nicht überall reibnugsfrei funktioniert. | |||
<pre> | <pre> | ||
xen dmesg | grep PVH | |||
(XEN) Command line: placeholder dom0_mem=1536M,max:1536M dom0_max_vcpus=1-1 dom0_vcpus_pin dom0=pvh loglvl=all | |||
(XEN) WARNING: PVH is an experimantal mode with limited functionality | |||
dmesg | grep PVH | |||
[ 0.270978] Booting paravirtualized kernel on XEN PVH | |||
</pre> | </pre> | ||
Aktuelle Version vom 13. März 2021, 17:11 Uhr
XENvelopment
Einleitung
Seit Einführung der Virtualisierungslösung KVM direkt im Linux Kernel ist es in den letzten Jahren stiller um den älteren XEN-Hypervisor geworden. Als Typ 1 Hypervisor wurde ihm immer als Nachteil ausgelegt, nicht direkt im Linux Kernel angesiedelt zu sein. Bei genauer Betrachtung erscheint mir persönlich das eher als Vorteil denn als Nachteil. Seine Entwicklung und Unterstützung steht auf einer Basis, welche tatsächlich unabhängig von einem bestimmten Kernel bzw. Betriebssystem ist. Der XEN Hypervisor ist also KEINE Linux-Lösung, sondern kann ebenfalls auf alternativen BSD oder Unix Systemen [1] wie z.B. FreeBSD aufbauen.
Was zeichnet XEN als Hypervisor aus
- Typ 1 Hypervisor
- alt = ausgereift (Erfahrung, hat sich bewährt)
- klein = sicher (einfach, weniger Fehler) und stabil (weniger Code, weniger Fehler)
- Modular = unabhängig (OS) und flexibel (Einsatzszenarien)
- Breite Hardware Unterstützung (ARM, Embedded, Cloud/IoT usw.)
Konzept
Die Virtualisierungslösung XEN besteht aus einem Hostsystem, Dom0 genannt, welches einer ganz normalen Linux-, BSD oder Unix Installation entspricht. Einziger Unterschied ist, dass nicht der normale System-Kernel direkt gestartet wird, sondern der XEN Hypervisor (xen.gz) diesen Kernel (Debian: vmlinuz) startet. Die Management Domain Dom0 selbst ist damit ein Standard Linux System, bei mir seit mehr als 10 Jahren Debian, derzeit Buster.
Auf dem Management System Dom0 selbst wird natürlich keinerlei Software oder Funktionalität installiert, dafür verwendet man ja die VMs. Sie dient ausschliesslich dem Management der virtualisierten Hardware- und Infrastruktur (Software-) Komponenten für die geplanten virtuellen Maschinen (VM), bei XEN als DomU bezeichnet.
Einige interessante aktuelle Entwicklungen im XEN Umfeld
Überblick[2]
- Driver Domain [3]
- Dom0 Disaggregation [4]
- Virtualisierungsvarianten
- PVH[5]
- XAPI (XEN Management API)
- XCPng [6](OpenSource Nachfolger des Citrix XEN Server)
- Xen on Embedded and Automotive systems [7]
- Unikernels [8][9]
- Qubes OS [10] (OS auf XEN Basis mit maximaler Sicherheit)
Für XEN Endanwender wie mich sind hier die Punkte Virtualisierungsvarianten wie PVH und Driver Domain interessant. Qubes OS treibt diese Ansätze auf die Spitze und hat damit ein maximal sicheres und freies Betriebssystem auf XEN Basis erstellt (empfohlen und genutzt z.B. von Edward Snowden), indem sie nicht jeweils ein ganzes System virtualisieren, sondern einzelne Applikationen. So gibt es beispielsweise einen Browser in einer "privaten" Umgebung, einen Browser in einer "Arbeit" Umgebung und evtl. noch einen separaten in einer "Banking" Umgebung.
Die Entwicklungen im Bereich Embedded/Automotive im Zusammenspiel mit maximaler Sicherheit und auch die Implementierungen in Cloud/IoT Bereich zeigen, das XEN durchaus aktuelle und höchst interessante Weiterentwicklungen erfährt. Warum? Vermutlich gerade durch die oben genannten Punkte in Zusammenhang mit dem OpenSource Ansatz und der durch den kleinen, einfachen, performanten und sicherem Design des Hypervisors, der für alle Anwendungsbereiche Vorteile aufweisen kann.
XEN steht meine Meinung nach einzig aus Endanwendersicht hinter besser integrierten Lösungen wie KVM zurück, ob das derzeit tatsächlich noch gerechtfertigt ist oder nicht sei von jedem selbst zu bewerten. Eine XEN Installation ist inzwischen nicht komplizierter als eine KVM Installation, trotz der zusätzlichen XEN Schicht unter dem eigentlichem Hostsystem.
Praxis für Endanwender
Einfach gesagt: Performance und Sicherheit der XEN Virtualisierung steigen, indem das Hostsystem Dom0 möglichst wenig selbst machen muss bzw. kann. Man möchte also soviel wie möglich auslagern. Das Konzept wird bei XEN als Domain Disaggregation bezeichnet.
XEN Driver Domain
Eine Driver Domain ist ein erster Schritt der Dom0 Disaggregation: Funktionen von Hardware Treibern werden aus der Dom0 in eine VM ausgelagert, eine ganz normale DomU. Sie dient den anderen VMs als Driver-Backend für z.B. Netzwerk, Storage und USB.
Network Driver Domain mit Debian (Buster, XEN 4.11 oder Bullseye, XEN 4.14)
Wir starten damit, der Dom0 die Netzwerkkarte wegzunehmen, und verfrachten diese in eine Network Driver Domain. Das Henne - Ei Problem Netzwerk lösen wir dadurch, das wir zuerst ganz normal die Dom0 installieren, und eine weitere DomU. Wenn beide installiert sind, können wir die Netzwerkkonfiguration so ändern, dass die Netzwerkkarte nach einem Neustart der DomU zugeordnet ist, und die Dom0 ein virtuelles Netzwerkinterface benutzt.
- Hardware Adresse der Netzwerkkarte(n) ermitteln und in einer Konfigurationsdatei /etc/xen/xen-pciback.conf speichern
# lspci | awk '/Ethernet/ {print "#"$1" #"$2" "$3" "$4}' > /etc/xen/xen-pciback.conf # cat /etc/xen/xen-pciback.conf 00:19.0 #Ethernet controller: Intel #02:00.0 #Ethernet controller: Intel #03:00.0 #Ethernet controller: Intel
- Der Dom0 die Netzwerkkarte wegnehmen
In obigem Beispiel soll z.B. nur das OnBoard-Netzwerkinterface (00:19.0) dem XEN Backend zugeordnet werden. Folgendes Skript hilft dabei, PCI-Karten entsprechend dem Konfigurationsfile aus der Dom0 zu lösen:
NAME=xen-pciback MODULE=xen_pciback CONFIGNAME=/etc/xen/$NAME.conf modprobe $MODULE cat $CONFIGNAME | awk '{if ($1 !~ /#/) print $1}' | while read PCI ; do [ -n "$PCI" ] && xl pci-assignable-remove -r "$PCI" done
Hier ist das entsprechende Debian Init-Script /etc/init.d/xen-pcibackend .
Dom0: Driver Domain Konfiguration
Die Network Driver Domain erhält neben dem PCI Device noch ein virtuelles Netzwerkinterface für die Dom0.
/etc/xen/Domain-N.cfg
name = 'Domain-N' memory = 256 vcpus = 1 driver_domain = 1 disk = [ 'phy:/dev/ssd/Domain-N-disk,xvda,w', 'phy:/dev/ssd/Domain-N-swap,xvdb,w' ] vif = [ 'ip=192.168.1.4, bridge=xenbr0' ] pci = [ '00:19.0' ] # Ethernet controller: Intel # PV #type = 'pv' #bootloader = 'pygrub' # HVM / PVHVM type = 'hvm' #boot = 'dc' # d=cdrom, c=Harddisk keymap = 'de' vnc = 1 #vnclisten = '0.0.0.0' #vncpasswd = '' serial = 'pty' usb = 1 usbdevice = 'tablet'
Die Dom0 verbindet sich mit der Network Driver Domain wie üblich über die virtuelle Bridge xenbr0 (vif=[bridge=xenbr0]).
XEN-Bridge Konfiguration der Dom0 in /etc/network/interfaces (Debian)
# --------------------------------- # settings for all XEN bridges # --------------------------------- iface xenbridge inet manual pre-up brctl addbr $IFACE bridge_fd 0 bridge_stp off bridge_hello 1 bridge_maxwait 0 bridge_waitport 0 post-up ip link set $IFACE promisc off post-down brctl delbr $IFACE # ---------------------------------------------------------- # xenbr0 -> Dom0 Network Interface connects to Driver Domain # ---------------------------------------------------------- auto xenbr0 iface xenbr0 inet static inherits xenbridge bridge_ports none address 192.168.1.5/24 gateway 192.168.1.4 dns-nameserver 192.168.178.1
Die Network Driver Domain ist jetzt die einzige Verbindung der Dom0 zur Aussenwelt. In den meisten Fällen muss daher in der DriverDomain IP-Forwarding aktiviert werden, damit die Dom0 sich mit dem Netzwerk verbinden kann. Je nach Netzwerk-Design muss auf dem Internet-Router eine zusätzliche Route zur Dom0 mit Domain-N als Gateway eingerichtet werden. Eine Outgoing NAT Regel für die Dom0 in Richtung Internet muss natürlich ebenfalls aktiv sein.
sysctl -w net.ipv4.ip_forward=1 # or make it permanent: uncomment in /etc/sysctl.conf and execute sysctl -p for refresh # Uncomment the next line to enable packet forwarding for IPv4 net.ipv4.ip_forward=1
Alternativ kann man die Dom0 auch über eine Network-Proxy Konfiguration an das LAN anbinden. Das habe ich auf meinem Notebook als Testsystem gemacht, da sich das Wireless Device nicht zu einer Bridge hinzufügen lässt, wie ich es mit dem Ethernet Device üblicherweise mache. Diese Konfiguration werde ich hier demnächst noch ergänzen. Dabei ist aufgfallen, dass die kaum verwendeten XEN-Scripten vif-route und vif-nat Fehler enthalten, da sie vereinzelt den Befehl ifconfig noch nicht durch dessen Nachfolger ip ersetzt haben.
Andernfalls kann man die Dom0 natürlich auch von einem internem Update-Mirror mit Updates versorgen. Dann braucht die Dom0 keine Verbindung mehr zum Internet. Sofern Domain-N selbst als Mirror dient, braucht man auch kein IP-Forwarding, und die Dom0 ist NUR von der Domain-N aus erreichbar.
Driver Domain: Konfiguration
Die Network Driver Domain erfüllt initial nur einen Zweck: Die Netzwerkkarte den anderen VMs zur Verfügung stellen. Dazu verbindet man die Netzwerkkarte mit einer Bridge, welche die virtuellen Interfaces aller VMs mit der Netzwerkkarte verbindet. Zusätzlich wird eine Netzwerkverbindung über das virtuelle Interface eth0 mit der Dom0 eingerichtet.
Netzwerkkonfiguration der Domain-N in /etc/network/interfaces (Debian)
# --------------------------------------- # The (routing) network interface to Dom0 # --------------------------------------- auto eth0 iface eth0 inet static address 192.168.1.4/24 # --------------------------------- # settings for all XEN bridges # --------------------------------- iface xenbridge inet manual pre-up brctl addbr $IFACE bridge_fd 0 bridge_stp off bridge_hello 1 bridge_maxwait 0 bridge_waitport 0 post-up ip link set $IFACE promisc off post-down brctl delbr $IFACE # ------------------------------------------- # br_lan -> Network Backend Interface vor VMs # ------------------------------------------- auto br_lan iface br_lan inet static inherits xenbridge bridge_ports none address 192.168.2.4/24 gateway 192.168.2.12 # --------------------------------- # The backend network device enp0s0 # --------------------------------- auto enp0s0 iface enp0s0 inet manual pre-up ifup br_lan up brctl addif br_lan $IFACE down brctl delif br_lan $IFACE
Nach dem Booten der Domain-N hat diese jetzt folgende Netzwerkkonfiguration:
- eine Bridge für die VMs (br_lan)
- ein virtuelles Interface für die Dom0 (eth0)
- die Netzwerkkarte die mit der Bridge verbunden ist (enp0s0)
- eine Default-Route
Domain-N:~# brctl show bridge name bridge id STP enabled interfaces br_lan 8000.6805ca23181e no enp0s0 Domain-N:~# ip -br a lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 192.168.1.4/24 fe80::216:3eff:fe28:e73/64 enp0s0 UP fe80::6a05:caff:fe23:181e/64 br_lan UP 192.168.2.4/24 fe80::28c8:c4ff:feac:7489/64 Domain-N:~# ip -br r default via 192.168.2.12 dev br_lan onlink 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.4
Driver Domain: XEN-Utils Installation
Die Driver Domain muss Zugriff auf die XEN Konfigurationsdatenbank xenstore erhalten, damit die grundlegenden Konfigurationsdaten der laufenden XEN Instanzen zwischen der Dom0 von der Driver Domain ermittelt werden können. Hierzu werden die xen-utils Pakete installiert.
Domain-N:~# apt-get install --no-install-recommends xen-utils
Jede virtuelle Maschine die unsere Domain-N als Network-Backend benutzt, erzeugt hier dynamisch ein neues virtuelles Netzwerkinterface vifX.Y, wobei X die ID der XEN-VM entspricht, und Y der Interface-ID. Den Namen kann man aber in der XEN Konfiguration der VM mit dem Parameter vifname frei definieren (das funktioniert meiner Erfahrung nach nicht mit HVM DomUs). Diese dynamisch erzeugten Interfaces müssen automatisch der Bridge br_lan hinzugefügt werden. Das kann auf zwei Arten erfolgen:
- man definiert die entsprechenden statischen Einträge in /etc/network/interfaces
- oder ein Daemon erledigt diese Arbeit automatisch
Lösung zu 1) statische Konfiguration in /etc/network/interfaces
auto /vif* allow-hotplug /vif* iface vif_vm2 inet manual pre-up ifup br_lan up brctl addif br_lan $IFACE post-up ip link set $IFACE qlen 1000 down brctl delif br_lan $IFACE ...
Lösung zu 2) dynamische Konfiguration mittels xl devd Der Daemon der diese Aufgabe erledigt wird mittels xl devd gestartet. Daher müssen die XEN-Utils installiert sein, was wir schon vorhin erledigt haben. Hierbei ist zu beachten, dass die Version von xen-utils identisch zur Version der Dom0 ist, da ja der xenstore der Dom0 gelesen wird.
xl devd
Hier ist ein entsprechendes Init-Skript zum Start des Daemons.
Der Daemon xl devd arbeitet mit den XEN-Skripten und deren Konfiguration in /etc/xen/xl.conf. Eine kleine Anpassung sorgt dafür, dass die virtuellen Interfaces die gleiche Konfiguration wie die physikalischen Interfaces (qlen=1000 statt qlen=32) erhalten.
Hinweis: Das gleiche mache ich übrigens auch in der Dom0.
/etc/xen/xl.conf und /etc/xen/scripts/vif-bridge_qlen
### xl.conf: grep qlen /etc/xen/xl.conf vif.default.script="vif-bridge_qlen" Skript vif-bridge_qlen: #!/bin/bash #============================================================================ # ${XEN_SCRIPT_DIR}/vif-bridge_qlen # # Script for configuring a vif in bridged mode. # # XEN default sets $vif txqueuelne 32 # correct this to default $vif txqueuelen 1000 dir=$(dirname "$0") ip link set $vif qlen 1000 $dir/vif-bridge $@
Nach dem Start einer neuen VM wurde deren virtuelles Interface automatisch mit der Backend-Bridge verbunden:
Domain-N:~# brctl show bridge name bridge id STP enabled interfaces br_lan 8000.6805ca23181e no enp0s0 vif2.0
Der entsprechende Eintrag in der XEN Konfiguration für die VM lautet:
vif = [ 'backend=Domain-N, bridge=br_lan' ]
Die Option vifname=<mein name> funktioniert meiner Erfahrung nach übrigens nicht im HVM Modus, weshalb ich diese nicht mehr verwende. Da der Befehl xl devd die mit jedem Start einer VM wechselnden vif-Namen mit obiger Konfiguration (allow-hotplug /vif*) trotzdem der Bridge hinzufügen kann, brauche ich keinen eigenen statischen Namen mehr festlegen, wie ich es in dem folgenden Screenshot noch getan hatte (vif_bullseye).
Dom0: XEN VM Start-/Stop- Reihenfolge
Nachdem zukünftig alle VMs von der Driver Domain abhängig sind, um Netzwerkverbindung zu erhalten, müssen wir uns noch um die Startreihenfolge kümmern. Beim Runterfahren des gesamten Systems sollte die Driver Domain auch erst nach allen anderen VMs runterfahren. Hierzu passen wir innerhalb der Dom0 das File xendomains an, welches alle VMs automatisch startet und auch stoppt.
Die Idee ist, dass wir ein 2.tes Start-/Stop- File xendomains.local anlegen, welches alle VMs die nicht die Driver Domain Domain-N, eine Firewall (opnsense) oder ein Domain/File-Server sind zuerst stoppen, dann den Domain/File-Server und anschliessend die Firewall stoppen, bevor das normale xendomains Skript alle restlichen virtuellen Maschinen runterfährt, welches jetzt nur noch die Driver Domain Domain-N sein sollte.
Hier ist das zusätzliche Dom0 Init-Skript /etc/init.d/xendomains.local zum stoppen der VMs in vorgegebener Reihenfolge.
XEN Virtualisierungsvarianten
XEN hat inzwischen verschiedene Varianten[11] der Virtualisierung von VMs implementiert:
- HVM (Vollvirtualisiert, QEMU Emulator)
- PVHVM
- PVH
- PV (Paravirtualisiert)
Zwischen den beiden Extremem HVM Vollvirtualisierung (alle Komponenten sind emuliert) und PV (alle Komponenten sind Paravirtualisiert) liegt ein Mischbetrieb von beidem, wo jeweils nur einzelne Komponenten im HV oder PV Modus verwendet werden. Zu bevorzugen ist hierbei die PVH Variante, welche die beste Performance aufweist: Die in Hardware (CPU, Memory) implementierten Virtualisierungsfunktionen werden ohne PV-Treiber direkt verwendet, während alle anderen Komponenten (Disk, Storage, Graphic, Timer, Interupts, Motherboard, Boot ...) paravirtualiserte Schnittstellen verwenden.
Quelle: xenproject.org
Der Einsatz der verschiedenen Modi sollte wie folgt priorisiert werden, je nach Möglichkeit ob sie eingesetzt werden kann:
- PVH
- HVM mit PVHVM Treiber (HVM Standard)
- HVM mit PV Treiber (überholt)
- PV
Xenproject.org: "PVHVM and PVH can be thought of as features and not modes. The choices are PV or HVM, which describes how the instance boots, and your choice may be influenced by the features available. Currently, on EC2, PVH is not available, but PVHVM is: so the best choice for Linux (in general) would be booting a "HVM" instance with PVHVM enabled (eg, setting CONFIG_XEN_PVHVM)."
Mein XEN VM Template listet alle verschiedenen Varianten, im Beispiel ist die PVH Variante aktiv, die anderen sind auskommentiert:
name = 'buster' memory = 1024 cpus = '1-3' #driver_domain = 1 # PVH, benötigt entweder bootloader oder kernel option type = 'pvh' bootloader = 'pygrub' #kernel = 'kernel/buster/vmlinuz' # HVM / PVHVM #type = 'hvm' #boot = 'dc' # d=cdrom, c=Harddisk keymap = 'de' vnc = 1 vnclisten = '0.0.0.0' vncpasswd = '' serial = 'pty' usb = 1 usbdevice = 'tablet' # PV - PVGRUB, benötigt ein grub-image (mit grub-mkimage erstellt) #type = 'pv' #kernel = 'pvgrub/grub-x86_64-xen.bin' # PV - pygrub #type = 'pv' #bootloader = 'pygrub' disk = [ 'phy:/dev/vg/buster-disk,xvda,w' ] vif = [ 'vifname=buster, script=vif-bridge_qlen, bridge=xenbr0, backend=Domain-0' ]
Auf meinem 7 Jahre alten Core i5 System (2x CPU plus Hyperthreading) mit 16GB RAM zeigt folgendes xentop wie effektiv XEN Virtualiserung implementiert:
Vier VMs, wobei 3x im (PV)HVM Modus laufen und 1x der PVH Modus zum Einsatz kommt, lassen die Dom0 mit nur einer CPU (von vier insgesamt) bei 1-2% Load rumdümpeln.
Sobald der Kernel der UCS System den PVH Modus unterstützt werde ich diese auch im PVH Modus betreiben. Die UCS Systeme basieren leider noch auf Debian 9, dessen Kernel ist noch nicht für PVH geeignet. Damit werden 2 QEmu Prozesse in der Dom0 ersatzlos verschwinden. Sobald ich die FreeBSD basierte OPNSense Firewall auch im PVH Modus betreibe, sind drei von vier QEmu Prozessen obsolet.
Als letzter Schritt kann seit XEN 4.11 auch die Dom0 mittels die Option dom0=pvh im PVH Modus gestartet werden.
Auf meinem produktivem System werde ich das aber erst nach einem ausführlichen Test aktivieren, da in Zeiten von Homeoffice und Homeschooling ungeplante Ausfallzeiten ziemlichen Ärger produzieren würden.
PVHVM / HVM
PVHVM ist die klassische Standard HVM Variante die bis Dato für Windows-VMs verwendet werden: In das OS der VM werden optimierte XEN-Treiber installiert, die eine Paravirtualisierte Schnittstelle zum XEN-Backend zur Verfügung stellen um eine bessere Performance zu erzielen.
OPNSense verfügt mit FreeBSD als zugrunde liegendem Betriebssystem bereits über die notwendigen XEN PV-Treiber, daher muss keine Emulation für Disk- und Netzwerkressourcen verwendet werden.
name = 'opnsense' memory = '2048' cpus = '1-3' type = 'hvm' disk = [ 'phy:/dev/ssd/opnsense,xvda,w' ] vif = [ 'mac=00:17:3E:BE:A1:FC, bridge=br2dmz, devid=0, script=vif-bridge_TxOff' ] # Orange, set tx checksum off #'mac=00:17:3E:BE:A1:FB, bridge=br1extern, devid=1, script=vif-bridge_TxOff', # RED #'mac=00:17:3E:BE:A1:FA, bridge=br0intern, devid=2, script=vif-bridge_TxOff', # Green #'mac=00:17:3E:BE:A1:FD, bridge=br3wlan, devid=3, script=vif-bridge_TxOff', # Blue #'mac=00:17:3E:BE:A1:FF, bridge=br4off, devid=4, script=vif-bridge_TxOff', # OFF pci = [ '02:00.0' ] # Ethernet, VLAN Konfiguration für RED, Green und Blue on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'destroy'
Das ist also theoretisch der zweit beste XEN Modus um OPNSense in einer VM zu betreiben. Noch performanter ist der PVH Modus, der als nächstes betrachtet wird. In der Realität ist derzeit meist noch der HVM Modus zu bevorzugen, da PVH noch nicht einzelne offene Punkte auf der ToDo Liste stehen hat, bevor alle Szenarien damit funktionieren.
XenProject.org[12]: "PV on HVM is a mixture of paravirtualization and full hardware virtualization. The primary goal of PV on HVM is to boost performance of fully virtualized HVM guests through use of specially optimized paravirtual device drivers (also called PVHVM or PV-on-HVM drivers).
...
"PV-on-HVM drivers are optimized PV drivers for HVM environments that bypass the emulation for disk and network IO. They also make use CPU functionality such as Intel EPT or AMD NPT support. Thus, giving you PV-like or better performance on HVM systems."
PVH
Der PVH Modus ist laut xenproject.org der Königsweg für VMs, da kein Domain Model mehr benötigt wird. Es werden jeweils die Vorteile von HVM und PV Modus genutzt. Das bedingt allerdings, dass der zu ladende Kernel PVH fähig ist. Bei meiner OPNSense Firewall die auf FreeBSD basiert ist das der Fall, weshalb ich es weiter unten ausprobiert habe.
Wenn ich die vorhandenen Informationen richtig deute, ist PVH der geplante Standard-Modus für DomU. Bis es soweit ist, sind allerdings noch ein paar Probleme zu lösen:
- PVGRUB funktioniert (derzeit) nicht im PVH Modus
- zum Starten der VM wird deren Kernel verwendet (bootloader='pygrub' oder kernel=<kernel> Option verwenden)
- der Kernel muss PVH unterstützen (Linux >= 4.11)
- PCI-Devices können (noch) nicht in die DomU gereicht werden
- Dom0 in PVH Mode ist ebenfalls (noch) experimentell und läuft noch nicht rund
xenproject.org:[13]
PVH technical Overview
|
Differences with PV
|
PVH Linux Konfiguration
Vorraussetzung ist einen Kernel der den PVH Modus unterstützt, wie Linux Kernel ab Version 4.11. Mein Owncloud Server auf Basis von Buster (Kernel 4.19) läuft in der DMZ stabil mit folgendem Standard Konfigurationsfile und pygrub als bootloader, damit ich mich nicht um den Kernel zum booten kümmern brauche:
name = 'owncloud' memory = 2560 cpu = '1-3' type = 'pvh' bootloader = 'pygrub' disk = [ 'phy:/dev/ssd/owncloud,xvda1,w', 'phy:/dev/ssd/owncloud_swap,xvdc,w', 'phy:/dev/ssd/owncloud-daten,xvdb1,w', ] vif = [ 'mac=00:16:3e:7b:04:05, bridge=br2dmz, script=vif-bridge_qlen' ] # set tx qlen 1000 on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'destroy'
PVH FreeBSD Konfiguration
Die Problematik liegt hier weniger bei dem PVH Modus selbst, sondern schlicht beim Mix aus Linux Dom0 und FreeBSD DomU. FreeBSD lässt sich derzeit im PVH Modus nur über den Kernel booten. Ich muss also zuerst den Kernel in die Dom0 kopieren, um ihn zum booten in der Dom 0 zu starten, ein Verfahren wie beim Bootloader pygrub. Diesen habe ich bisher leider nicht selbst dazu bewegen können, den FreeBSD Kernel und dessen Partition zu finden und zu starten. Ein manuelles Skript dazu wird deshalb weiter unten aufgezeigt. Grub(-XEN) unterstützt leider (warum eigentlich?) mit PV weder chainloading noch die kfreebsd option um FreeBSD zu starten.
Da im PVH Modus (derzeit) kein PCI-Device wie meine Netzwerkkarte in die DomU gereicht werden kann, werde ich die OPNSense Firewall trotzdem im PVHVM Modus betreiben. Unter Debian Buster (XEN 4.11) funktionieren virtuelle Netzwerkinterfaces problemlos. Auf meinem Testsystem mit Debian Bullseye (XEN 4.14) bekomme ich derzeit allerdings kein einziges Paket über die virtuelle Netzwerkschnittstelle übertragen, FreeBSD bzw. OPNSense deaktiviert das virtuelle Interface beim booten leider.
XEN OPNsense (FreeBSD) PVH Konfiguration:
name = 'opnsense' memory = 1536 cpus = '1-3' # PVH type = 'pvh' kernel = '/root/xen/kernel/opnsense/kernel' # load FreeBSD kernel direct extra = 'vfs.root.mountfrom=ufs:/dev/gpt/rootfs vfs.root.mountfrom.options=rw module_path="/boot/kernel;/boot/modules"' # oder ufs:/dev/ufs/OPNSense mit MBR Partitionierung # Disk disk = [ 'phy:/dev/vg/opnsense-disk,xvda,w' ] # Network vif = [ 'script=vif-bridge_TxOff' ] # OPNSense needs Tx off # Behavior on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'restart'
OPNSense bzw. die FreeBSD Firewall Implementierung PF (Paket Filter) benötigt folgende Anpassung der Netzwerkschnittstellen: Tx off.
Dafür verwende ich folgendes angepasstes vif-bridge_TxOff Skript (ethtool vorher installieren nicht vergessen):
#!/bin/bash #============================================================================ # ${XEN_SCRIPT_DIR}/vif-bridge_TxOff # # Script for configuring a vif in bridged mode. # # XEN default sets $vif txqueuelne 32 # correct this to default $vif txqueuelen 1000 # opnsense (freebsd) needs tx checksum off dir=$(dirname "$0") ip link set $vif qlen 1000 ethtool -K $vif tx off || /bin/true $dir/vif-bridge $@
Bei jedem OPNSense update mit einem neuem Kernel stehe ich also vor einem Problem, da OPNSense normalerweise direkt neu startet. Das wird sicher scheitern, da die Dom0 den neuen Kernel ja nicht starten kann, wenn er nicht vorher in die Dom0 kopiert wurde. Es sind zwei Lösungsansätze denkbar:
- Aus der DomU vor dem Reboot den aktualisierten Kernel in die Dom0 kopieren (lassen)
- In der Dom0 vor dem Starten der DomU den Kernel aus der DomU kopieren
Ich verwende erstmal folgenden Skript-basierten Ansatz um vor dem Start der VM den aktuellen Kernel in die Dom0 zu laden:
#!/bin/bash # # start OPNSense XEN domU in PVH mode # - get OPNSense kernel # - run PVH domU # # neobiker 2021-01-30 set -e # my VM VM=opnsense VM_CFG='' VM_DISK=/dev/mapper/vg-opnsense--disk VM_DISK_PART='3' # FreeBSD VM_FSTYPE=ufs VM_KERNEL=/boot/kernel/kernel # my personal XEN setup CONFIG_DIR=/root/xen KERNEL_DIR=${CONFIG_DIR}/kernel/${VM} # temporary mountpoint MOUNT_DIR=/run/xen/pvh_disk/${VM} case ${VM_FSTYPE} in ufs) mount_options='-r -t ufs -o ufstype=ufs2' ;; *) mount_options='' esac update_kernel () { echo "check kernel..." [ -d ${MOUNT_DIR} ] || mkdir -p ${MOUNT_DIR} [ -z "${VM_DISK_PART}" ] || kpartx -a ${VM_DISK} mount ${mount_options} ${VM_DISK}${VM_DISK_PART} ${MOUNT_DIR} [ -d ${KERNEL_DIR} ] || mkdir -p ${KERNEL_DIR} rsync ${MOUNT_DIR}${VM_KERNEL} ${KERNEL_DIR}/ umount ${MOUNT_DIR} [ -z "${VM_DISK_PART}" ] || kpartx -d ${VM_DISK} } update_kernel # xen: toolstack echo "start domU" xen create ${CONFIG_DIR}/${VM}${VM_CFG}
Das funktioniert soweit, ich kann OPNSense im PVH Modus starten.
Allerdings gibt es beim runterfahren ein lästiges Problem: Der OPNSense Kernel beendet die VM nicht vollständig, wartet am Ende auf einen Tastendruck, und xentop zeigt dabei 100% cpu load an :-(
... 2021-02-01T21:03:39.357188+00:00 OPNsense-trek.friedrichnet.de lighttpd 37923 - - (server.c.1971) server stopped by UID = 0 PID = 1 Waiting (max 60 seconds) for system process `vnlru' to stop... done Waiting (max 60 seconds) for system process `syncer' to stop... Syncing disks, vnodes remaining... 6 1 0 done Waiting (max 60 seconds) for system thread `bufdaemon' to stop... done Waiting (max 60 seconds) for system thread `bufspacedaemon-0' to stop... done All buffers synced. Uptime: 2m2s The operating system has halted. Please press any key to reboot. Rebooting... No known reset method worked, attempting CPU shutdown
PVH Dom0 Konfiguration
Xen Project 4.11 adds experimental PVH Dom0 support by calling Xen via dom0=pvh on the command line. Running a PVH Dom0 removes approximately 1 million lines of QEMU code from Xen Project’s computing base shrinking the attack surface of Xen Project based systems.
Enabling a PVH Dom0 requires a PVH Dom0 capable Linux or FreeBSD. Patches for each operating system are currently being upstreamed and should be available in the next Linux and FreeBSD versions.
/etc/default/grub.d/xen
GRUB_CMDLINE_XEN="dom0_mem=1536M,max:1536M dom0_max_vcpus=1-1 dom0_vcpus_pin dom0=pvh loglvl=all"
Debian 11 (Bullseye) Dom0 in PVH mode startet, XEN bringt aber noch einen Hinweis auf Experimental Mode. Ausserdem zeigt xentop eine Auslastung der Dom0 von 100% an, während auch top 65% anzeigt. Es zeigt sich, dass der PVH Modus der "neueste" Modus ist, der tatsächlich noch experimentellen Charakter aufweist und noch nicht überall reibnugsfrei funktioniert.
xen dmesg | grep PVH (XEN) Command line: placeholder dom0_mem=1536M,max:1536M dom0_max_vcpus=1-1 dom0_vcpus_pin dom0=pvh loglvl=all (XEN) WARNING: PVH is an experimantal mode with limited functionality dmesg | grep PVH [ 0.270978] Booting paravirtualized kernel on XEN PVH
XEN Stubdom
Eine Stub Domain ist eine PV DomU die nur einen bestimmten Zweck erfüllt: Sie stellt anderen Domains Ressourcen zur Verfügung, welches damit nicht mehr in der Dom0 erfolgen muss.
- Storage
- Network
- USB
- Graphic
Da sonst keine weiteren Aufgaben anfallen, ist kein komplettes Linux-System und auch kein vollständiger Kernel notwendig. Hierfür werden spezielle Kernel wie MiniOS verwendet: Er enthält im wesentlichen nur die notwendigen XEN-Treiber damit die zugehörige Domain Zugriff auf die oben genannten Ressourcen erhält. Die Domain selbst benutzt die XEN-Frontend Treiber, welche direkt mit dem XN-Backend in der Stubdom verbunden sind.
Einschub:
Für meine OPNsense Firewall welche in einer HVM DomU läuft würde sich für den Storage eine Stubdom anbieten. Das Netzwerk ist ja mit der nativ durchgereichten Netzwerkkarte über die PCI-Schnittstelle schon direkt in die DomU eingebunden. Im Verlauf der Testinstallation für diesen Artikel zeigte sich, dasss meine Entscheidung auf Debian Testing (Bullseye) mit XEN 4.14 zu setzen offensichtlich ein Fehler war: Ich bekam OPNSense zwar ordentlich gestartet, über das Netzwerkinterface floss allerdings kein einziges Byte, obwohl alle Schnittstellen up/running anzeigten. Ergo ging ich zurück zu Debian Stable (Buster) mit XEN 4.11. Damit erfolgte ebenfalls der Test des des PVH Modus, der ja ohne jegliche emulierten Ressourcen auskommt.
Die benötigten stubdom Binaries sind unter Debian derzeit leider nicht zu finden. Ich versuche diese aus den XEN Sourcen selbst zu installieren, oder aus den Debian Paket zu erstellen.
Stubdom Konfiguration
Aktuelle Informationen und Beispiele zur Konfiguration von Stub Domains habe ich nicht wirklich finden können. Beispiele die unter dem früheren Toolstack xm mit XEN 3 verwendet wurden sind inzwischen sehr veraltet.
Die Instantiierung der HVM erfolgt derart, dass sämtliche Ressourcen aus der HVM-Konfiguration in die Stubdom verlagert werden. Ein Extra-Eintrag teilt dem XEN Toolstack xl mit dass die HVM-DomU eine Stub Domain beim Start verwenden soll, anstatt das QEMU Device-Model der DomU direkt in der Dom0 zu starten.
HVM-Konfiguration 'opnsense zur Verwendung eine stubdom:
name = 'opnsensee' memory = 1536 # HVM type = 'hvm' # use Stubdom device_model_stubdomain_override = 1 # Block device(s) for target domain disk = [ 'phy:/dev/vm/opnsense-disk,xvda,w', #'file:/root/xen/iso/OPNsense-20.7-OpenSSL-dvd-amd64.iso,xvdb:cdrom,r' ] # Network device(s) for target domain vif = [ 'script=vif-bridge_TxOff' ] keymap = 'de' vnc = 1 vnclisten = '0.0.0.0' vncpasswd = ''
Der Start der VM erfolgt ganz normal, die stubdom wird automatisch gestartet.
xl create opnsense
Leider beenden sich beide domu sofort nach dem Start. Auch die originalen aus den XEN Sourcen kompilierte Pakete zeigen das gleiche Verhalten.
Das Thema HVM-Stubdom lege ich jetzt erstmal auf Eis. Ich werde mich wegen meiner OPNSense HVM jetzt mit dem PVH Modus beschäftigen, der einen optimalen Hybriden aus HVM und PV implementiert. FreeBSD unterstützt diesen Mode, das Ergebnis ist oben dokumentiert.
XEN Stubdomain installieren
Als erste XEN VM richte ich mir deshalb gleich ein Debian System ein, mit dem ich die fehlenden Dateien erstellen möchte.
xen-create-image --hostname bullseye --dist bullseye --vifname=vif_bullseye --bridge=br_lan --dhcp
Als erstes versuche ich die Installation anhand der Debian Sourcen:
apt-get install build-essentials devscripts apt-get source xen apt-get build-dep xen cd xen-4.14.* # edit debian/rules >>> enable-stubdom, disable-xen, disable-tools, disable-docs debuild -b -us -uc make dist-stubdom # doesn't help: see changelog changelog: * Document that ioemu is currently unsupported. (closes: #536175) changelog: * Remove ioemu for now. (closes: #490409, #496367)
In Debian sind die notwendigen Pakete leider explizit deaktiviert worden.
Also gehe ich zu den originalen XEN Sourcen der unter Debian vrewendeten Version über:
# Sourcen für XEN 4.14.1 (Debian Bullseye verwendet xen 4.14.1) wget https://downloads.xenproject.org/release/xen/4.14.1/xen-4.14.1.tar.gz tar xvzf xen-4.14.1.tar.gz cd xen-4.14.1 # apply a patch (Compile Error), see below # this is catched from debian/rules export DEB_HOST_MULTIARCH=x86_64-linux-gnu ./configure --prefix=/usr --includedir=/usr/include --libdir=/usr/lib/$DEB_HOST_MULTIARCH --with-libexec-libdir-suffix=/$DEB_HOST_MULTIARCH --host=$DEB_HOST_MULTIARCH --mandir=/usr/share/man --infodir=/usr/share/info --sysconfdir=/etc --localstatedir=/var --with-libexec-leaf-dir=xen-4.14 --disable-blktap1 --disable-blktap2 --disable-rombios --with-system-qemu=/usr/bin/qemu-system-i386 --enable-ovmf --with-system-ovmf=/usr/share/ovmf/OVMF.fd --with-system-seabios=/usr/share/seabios/bios-256k.bin make dist-stubdom
Das kompilieren des Paketes stubdom war hier jedenfalls möglich. Natürlich kann es jetzt aufgrund fehlender Anpassungn an die XEN Installation unter Debian zu Fehlern oder auch prinzipiell zu unerwünschten Nebeneffekten oder Instabilitäten kommen.
Evtl. treten Fehler bei der Kompilation eines Treibers auf, die sich wie folgt beheben lassen:
# --------------------------------- # läuft auf Fehler beim Kompilieren eines (nicht notwendigen) Treibers # fix: # im File tools/firmware/etherboot/ipxe/src/ininiband/flexboot.c in den Zeilen 368 und 409 jeweils # den korrekten Typ vor dem Parameter qp->type einfügen: (nodnic_queue_pair_type) # :368 ... (nodnic_queue_pair_type)qp->type ... # :409 ... (nodnic_queue_pair_type)qp->type ... diff flexboot_nodnic.c.orig flexboot_nodnic.c 368c368 < status = nodnic_port_create_qp(&port->port_priv, qp->type, --- > status = nodnic_port_create_qp(&port->port_priv, (nodnic_queue_pair_type)qp->type, 409c409 < nodnic_port_destroy_qp(&port->port_priv, qp->type, --- > nodnic_port_destroy_qp(&port->port_priv, (nodnic_queue_pair_type)qp->type, # ----------------------------------
Das fehlende File ioemu-stubdom.gz konnte ich so erstellen und in die Dom0 kopieren, zusammen mit einigen anderen Dateien. Auch die benötigte Device-Modell Datei qemu-dm wurde gebaut.
Stubdom Dokumentation
Die Manpage und Dokumentation lassen eine Beispielkonfiguration vermisssen.
Toolstack to MiniOS ioemu stubdomain protocol --------------------------------------------- This section describe communication protocol between toolstack and qemu-traditional running in MiniOS stubdomain. The protocol include expectations of both qemu and stubdomain itself. Setup (done by toolstack, expected by stubdomain): - Block devices for target domain are connected as PV disks to stubdomain, according to configuration order, starting with xvda - Network devices for target domain are connected as PV nics to stubdomain, according to configuration order, starting with 0 - if graphics output is expected, VFB and VKB devices are set for stubdomain (its backend is responsible for exposing them using appropriate protocol like VNC or Spice) - QEMU command line (space separated arguments) is stored in /vm/<target-uuid>/image/dmargs xenstore path ?? - bios type is stored in /local/domain/<target-id>/hvmloader/bios - stubdomain's console 0 is connected to qemu log file - stubdomain's console 1 is connected to qemu save file (for saving state) - stubdomain's console 2 is connected to qemu save file (for restoring state) - next consoles are connected according to target guest's serial console configuration Startup: 1. PV stubdomain is started with ioemu-stubdom.gz kernel and no initrd 2. stubdomain initialize relevant devices 3. stubdomain signal readiness by writing "running" to /local/domain/<stubdom-id>/device-model/<target-id>/state xenstore path 4. now stubdomain is considered running man xl.cfg ... Device-Model Options The following options control the selection of the device-model. This is the component which provides emulation of the virtual devices to an HVM guest. For a PV guest a device-model is sometimes used to provide backends for certain PV devices (most usually a virtual framebuffer device). device_model_version="DEVICE-MODEL" Selects which variant of the device-model should be used for this guest. Valid values are: qemu-xen Use the device-model merged into the upstream QEMU project. This device-model is the default for Linux dom0. qemu-xen-traditional Use the device-model based upon the historical Xen fork of QEMU. This device-model is still the default for NetBSD dom0. It is recommended to accept the default value for new guests. If you have existing guests then, depending on the nature of the guest Operating System, you may wish to force them to use the device model which they were installed with. device_model_override="PATH" Override the path to the binary to be used as the device-model running in toolstack domain. The binary provided here MUST be consistent with the device_model_version which you have specified. You should not normally need to specify this option. stubdomain_kernel="PATH" Override the path to the kernel image used as device-model stubdomain. The binary provided here MUST be consistent with the device_model_version which you have specified. In case of qemu-xen-traditional it is expected to be MiniOS-based stubdomain image, in case of qemu-xen it is expected to be Linux-based stubdomain kernel. stubdomain_ramdisk="PATH" Override the path to the ramdisk image used as device-model stubdomain. The binary provided here is to be used by a kernel pointed by stubdomain_kernel. It is known to be used only by Linux-based stubdomain kernel. stubdomain_memory=MBYTES Start the stubdomain with MBYTES megabytes of RAM. Default is 128. device_model_stubdomain_override=BOOLEAN Override the use of stubdomain based device-model. Normally this will be automatically selected based upon the other features and options y device_model_args_hvm=[ "ARG", "ARG", ...]
XAPI
Ein Toolstack für XEN der leistungsfähiger als xl ist und innerhalb von Cloud-Lösungen und dem XCP-ng Server verwendet wird.
XCP-ng
Freier Nachfolger des früheren XEN- bzw. Citrix Server.
Qubes OS
Qubes OS treibt die Ansätze zur Disaggregation und Sicherheit auf die Spitze und hat ein maximal sicheres und freies Betriebssystem auf XEN Basis erstellt (empfohlen und genutzt z.B. von Edward Snowden), indem sie nicht jeweils ein ganzes System virtualisieren, sondern sogar die einzelnen Applikationen darin. So gibt es beispielsweise einen Browser in einer "privaten" Umgebung, einen Browser in einer "Arbeit" Umgebung und evtl. noch einen separaten in einer "Banking" Umgebung. Trotzdem kann der Anwender zwischen diesen unterschiedlichen Umgebungen Daten austauschen, z.B. sind Copy+Paste möglich.
Verweise
Grafik: XEN Disaggregation (Quelle: XEN.Org)
- ↑ https://wiki.xenproject.org/wiki/Dom0_Kernels_for_Xen
- ↑ https://wiki.xenproject.org/wiki/Xen_Project_Software_Overview
- ↑ https://wiki.xenproject.org/wiki/Driver_Domain
- ↑ https://wiki.xenproject.org/wiki/Dom0_Disaggregation
- ↑ https://wiki.xenproject.org/wiki/Xen_Project_Software_Overview#PVH_.28x86.29
- ↑ https://xenproject.org/developers/teams/xcp-ng/
- ↑ https://wiki.xenproject.org/wiki/Category:Embedded_and_Automotive
- ↑ https://wiki.xenproject.org/wiki/MirageOS
- ↑ https://wiki.xenproject.org/wiki/Category:Unikraft
- ↑ https://www.qubes-os.org/
- ↑ https://wiki.xenproject.org/wiki/Understanding_the_Virtualization_Spectrum
- ↑ https://wiki.xenproject.org/wiki/PV_on_HVM
- ↑ https://xenbits.xen.org/people/royger/fosdem2014.pdf