Qemu im Test
Intention
Getestet werden sollte qemu als freie Virtualisierungssoftware unter Linux.
Warum jetzt noch qemu? Weil sich die erzeugten Gast-Images unmittelbar in KVM einsetzen lassen - aber gerade kein freier Rechner zur Verfügung stand, der die Hardware-Anforderungen von KVM erfüllt (da KVM einen neueren Intel-/AMD-Prozessor benötigt, der über Virtualisierungsfähigkeiten verfügt).
Und um die Zukunft von XEN im Zusammenhang mit dem Linux-Kernel scheint es derzeit etwas Querelen zu geben (http://www.heise.de/open/Kernel-Log-Morton-stellt-Aufnahme-des-Xen-Dom0-Codes-in-Frage-Dateisysteme-fuer-SSDs--/artikel/134016).
Der Text im weiteren ist noch nicht fertig, es handelt sich derzeit nur um unvollständige Notizen. Daher erhebt er weder Anspruch auf Vollständig- noch auf Richtigkeit.
Installation
Günstig ist die Benutzung der Debian-Netinstall-CD. Diese ist relativ klein (für Debian 5.0 ca. 130MB in der i386-Version). Man kann das Image sie unter http://www.debian.org/distrib/netinst herunterladen und mit vermutlich jedem aktuellen CD-Brennprogramm auf CD bannen. Voraussetzung für die weitere Installation ist natürlich dann ein Zugriff auf ein Debian-Repository über das Netzwerk, wer also nur eine langsame oder gar keine Verbindung dorthin hat, muss sich eine Debian-Komplett-DVD besorgen und damit die Installation durchführen.
Mit dieser CD starten wir den blanken Rechner und installieren erst mal alles mit den Standard-Einstellungen (sofern nicht individuelle Anpassungen z.B. fürs Netzwerk nötig sind). Nur die tasksel-Konfiguration machen wir komplett leer (per default ist dort "Standard" angekreuzt, auch das nehmen wir heraus).
Die Plattenaufteilung ist Geschmackssache, spielt für den weiteren Betrieb auch keine besondere Rolle, da qemu ohnehin mit ganz normalen Dateien im Filesystem arbeitet. Es sollte nur auf der Partition, die das Start-Betriebssystem enthält, ausreichend Platz sein, um dieses und spätere Aktualisierungen ordentlich unterzubringen. Da bei heutigen Plattengrößen das nicht mehr wirklich eine Rolle spielt, kann man z.B. mit 10 oder 20GB (oder mehr) arbeiten. Man kann auch die Option "Guided Partioning" wählen, da wird im wesentlichen alles automatisch ausgewählt.
Im Ergebnis haben wir jetzt eine ziemlich kleine Debian-Installation.
Zu dieser Installation fügen wir jetzt noch hinzu:
- wenn wir Installation und Konfiguration über den Rechner selbst machen wollen: ein X mit den erforderlichen Softwarepaketen (hier im Beispiel: kde mit allen Abhängigkeiten)
- das Paket qemu
- empfehlenswert, aber für die Installation nicht relevant: smartmontools
Die Pakete können bei Debian über
apt-get install kde qemu
installiert werden. Wenn wir NICHT über X arbeiten wollen, sondern über VNC, dann genügt uns das SDL-Paket
Jetzt haben wir alles, was wir für qemu brauchen. Ein Neustart zum Abschluss zeigt uns dann noch, ob wirklich alles funktioniert und führt uns, wenn alles in Ordnung ist, ins KDE, bei welchem wir uns mit dem Nicht-root-Benutzer, der bei der Installation angelegt wurde, anmelden können. Falls wir uns auch als root anmelden dürfen wollen, müssen wir die Datei /etc/kde3/kdm/kdmrc editieren und dort die Zeile
AllowRootLogin=False
in
AllowRootLogin=True
ändern.
Erster Test von qemu
Nachdem wir alles installiert haben, testen wir die Sache einfach mal. Wir definieren uns ein Verzeichnis, in welches wir die Gast-Images legen. Im folgenden ist das einfach /var/local
Mit dem Befehl
qemu-img create -f qcow2 /var/local/debian1.img 4000M
erzeugen wir ein Harddisk-Image mit einer Größe von 4000 MBytes im Format qcow2. Mit qcow2 wird versucht, die Imagegröße immer möglichst klein zu halten. Nicht wundern also, wenn nach dem o.g. Befehl nur ein Image von ein paar KBytes entsteht. Dementsprechend schnell ist das Image auch erzeugt.
Mit
qemu -hda /var/local/debian1.img -cdrom /dev/cdrom -boot d -no-acpi
starten wir unser neues Image in einem neuen Fenster, das von qemu geöffnet wird. Beim Start des Images sehen wir den virtuellen PC, welcher dann (aufgrund des Parameters -boot d) versucht, vom CD-Laufwerk zu booten. Liegt im CD-Laufwerk unsere ganz am Anfang erstellte Debian-Netinstall-CD, wird die Installation auf genau die gleiche Weise gestartet, wie wir es zu Beginn erlebt haben. Im weiteren Verlauf sollten wir eigentlich in der Lage sein, in der virtuellen Umgebung eine komplette Debian-Installation durchzuführen.
Der Parameter "-no-acpi" ist für einige Gastsysteme erforderlich, hier muss man ggf. experimentieren. Ich habe es z.B. nicht geschafft, Openfiler von der Original-CD zu installieren, ohne "-no-acpi" gesetzt zu haben.
Wer es ganz eilig hat oder sofort sehen will, ob seine qemu-Installation funktioniert, kann auch fertige Disk-Images erhalten, und zwar über den Link http://www.nongnu.org/qemu/download.html. Dort findet sich unter anderem auch ein i386-Linux-Image. Das kann man sich einfach z.B. auch unter /var/local ablegen und aufrufen, dann allerdings NICHT mit der oben genannten Kommandozeile, sondern über
qemu -hda /var/local/<imagename> -cdrom /dev/cdrom -no-acpi
wobei <imagename> durch den Namen des heruntergeladenen Images zu ersetzen ist.
Diese Zeile gilt natürlich auch für den Einsatz unseres selbst erzeugten Images debian1.img.
Auf keinen Fall darf hier natürlich noch das "-boot d" enthalten sein, allenfalls ein "-boot a" (das aber dem Default entspricht), denn sonst versucht unser Image wieder von CD zu booten. Wenn keine CD eingelegt ist, dann kann auch nicht gebootet werden.
Die weiteren Parameter für den qemu-Aufruf finden sich in der qemu-Dokumentation unter http://www.nongnu.org/qemu/qemu-doc.html#SEC10.
Vereinfachen lässt sich die Bedienung mit Programmen wie qtemu und qemu-launcher. qtemu hat allerdings die Nachteile:
- man kann in der Konfiguration nur neue Images erstellen, aber keine vorhandenen einbinden. Das geht nur manuell "hintenherum".
- erstellte Images sind immer im raw-Format, es besteht keine Auswahl z.B. von qcow2
- kqemu wird nicht berücksichtigt
- eine Bedienung des qemu-Monitors von qtemu aus ist nicht möglich
qemu-launcher bietet im Zusammenspiel mit qemuctl eine recht gute Möglichkeit für den Start/Stop/Suspend/Resume und die Konfiguration von Gast-Images.
Qemu im Netzwerk
Die Konfiguration von qemu fürs Netzwerk ist eigentlich simpel, da es sich selbst mit internen IP-Adressen versorgt. Mit dem Parameter "-net nic,vlan=0" wird dem Gast eine Netzwerkkarte (NE2000 PCI) zugewiesen.
Häufig wird es aber so sein, dass man mehrere qemu-Session gleichzeitig betreibt und diese jeweils IP-Adressen bekommen sollen, unter denen die Gäste dann auch erreichbar sein sollen. Das funktioniert am besten über Bridging des Netzwerkinterfaces des Hosts zu den virtuellen Netzwerkkarten sowie zur physischen Netzwerkkarte. Dazu ist zunächst in der Datei /etc/network/interfaces die physische Netzwerkkarte auszukommentieren. Anstelle der physischen Netzwerkkarte wird ein Bridge-Interface eingeführt, welches per default erst einmal die physische Netzwerkkarte bedient.
#auto eth0
#iface eth0 inet static
# address 10.1.1.2
# network 10.1.1.0
# netmask 255.255.255.0
# broadcast 10.1.1.255
# gateway 10.1.1.1
auto br0
iface br0 inet static
address 10.1.1.2
network 10.1.1.0
netmask 255.255.255.0
broadcast 10.1.1.255
gateway 10.1.1.1
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off
Bei einem Neustart des Rechners sehen wir, dass das Bridge-Interface initialisiert wird. Mit ifconfig sieht man die neue Konfiguration des Netzwerks:
qemutest:/var/local# ifconfig
br0 Link encap:Ethernet HWaddr 00:60:08:6a:33:4d
inet addr:10.1.1.2 Bcast:10.1.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2835176 errors:0 dropped:0 overruns:0 frame:0
TX packets:4239402 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:447734595 (426.9 MiB) TX bytes:1151708996 (1.0 GiB)
eth0 Link encap:Ethernet HWaddr 00:60:08:6a:33:4d
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2835074 errors:0 dropped:0 overruns:0 frame:0
TX packets:4240094 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:487438184 (464.8 MiB) TX bytes:1151765134 (1.0 GiB)
Interrupt:11 Base address:0xb000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:149 errors:0 dropped:0 overruns:0 frame:0
TX packets:149 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:8676 (8.4 KiB) TX bytes:8676 (8.4 KiB)
Jetzt müssen wir noch qemu diese Änderungen beibringen. Dazu ändern wir die Datei /etc/qemu-ifup folgendermaßen:
#!/bin/sh
#sudo -p "Password for $0:" /sbin/ifconfig $1 172.20.0.1
sudo -p "Password for $0:" /sbin/ifconfig $1 0.0.0.0 promisc up
sudo -p "Password for $0:" /usr/sbin/brctl addif br0 $1
Das Programm /usr/sbin/brctl bekommen wir aus dem Paket bridge-utils, welches wir uns wieder mit "apt-get install bridge-utils" installieren.
Beim Aufrufen der Gäste ist es jetzt wichtig, dass diese separate virtuelle Netzwerkkarten bekommen, damit sie im Netzwerk auch wirklich unterscheidbar sind. Das geschieht durch die Benutzung des "macaddr"-Parameters, bei welchem dem Aufrufparameter "-net nic,..." gesagt wird, welche MAC-Adresse (also welche physische Kartenadresse) der Netzwerkkarte zugewiesen wird. Normalerweise sollen MAC-Adressen nur ein einziges Mal in der Welt existieren - da die MAC-Adresse aber ohnehin nur bis zum nächsten Router benutzt wird, genügt es im Normalfall, wenn wir uns unsere eigene Liste verwendeter MAC-Adressen merken. Wichtig: Die ersten Stellen sollten nicht verändert werden, da sie den Hersteller der Karte angeben. Wenn wir für die ersten Stellen z.B. "00:60" benutzen, könnte es sein (auch wenn es unwahrscheinlich ist), dass wir in Konflikt mit einer 3COM-Netzwerkkarte geraten, die die gleiche MAC-Adresse besitzt.
Von qemu wird als Standard-MAC-Adresse benutzt: 52:54:00:12:34:56. Diese können wir unserem ersten qemu-Gast zuweisen. Dem nächsten können wir z.B. die MAC-Adresse 52:54:00:12:34:57 geben. Die MAC-Adressen werden übrigens hexadezimal notiert, nach der 59 kommt also nicht die 60, sondern die 6A.
Dementsprechend lautet der Aufruf für unseren ersten qemu-Gast:
qemu -hda /var/local/<imagename> -cdrom /dev/cdrom -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -no-acpi
für unseren zweiten Gast dann:
qemu -hda /var/local/<imagename> -cdrom /dev/cdrom -net nic,vlan=0,macaddr=52:54:00:12:34:57 -net tap,vlan=0,ifname=tap1 -no-acpi
Das Gastsystem kann jetzt jeweils separat konfiguriert werden - ebenso wie für die MAC-Adresse gilt aber natürlich auch für die IP-Adressen, dass man sich hier eine Liste machen muss, um Überschneidungen zu verhindern.
Beispiel für zwei Openfiler-Gastsysteme, hier erfolgt die IP-Konfiguration in der Datei /etc/sysconfig/network-scripts/ifcfg-eth0:
Gast 1:
DEVICE=eth0
IPADDR=10.1.1.2
NETMASK=255.255.255.0
NETWORK=10.1.1.0
BROADCAST=255.255.255.255
GATEWAY=10.1.1.1
ONBOOT=yes
TYPE=Ethernet
HWADDR=52:54:00:12:34:56
Gast 2:
DEVICE=eth0
IPADDR=10.1.1.3
NETMASK=255.255.255.0
NETWORK=10.1.1.0
BROADCAST=255.255.255.255
GATEWAY=10.1.1.1
ONBOOT=yes
TYPE=Ethernet
HWADDR=52:54:00:12:34:57
Sobald die Gastsysteme mit dieser Konfiguration gestartet wurden, können wir sie von irgendeinem anderen Rechner im Netzwerk anpingen. Auf diesem Rechner können wir dann auch gleich anhand der ARP-Tabelle sehen, dass die MAC-Adressen passend zugeordnet wurden:
remotehost:~#arp -a
? (10.1.1.2) at 52:54:00:12:34:56 [ether] on eth0
? (10.1.1.3) at 52:54:00:12:34:57 [ether] on eth0
? (10.1.1.5) at 00:60:08:6A:33:4D [ether] on eth0
Die letzte Zeile gehört dabei zu unserem Host, hier sehen wir die MAC-Adresse der physischen Netzwerkkarte (eine 3COM 3c905 Boomerang), diese haben wir bereits weiter oben beim "ifconfig" gesehen.
Fazit
Man sollte keine Wunder von der Virtualisierung erwarten. Ein virtueller Rechner kann nie so schnell laufen wie sein Host.
Insgesamt läuft qemu ordentlich, benötigt allerdings auch etliches an CPU-Leistung. Eine Installation eines Debian-Systems in einem qemu-PC benötigt das Mehrfache an Zeit gegenüber der Installation auf seinem Host.
Auch Plattenzugriffe sind deutlich langsamer.
Auf dem Testsystem brachte hdparm auf dem Hostsystem auf einer nicht mehr ganz taufrischen PATA-Platte eine Übertragungsrate von 28,3 MB/s.
Das Debian-Gastsystem brachte es nur noch auf ca. 3,8 MB/s.
Beschleunigung mit kqemu
Die Geschwindigkeit von qemu ohne Beschleuniger ist, mit Verlaub, nicht erträglich. Ein 386er erscheint einem da als Rennpferd.
Abhilfe verschafft kqemu. Nachteil: kqemu ist ein Kernel-Modul, welches standardmäßig nicht im Kernel enthalten ist - und damit auch nicht in den fertigen Kernel-Paketen von Debian. Damit muss man sich einen eigenen Kernel nebst kqemu-Modul übersetzen. Kenntnisse im Konfigurieren, Übersetzen und Einbinden eigener Kernel sind damit auf jeden Fall erforderlich.
Problem ist, dass sich der kqemu-Source zwar unter der stable Release problemlos übersetzen und das Modul sich auch ohne weiteres laden lässt. Das böse Erwachen gibt es, wenn qemu zum ersten Mal mit dem Parameter "-kernel-kqemu" aufgerufen wird. Das Gastsystem beginnt nämlich zu booten, nach kurzer Zeit endet das aber mit einem Kernel-panic-Error des Gastsystems. Ursache ist offenbar, dass sich das fertige qemu und das selbst übersetzte kqemu nicht miteinander vertragen. Man würde jetzt zwar normalerweise einfach aus den qemu-Sourcen ein neues qemu übersetzen, aber das scheitert daran, dass sich diese mit dem gcc aus der stable Release nicht übersetzen lassen - mindestens die Version 0.9x von qemu lässt sich nämlich nicht mit dem gcc 4.x übersetzen.
Auch hier gibt es Abhilfe - nämlich die Benutzung der unstable Release. Dazu ändern wir in der Datei /etc/apt/sources.list bei den beiden Zeilen für das main-Paket den "lenny" durch "unstable" und führen danach ein
apt-get update
aus.
Was brauchen wir jetzt? Neben den Kernel-Sourcen, den Übersetzungswerkzeugen und den kqemu-Sourcen brauchen wir noch einige Hilfsprogramme, die in unserer bisherigen Installation nicht enthalten sind. Wir können das erledigen mit:
apt-get install linux-source-2.6.28 kernel-package bzip2 libncurses-dev ncurses-dev zlib1g-dev kqemu-common kqemu-source
Die Sources sind damit zwar auf der Platte, aber noch in gepackter Form. Wir entpacken sie mit
cd /usr/src
tar -xjvf linux-source-2.6.28.tar.bz2
tar -xjvf kqemu.tar.bz2
ln -s linux-source-2.6.28 linux
Wenn wir die config-Datei unseres aktuellen Kernels aus dem /boot-Verzeichnis hernehmen und als .config nach /usr/src/linux kopieren, können wir normalerweise anschließend gleich mit
cd /usr/src/linux
make-kpkg kernel-image
make-kpkg modules-image
alles übersetzen. Wenn alles fehlerfrei gelaufen ist, haben wir dann unter /usr/src zwei neue .deb-Pakete liegen. Diese können wir dann mit
dpkg -i linux<version>.deb
dpkg -i kqemu<version>.deb
installieren. Bitte jetzt aber noch nicht einfach neu booten. Der Kernel hat nämlich selber quasi kaum Treiber eingebaut, diese liegen meist als Module vor, die dann in eine initramfs-Datei gepackt werden müssen. Dazu erst einmal aufrufen
update-initramfs -k 2.6.28 -c
und dann in der Datei /boot/grub/menu.lst bei den beiden bereits von der erfolgten Installation vorgenommenen neuen Einträgen jeweils noch die Zeile
initrd /boot/initrd.img-2.6.28
einfügen (als Beispiel kann man sich die alten Einträge in der gleichen Datei anschauen und vielleicht einfach kopieren und anpassen).
Damit kqemu gleich als Modul geladen wird, tragen wir es einfach mit in die Datei /etc/modules ein.
JETZT können wir damit neu booten und anschließend können wir zu unseren oben aufgeführten Kommandozeilen noch den Parameter "-kernel-kqemu" anhängen.
Resultat: Die Geschwindigkeit des Gastsystems wird mit kqemu - zumindest was die CPU betrifft - endlich an die des Hosts angenähert. Ein Test mit openssl-Berechnungen ("openssel speed rsa4096"; jeweils 10 Sekunden langer Test mit der Berechnung von 4096bit RSA-Keys (private und public)) erbringt die Werte:
16 private RSA's auf dem Host vs. 13 private RSA's auf dem Gastsystem
1100 public RSA's auf dem Host vs. 894 public RSA's auf dem Gastsystem
Die Plattengeschwindigkeit allerdings ist sogar noch etwas geringer als bei qemu ohne Beschleuniger - hier wurde noch mal etwas weniger Durchsatz gemessen (ca. 2,8 MB/s).
KVM
Mit KVM sieht alles deutlich anders aus. Durch die direkte Unterstützung der Virtualisierung durch die CPUs ist die Performance mit dem normalen qemu und auch mit kqemu nicht mehr vergleichbar.
KVM läuft auf vorhandenen Kernels ohne dass diese gepatcht werden müssen. Allerdings benötigt man Module, die vom Kernel geladen werden können. Das sind die Module kvm.ko und kvm-intel.ko bzw. kvm-amd.ko. Die Module stehen entweder fertig für fixe Kernel (wie sie z.B. bei den Distributionen fertig geliefert werden) zur Verfügung oder, wenn man einen selbstgebauten Kernel benutzt, per Übersetzung der entsprechenden Modul-Sourcen. Letzteres läuft unter Debian einfach so ab wie bereits oben für das kqemu-Modul beschrieben:
- Download der Sourcen mit "apt-get install kvm-source" und entpacken der Datei /usr/src/kvm.tar.bz2
- Wechsel nach /usr/src/linux und Übersetzen der Module mit "make-kpkg modules-image"
- unter /usr/src liegt jetzt das fertige .deb-Paket für die KVM-Module, die dann nur noch installiert werden müssen