Mini-Howto: Xen nach KVM migrieren

(2010-06-23)

Da Xen wohl auch in Zukunft nicht in den Linux-Kernel aufgenommen wird und stattdessen KVM bereits verfügbar ist, habe ich meinen Server von Xen auf KVM migriert. Da die Migration ziemlich stressfrei lief (wenn man weiß, wo man drehen muss), möchte ich hier kurz den Verlauf schildern. Ich gehe davon aus, dass in der bestehenden Xen-Installation die Daten auf Logical Volumes abgelegt wurden.

Schritt 1: Hardware-Unterstützung verifizieren

Da KVM ohne Hardware-Unterstützung nicht zu gebrauchen ist, schaut man zunächst via egrep '^flags.*(vmx|svm)' /proc/cpuinfo (Vorsicht: In einer Xen dom0 wird dieses Flag nicht angezeigt) nach, ob die eingebaute CPU Virtualisierung unterstützt. Sofern der Befehl keine Ausgabe bringt, kann man noch im BIOS schauen, ob die Virtualisierung deaktiviert wurde.

Schritt 2: Bootloader installieren

In Xen ist der Bootloader extern, weswegen in den domUs üblicherweise kein GRUB in den MBR installiert wird (was für KVM aber notwendig ist). Während die Xen-domUs also noch laufen, installiert man via grub-install /dev/xvda einen Bootloader in den MBR. Bei mir hat das sowohl mit grub1 als auch mit grub2 problemlos funktioniert.

Schritt 3: Kernel wechseln, libvirt installieren

Nachdem man nun einen aktuellen Kernel (in Debian ist derzeit 2.6.32) gebootet hat, installiert man die Pakete libvirt-bin und virtinst (letzteres muss aus Debian testing kommen, die Version aus Debian lenny ist zu alt).

Schritt 4: Netzwerk einrichten

Die Standardkonfiguration findet man in /etc/libvirt/qemu/networks/default.xml. Ich habe sie, analog zu meiner Xen-Installation, so angepasst, dass alle VMs miteinander gebridged werden und direkt öffentliche IPs verwenden. Auf dem Hostsystem wird dann auf der Bridge eine IP aus diesem Netz konfiguriert, welche als Gateway dient. Die XML-Datei sieht bei mir also folgendermaßen aus:

<network>
<name>default</name>
<uuid>some-uuid</uuid>
<forward mode='route'/>
<bridge name='virbr0' stp='on' forwardDelay='0' />
<ip address='xx.yy.zz.193' netmask='255.255.255.224' />
</network>

Nachdem man den libvirtd neugestartet hat und mithilfe von virsh net-start default verifiziert hat, dass die Bridge und die iptables-Regeln korrekt installiert wurden, kann man durch virsh net-autostart default diese Konfiguration automatisch starten lassen.

Schritt 5: VMs einrichten und anpassen

Nun erzeugt man sich mithilfe von virt-install die Konfigurationsdatei für jede der alten domUs (im folgenden als VM bezeichnet):

virt-install --name web --ram 512 -f /dev/mapper/vg-web --import --vnc

Da KVM zum Anzeigen des VM-Bildschirms VNC anstelle einer emulierten Textkonsole benutzt, heißt es schnell sein: Mit vncviewer auf Port 5900 (für die zweite VM 5901, etc.) verbinden bevor die VM versucht zu starten und die „e”-Taste drücken um das Bootmenü zu editieren. Hier gilt es nun, den Eintrag console=hvc0 zu entfernen und ggf. den Pfad zum Root-Dateisystem anzupassen (wenn /dev/xvda1 benutzt wird, was bei grub2 nicht mehr der Fall ist).

Sobald die VM erfolgreich startete, kann man die restlichen Anpassungen vornehmen:

  • In /etc/default/grub (grub2) oder /boot/grub/menu.lst (grub1) die Vorkommen von console=hvc0 entfernen
  • In /etc/inittab den getty-Eintrag für hvc0 entfernen.
  • In /etc/fstab xvda durch hda ersetzen.

Anschließend kann man die VMs mit virsh autostart web zum automatischen Starten bei Systemstart animieren.

Fallstrick: arp-cache

Bei meiner Migration hatte ich den lustigen Effekt, dass manche (nicht alle!) IPs aus meinem Netz nicht mehr erreichbar waren. Interessanterweise hatte ich also die Situation, dass eine VM zwei IPs hatte, von denen eine funktionierte und eine nicht. Mithilfe von tcpdump sah ich, dass das Paket zwar auf meinem Server ankam, dann aber nicht an die VM weitergeroutet wurde, obwohl augenscheinlich die Konfiguration in Ordnung war.

Des Rätsels Lösung offenbarte sich dann durch ein tcpdump -e, in welchem man auch die Ethernet-Header sieht: Adressiert war das Paket an die alte MAC-Adresse aus dem Xen-Adressbereich, weswegen es nie sein Ziel erreichte. Eine kurze Mail an meinen Provider mit der Bitte, den arp-cache auf dem Router vor meinem Server zu leeren, löste dann das Problem. Man sollte also sicherstellen, dass der Provider einsatzbereit ist, wenn man migriert.