» Virtualisierung mit KVM und virtuelle Netzwerke mit VDE
» November 20, 2012 | german linux network | Adrian Kummerländer
Ich spiele in meiner Freizeit gerne mit verschiedenen neuen Datenbank-Systemen, Sprachen und Frameworks - passe ich dabei nicht penibel auf, entsteht schnell ein Gewirr aus Konfigurations-Dateien und einmal installierten Paketen, die gar nicht mehr verwendet werden. Das System fühlt sich mit der Zeit also etwas ungut und zugemüllt an.
Bis jetzt versuche ich zumindest größere Entwicklungen in eigenen VMs abzugrenzen, ganz einheitlich bin ich dabei wegen einigen störenden Punkten aber nicht. Zum einen ist die Verwaltung der Netzanbindung verschiedener VMs über die im Arch-Wiki beschriebene Behelfsmethode mit SSH-Tunneln alles andere als schön, zum anderen will ich nicht für jede VM ein eigenes Fenster mit Konsole rumfliegen haben. Was ich will, ist also eine “richtige” Netzwerk-Konfiguration über virtuelle Interfaces und einen Betrieb der VMs ohne grafische Oberfläche als Daemon im Hintergrund.
Als Virtualisierungs-System setze ich auf KVM, die Distribution der Wahl ist weiterhin ArchLinux.
Kernel Based Virtual Machine
KVM ist das direkt im Linux-Kernel integrierte Virtualisierung-System. Einzige Voraussetzung dafür ist ein Prozessor mit Virtualisierungs-Funktionen, diese sollten die meisten der in den letzten Jahren auf den Markt gekommenen Prozessoren besitzen - selbst mein Core Duo aus 2007 führt KVM einwandfrei aus. Ansonsten verhält sich KVM identisch zu QEMU, der einzige Unterschied ist, dass der Prozessor nicht wie bei QEMU komplett emuliert wird, sondern die Befehle über den Kernel an den physikalischen Prozessor durchgereicht werden. Dies hat den Nachteil, dass KVM z.B. keine ARM-Plattformen unter x86 ausführen kann, der große Vorteil ist jedoch die gute Performance. Es übertrifft bei mir - gefühlsmäßig, ich habe keine Benchmarks durchgeführt - ohne Probleme sowohl VirtualBox als auch VMware.
Ein Vorteil aus der vollständigen Integration der KVM in den Kernel ist es, dass sich auch ganz normale Block-Geräte wie Festplatten-Partitionen etc. ohne Anpassung verwenden lassen. Dadurch kann ich ohne Probleme z.B. ein auf einer zweiten Host-Partition installiertes Betriebssystem im laufenden Linux-Betrieb “dazubooten” und nutzen.
Angesteuert wird die KVM wahlweise über qemu-kvm
oder qemu --enable-kvm
. Damit das funktioniert müssen jedoch die Kernel-Module kvm
und kvm_intel
bzw. kvm_amd
geladen werden. Die grundlegende Verwendung abseits des anderen Befehls ist gleich wie bei QEMU. So werden Image-Dateien für die Gast-Systeme mit qemu-img
erstellt und auch Einstellungen zur Hardware des Gast-Systems werden auf die gleiche Weise gesetzt. Aus diesem Grund gehe ich hier auch nicht näher auf die grundlegende Verwendung ein, Details lassen sich bei Bedarf im Arch-Wiki nachlesen.
Hier als Beispiel mein derzeitiger Standardaufruf von KVM, der für alle VMs gleich ist. Dynamisch ist allein das zu verwendende Speicher-Gerät - in meinem Fall verschiedene Image-Dateien.
qemu-kvm -cpu host -hda $1 -m 1024 -daemonize -vnc none -usb -net nic -net vde
Dieser verwendet das als erster Parameter übergebene Gerät als Festplatte und setzt neben den nötigen Netzwerk-Einstellungen die VM mittels -daemonize
in den Hintergrund. Falls benötigt, kann als Wert des Parameters -vnc
auch eine von einem Doppelpunkt angeführte Zahl übergeben werden um die Grafik-Ausgabe der VM an einen VNC-Server anzubinden (z.B. -vnc :1
für 127.0.0.1:1
). Diese Funktion verwende ich nicht, da ich ausschließlich über das interne Netzwerk die im Gast installierten Dienste nutze und administrative Tätigkeiten immer über SSH durchführe.
Netzwerken mit VDE
VDE steht für Virtual Distributed Ethernet und ermöglicht genau das was der Name erahnen lässt: Virtuelle Switches die beispielsweise VMs in einem Host internen LAN verbinden können.
Meine Konfiguration hält sich dabei im wesentlichen an den Vorschlag im englischen Arch-Wiki, welchen ich in ein einfaches Script verpackt habe:
#!/bin/sh case "$1" in start) ip tuntap add tap0 mode tap vde_switch -tap tap0 -daemon -pidfile .switch.pid -mod 660 -group kvm ip addr add dev tap0 192.168.100.254/24 ip link set dev tap0 up ;; stop) kill -9 `cat .switch.pid` rm .switch.pid ip tuntap del tap0 mode tap ;; esac
Dieses Script erzeugt ein virtuelles Interface tap0
und verbindet ein neues, als Daemon im Hintergrund laufendes, virtuelles Switch mit diesem. Als nächstes wird dann noch eine statische IP Konfiguration für das virtuelle Interface definiert. Durch diese können alle mit -net nic -net vde
Parametern gestarteten KVM Gäste über die IP 192.168.100.254
auf den Host zugreifen.
In den Gast-Systemen selbst muss zusätzlich eine statische IP Konfiguration vorgenommen werden:
interface=eth0 address=192.168.100.1 netmask=255.255.255.0 broadcast=192.168.100.255 gateway=192.168.100.254
Um das interne virtuelle LAN bei Bedarf mit der Außenwelt zu verbinden gibt es ebenfalls ein kleines Script welches die nötige Route erzeugt bzw. löscht:
#!/bin/sh case "$1" in start) echo "1" > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o $2 -j MASQUERADE ;; stop) iptables -t nat -X echo "0" > /proc/sys/net/ipv4/ip_forward ;; esac
Anpassbar ist hierbei das Interface, um z.B. daheim eth0
und unterwegs wahlweise wlan0
oder usb0
verwenden zu können.
KVM Hardware Error
Nach einer Kernel Aktualisierung im ArchLinux Gast-System, kam es beim Neustart plötzlich zu dieser etwas erschreckenden Meldung:
KVM: entry failed, hardware error 0x80000021 If you're running a guest on an Intel machine without unrestricted mode support, the failure can be most likely due to the guest entering an invalid state for Intel VT. For example, the guest maybe running in big real mode which is not supported on less recent Intel processors. EAX=00000000 EBX=0020fa5c ECX=00000000 EDX=fffff000 ESI=f6d29014 EDI=00000001 EBP=f6461fa0 ESP=f6461f60 EIP=c0128443 EFL=00010246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0 ES =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA] CS =0060 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA] SS =0068 00000000 ffffffff 00c09300 DPL=0 DS [-WA] DS =007b 00000000 ffffffff 00c0f300 DPL=3 DS [-WA] FS =00d8 36648000 ffffffff 00809300 DPL=0 DS16 [-WA] GS =00e0 f6d2f540 00000018 00409100 DPL=0 DS [--A] LDT=0000 ffff0000 f0000fff 00f0ff00 DPL=3 CS64 [CRA] TR =0080 f6d2d3c0 0000206b 00008b00 DPL=0 TSS32-busy GDT= f6d28000 000000ff IDT= c060b000 000007ff CR0=8005003b CR2=ffffffff CR3=006ef000 CR4=000006d0 DR0=0000000000000000 DR1=0000000000000000 DR2=0000000700000000 DR3=0000000000000000 DR6=00000000ffff0ff0 DR7=0000000000000400 EFER=0000000000000000 Code=00 8b 15 c4 b5 61 c0 55 89 e5 5d 8d 84 10 00 c0 ff ff 8b 00 <c3> 8d b6 00 00 00 00 8d bf 00 00 00 00 8b 15 a0 ae 61 c0 55 89 e5 53 89 c3 b8 30 00 00 00
Dies sah für mich im ersten Moment wie ein klarer Hardware-Fehler aus, alle Informationen die sich über meine bevorzugte Suchmaschine finden ließen, waren jedoch für andere Situationen und ältere Kernel Versionen als 3.6.6-1
. Nach Tests mit verschiedenen Parametern für die zuständigen Kernel-Module, funktionierte es schließlich nach Laden des Moduls mit folgendem Befehl wieder einwandfrei:
modprobe kvm_intel emulate_invalid_guest_state=0
Um den emulate_invalid_guest_state
Parameter dauerhaft zu setzen reicht ein Eintrag in /etc/modprobe.d
.
Fazit
Mithilfe der beschriebenen Konfiguration und den Scripts lassen sich KVM VMs unsichtbar im Hintergrund starten und in einem Host-internen virtuellen LAN ansteuern. Bei Bedarf kann dieses virtuelle Netz mithilfe von Routen erweitert werden. Für den Netzzugriff in den Gast-Systemen reicht eine einfache statische Konfiguration.
Ich werde das Ganze in nächster Zeit vermutlich noch etwas erweitern und verbessern, aber diese Grundlage ist auf jeden Fall besser als die von mir am Anfang genutzten SSH-Tunnel zwischen Gast und Host.
Das Erstellen einer neuen VM benötigt jetzt nicht viel mehr als eine Kopie eines Muster-Images und eine Anpassung der statischen IP Konfiguration - mit zusätzlichen Scripts könnte ich mir auch eine einfache, selbstgebaute Variante von Vagrant auf KVM Basis vorstellen. Wobei auch dort, durch die Einführung einer neuen Abstraktionsschicht, die Unterstützung von KVM als Alternative zu VirtualBox ein Stück näher gerückt sein dürfte.