QEMU Primer Part 1

von Simon Wilper am Sonntag, 20. September 2020

Darum geht es

QEMU, kurz für Quick Emulator ist wohl eine der verbreitesten Betriebssystemvirtualisierungslösungen für Linux. Es gibt verschiedenste Gründe, warum man eine virtuelle Maschine einsetzen möchte: Man ist Anbieter von vServern, der Kollege kommt mit einem Programm um die Ecke, das man sofort ausprobieren müsse, weil es ja so toll ist -- läuft aber nur unter Windows, oder die Wetter-App vom Pariser Flughafen läuft nur unter Windows 3.11.

QEMU installieren

Da es sich ja hierbei um ein recht populäres Paket handelt, sollte es jedem gängigen Paketmanager bekannt sein. Meistens heisst es qemu.

Einfaches Beispiel: Alpine Linux installieren

Das schöne an QEMU ist ja, dass man sich mit zwei Befehlen eine komplette Linux-Maschine erstellen kann. Wir nehmen hier im Beispiel mal ein x86_64 Alpine Linux, da das Install-ISO nur 40M groß ist, einen Shell-Installer hat und ziemlich schnell ist:

> wget http://dl-cdn.alpinelinux.org/alpine/v3.12/releases/x86_64/alpine-virt-3.12.0-x86_64.iso

2020-09-20 13:40:16 (9,81 MB/s) - ‘alpine-virt-3.12.0-x86_64.iso’ saved [41943040/41943040]
> qemu-img create -f qcow2 alpine-vm.img 4G
Formatting 'alpine-vm.img', fmt=qcow2 cluster_size=65536 compression_type=zlib size=4294967296 lazy_refcounts=off refcount_bits=16
qemu-system-x86_64 --enable-kvm -m 2G \
  -cdrom alpine-virt-3.12.0-x86_64.iso -boot order=d \
  -drive file=alpine-vm.img,format=qcow2

Und es sollte automatisch vom ISO-Image gebootet werden, so dass man die Installation ganz normal über setup-alpine oder bei anderen Distributionen über den grafischen Installer durchführen kann.

Was haben die beiden obigen Befehle nun bewirkt?

qemu-img create haben wir mitgeteilt, dass es ein Festplatten-Image der Größe 4GB mit dem Namen alpine-vm.img anlegen soll. Dabei haben wir über den Parameter -f das Format qcow2 angegeben. Lässt man den Parameter weg, wird raw angenommen.

Der offensichtlichste Unterschied zwischen den Formaten ist, dass bei raw die 4GB schon vorher reserviert werden und der Platz vom Host-System nicht mehr benutzt werden kann. Das klingt erstmal nach Platzverschwendung, kann aber zur besseren IO-Performance führen. Bei qcow2 (Copy on Write) wird der Platz beim Host erst belegt, wenn er auch wirklich benötigt wird.

Ist man z.B. geneigt, seine VMs in der Azure-Cloud laufen zu lassen, funktioniert dies nur mit dem Format raw.

Der zweite Befehl startet nun die VM und bootet vom Install-ISO. Die Kommandozeilenparameter bewirken dabei Folgendes:

Nach der Installation des Gastsystems sollte man die Optionen boot order und cdrom weglassen, damit es auch von dem Festplatten-Image bootet.

QEMU versucht, einige Dinge automatisch zu konfigurieren, damit man sofort loslegen kann. So auch das Netzwerk. Es wird sofort eine Netzwerkkarte angelegt, die vom internen DHCP-Server mit einer Adresse aus dem 10.0.2.0/24-Netz versorgt wird und zum aktiven Host-NIC via NAT verbunden wird -- man kommt also aus dem Gast direkt ins gleiche Netzwerk wie der Host. Mehr zur Netzwerkkonfiguration, z.B. mit VDE2

GUI

Jetzt ist das Ganze natürlich so schon lauffähig, nur bei einer Vielzahl von virtuellen Maschinen ist das Handling und Management nur über QEMU-Kommandozeilenparameter ziemlich umständlich. Dazu wollen wir uns in diesem Teil den virt-manager anschauen, einer grafischen Benutzeroberfläche, die auf libvirt aufbaut, etwa folgendermaßen:

libvirt, von Redhat entwickelt, ist eine abstrahierende Bibliothek, um auf verschiedene Virtualisierungsplattformen zuzugreifen, nicht nur KVM. Zudem wartet sie mit jeder Menge Bindings für jede Menge verschiedener Programmiersprachen auf.

Auch hier sollte es für die gängigen Distributionen kein Problem sein, die erforderlichen Pakete zu installieren:

Danach ist der Daemon libvirtd zu starten. Je nach Distribution oder Supervision-Daemon kann das unterschiedlich ausfallen. Bei systemd z.B.

# > systemctl start libvirtd
# > systemctl status libvirtd
● libvirtd.service - Virtualization daemon
     Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; disabled; vendor preset: disabled)
     Active: active (running) since Sun 2020-09-20 21:31:42 CEST; 19s ago
TriggeredBy: ● libvirtd-ro.socket
             ● libvirtd.socket
             ● libvirtd-admin.socket
       Docs: man:libvirtd(8)
             https://libvirt.org
   Main PID: 8940 (libvirtd)
      Tasks: 17 (limit: 32768)
     Memory: 10.6M
     CGroup: /system.slice/libvirtd.service
             └─8940 /usr/bin/libvirtd --timeout 120

Sep 20 21:31:42 archeus systemd[1]: Started Virtualization daemon.
# >

Jetzt sollte man den virt-manager normal starten können und folgendes Fenster zu sehen bekommen:

Da wir eine vorhandene Maschine hinzufügen wollen -- und zwar jene, die wir gerade im obigen Verlauf des Artikels erstellt haben -- müssen wir erst einen Storage Pool anlegen. Dazu Rechtsklick auf den Eintrag QEMU/KVM und dann auf Details.

Unten über das +-Symbol einen neuen Pool anlegen, Zielverzeichnis angeben und schon sollte unser alpine-vm.img in der Liste auftauchen.

Nun können wir mit dem ersten Icon der Toolbar im Hauptfenster eine neue VM hinzufügen. Ein Wizard sollte sich öffnen:

Option Import existing Disk Image wählen und auf Weiter.

Image aus dem Pool auswählen und unten ein System eintragen.

Speicher und Anzahl CPUs zuweisen.

Im nächsten Schritt vergeben wir nur noch einen aussagekräftigen Namen und bestätigen mit Finish.

Schon wird die VM automatisch gestartet: