Login
Newsletter
Werbung

Do, 23. Januar 2014, 15:00

Projekt »Virtueller hochverfügbarer Linux-Server«, Teil 11

Corosync und Pacemaker, libvirt und Live-Migration von KVM

libvirt

libvirt dient uns als Schnittstelle zur Steuerung der VM. Wir erinnern uns: Qemu bietet nicht so ohne weiteres die Möglichkeit, eine VM skriptgesteuert zu stoppen oder zu migrieren. libvirt leistet das. Dass libvirt darüber hinaus noch verschiedene Hypervisoren in einheitlicher Weise behandeln kann, interessiert uns hier nur am Rande.

Wir installieren das Paket libvirt-bin, das den Daemon libvirtd startet und das Kommandozeilenprogramm virsh bereitstellt.

apt-get -t squeeze-backports install libvirt-bin pm-utils 

pm-utils wird mit installiert, um eventuelle Fehlermeldungen »Cannot find 'pm-is-supported' in path« in /var/log/libvirt/libvirtd.log zu vermeiden. Vor dem Einsatz von libvirt sind zwei Änderungen nötig, die erste in /etc/default/libvirt-bin:

libvirtd_opts="-d -l"

Mit der zusätzlichen Option -l wird es möglich, vom einen Server aus auf den anderen zuzugreifen. In der Datei /etc/libvirt/qemu.conf müssen wir außerdem VNC aktivieren, da wir die virtuellen Maschinen mit der VNC-Option betreiben wollen. Die betreffende Zeile in der Datei ist zu aktivieren oder abzuändern:

vnc_listen = "0.0.0.0"

In neueren Versionen von libvirt ist es auch möglich, das SPICE-Protokoll zu nutzen. Es stellt sich heraus, dass der Remote-Zugriff von libvirt verschlüsselt abläuft und daher Zertifikate erfordert. Wir legen daher zwei Verzeichnisse an:

mkdir -p /etc/pki/CA
mkdir -p /etc/pki/libvirt/private

Anschließend können wir die Zertifikate nach der Anleitung auf libvirt.org generieren. Das Paket gnutls-bin muss dafür installiert sein. Wer bereits eine eigene CA eingerichtet hat, wird seine Schlüssel möglicherweise mit dieser generieren wollen. Die nötigen Kommandos dafür lauten ganz grob:

openssl genrsa -out privkey.pem 4096
openssl req -new -nodes -out req.pem -config ./openssl.cnf
openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem

Sie müssen für beide Server wiederholt werden. Ein Artikel auf debian-administration.org hilft eventuell bei Zertifikatsproblemen weiter. Die Schlüssel müssen an die richtige Stelle kopiert werden, das Resultat sollte so aussehen:

# ls -lR /etc/pki/CA /etc/pki/libvirt
/etc/pki/CA:
insgesamt 4
-rw--w---- 1 root root 1996 27. Sep 2003  cacert.pem

/etc/pki/libvirt:
insgesamt 16
-rw-r--r-- 1 root root 5403 28. Feb 2012  clientcert.pem
drwxr-xr-x 2 root root   46 28. Feb 2012  private/
-rw-r--r-- 1 root root 5403 28. Feb 2012  servercert.pem

/etc/pki/libvirt/private:
insgesamt 8
-rw-r--r-- 1 root root 3268 28. Feb 2012  clientkey.pem
-rw-r--r-- 1 root root 3268 28. Feb 2012  serverkey.pem

Ein erster Test, ob alles erfolgreich installiert wurde, ist der Zugriff über virsh von beiden Servern aus jeweils lokal und auf den anderen Server:

virsh -c qemu://erdbeere/system list

Sollte virsh beim Starten eine Fehlermeldung wie »failed to connect to the hypervisor« ausgeben, dann liegt das daran, dass kein Hypervisor gefunden wurde. virsh sucht beim Programmstart nach verschiedenen Programmen wie qemu, kvm und xend, und wenn keines davon vorhanden ist, schlägt es Alarm. Ist qemu in einer eigenen Version selbst installiert, dann kann man virsh beruhigen, indem man einen Link vom selbst installierten Qemu auf /usr/bin/kvm setzt:

ln -s /usr/local/bin/qemu-system-x86_64 /usr/bin/kvm

Unser nächstes Ziel soll sein, eine virtuelle Maschine mittels virsh zu starten und - viel wichtiger - zu stoppen. Die erste Beobachtung, die wir anhand der Dokumentation machen, ist, dass Kommandos in virsh asynchron sind. Wenn wir beispielsweise ein Stop-Kommando absetzen und erst nach dem Beenden der VM weitermachen wollen, müssen wir durch eine wie auch immer geartete wiederholte Abfrage darauf warten.

Eine virtuelle Maschine für libvirt wird in einer XML-Datei definiert. Wie üblich bei XML, muss die Syntax dieser Datei genau eingehalten werden. Glücklicherweise genügen einige wenige Angaben zum Starten; die meisten der zahlreichen Definitionen betreffen Spezialfälle, die wir erst einmal nicht benötigen. Einige Angaben sind außerdem optional; fehlen sie, setzt libvirt Standardwerte ein. Eine komplette Dokumentation der Optionen findet man auf den libvirt-Dokumentationsseiten. Eine einfache, funktionsfähige Datei kann man nach folgendem Muster zusammenstellen:

<domain type="kvm" id="0">
  <name>test</name>

  <os>
    <type>hvm</type>
    <boot dev="hd" />
    <kernel>vmlinuz-3.2.0-0.bpo.4-amd64</kernel>
    <initrd>/boot/initrd.img-3.2.0-0.bpo.4-amd64</initrd>
    <cmdline>root=/dev/vda1 noapic vga=-1</cmdline>
  </os>

  <memory>200000</memory>
  <vcpu>2</vcpu>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>destroy</on_reboot>
  <on_crash>destroy</on_crash>

  <features>
    <acpi/>
  </features>

  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='block' device='disk'>
      <driver name='qemu' type='raw' cache='none'/>
      <source dev='/dev/drbd0' />
      <target dev="vda" bus="virtio" />
    </disk>
    <interface type="bridge">
      <source bridge="br1" />
      <model type="virtio" />
      <mac address="66:66:66:66:66:00" />
    </interface>
    <graphics type="vnc" port="5900" keymap="de"/>
  </devices>
</domain>

Dabei ist

  • type="kvm" der Hypervisor, der verwendet werden soll - hier KVM
  • id="0" die ID der virtuellen Maschine, eine Zahl, die bei allen VMs unterschiedlich sein muss
  • <memory>200000</memory> wird in Kilobytes angegeben
  • <vcpu>2</vcpu> Anzahl der virtuellen CPUs - Standardwert ist natürlich 1
  • acpi ein notwendiges Feature, um die VM ausschalten oder rebooten zu können

Die weiteren Angaben sollten eigentlich selbsterklärend sein. Die Option noapic ist das Resultat eines Fehlers, der beim Starten ohne diese Option auftrat:

libvir: Remote error : socket closed unexpectedly
error: Failed to create domain from domain1.xml

Versuchen wir nun einen Start:

# virsh -d5 create domain1.xml
command: "create domain1.xml "
create: file(DATA): domain1.xml
Domain test created from domain1.xml

# virsh list
 Id Name                 State
----------------------------------
  2 test                 running

Und jetzt sollte die VM laufen und man sollte sich über ihre IP-Adresse (sofern konfiguriert) per SSH einloggen können. Alternativ kann man per VNC (Display Nr. 0 des Host-Rechners) zugreifen. Funktioniert das nicht, sollte man mit ps sicherstellen, dass die VM noch läuft. Mögliche Probleme muss man anhand des Syslogs oder, wenn es ganz hart kommt, per strace identifizieren.

Das shutdown funktioniert nur, wenn der Gastkernel ACPI-fähig ist und acpid gestartet ist:

# virsh shutdown 2

Kommt beim Start die Meldung »Domain already defined«, dann sieht man sehr wahrscheinlich nach Anwendung der Kommandos virsh list --all und virsh list --uuid eine inaktive Domain gleichen Namens. Es tritt dann auf, wenn man zum Testen der VM-Migration die XML-Datei auf den zweiten Server kopiert und einige Tests gefahren hat. Die Lösung besteht darin, die ursprüngliche XML-Datei nicht zu kopieren. Stattdessen führt man

virsh dumpxml <domainname> > /etc/libvirt/<domainname>.xml

aus. Damit schreibt libvirt eine erweiterte XML-Datei an die Stelle der ursprünglichen. Diese kann man kopieren. Da sie eine UUID enthält, weiß das System dann, dass es keine neue UUID generieren muss, und kann eine eventuell bereits definierte, aber deaktivierte VM wieder verwenden.

Kommentare (Insgesamt: 5 || Alle anzeigen )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung