|

qemu-guest-agent als Schnittstelle zwischen VMs und Proxmox

Da mit KVM/QEMU realisierte virtuelle Maschinen im Vergleich zu einem Container deutlich strikter von dem Host-System getrennt sind, stellt QEMU mit dem qemu-guest-agent für Linux-Gastsysteme einen begleitenden Service zur Verfügung. qemu-guest-agent fungiert dabei als Schnittstelle zwischen den VMs und dem Host-System.

Einige Funktionen wie das Durchreichen von ACPI-Informationen für ein sauberes Herunterfahren der Gastsysteme sind relativ bekannt. Wusstest Du aber, dass Du sogar beliebige Befehle direkt über dein Proxmox-Hostsystems an die VMs übergeben kannst?

Auch die Virtualisierungsumgebung Proxmox Virtual Environment nutzt KVM/QEMU als Virtualisierungs-Technologie. Da das qemu-guest-agent-Interface auf den ersten Blick nicht sonderlich intuitiv zu bedienen ist, stellt Proxmox den qm guest-Befehl zur Verfügung, welcher als Brücke zwischen dem Host-System und den VMs dient.

Die Verwendung des qm guest-Befehls setzt voraus, dass qemu-guest-agent in den Linux-Gastsysteme installiert ist. Da der Guest Agent jedoch schon dann benötigt wird, wenn Du beispielsweise VMs sauber herunterfahren möchtest, ohne den virtuellen Stecker zu ziehen oder auch konsistente Backups anfertigen willst, möchtest Du den Guest Agent vermutlich ohnehin auf allen deiner Linux-Gastsysteme installieren.

Für die folgenden Befehle benötigst du die VMID deiner VMs. Diese kannst Du entweder dem Proxmox-Dashboard entnehmen oder über den Befehl qm list abfragen.

Benutzer-Passwörter zurücksetzen (einschließlich des root-Benutzers)

Auf qm bin ich quasi zufällig gestoßen. Üblicherweise sperre ich alle Linux-Systembenutzer, um die Anmeldung an der (virtuellen) Konsole unmöglich zu machen. Gerade bei VMs mag das nicht einmal einen Sicherheitsgewinn bringen, aber irgendwie ist das eine Angewohnheit von mir. Durch einen Konfigurationsfehler habe ich mich dabei aus einer VM, die auf meinem Proxmox-Host läuft, ausgesperrt, sodass ich weder über die lokale Konsole noch via SSH auf das System zugreifen konnte.

Die offensichtliche Lösung wäre hier eigentlich, die VM herunterzufahren, ein Rettungssystem oder ein Live-Linux zu booten und die Konfiguration dort zu korrigieren. Ich wusste, dass zu diesem Zeitpunkt die VM einige Wartungsarbeiten/Cronjobs ausgeführt hatte, welche bei plötzlichen Unterbrechungen problematisch werden können.

An dieser Stelle kommt qm guest passwd ins Spiel. Wie der Name des Befehls schon suggeriert, können damit auch ohne „Direktzugriff“ die Benutzer-Passwörter innerhalb einer VM neu gesetzt werden.

Folgender Befehl etwa setzt das Passwort für den Benutzer root auf der VM mit der ID 100 zurück:

qm guest passwd 100 root

Nach dem Absetzen dieses Befehls wird dich qm nach einem neuen Passwort für den betroffenen Benutzer fragen. Sofern der Benutzer zuvor mittels passwd -l gesperrt wurde, wird er nun automatisch entsperrt.

Beliebige Befehle in einer VM ausführen

Wie Du vermutlich bereits bemerkt hast, haben wir über den QEMU Guest Agent (oder kurz QGA) vollen Zugriff auf das Betriebssystem der VMs, weshalb wir auch tatsächlich jeden Befehl an die VM weiterreichen können. Das ist übrigens ein guter Zeitpunkt, sich daran zu erinnern, dass man sich in jedem Fall um die Sicherheit des Hostsystems kümmern möchte.

Der Befehl, den wir hier benötigen, ist qm guest exec (wieder mit VMID 100 als Beispiel):

qm guest exec 100 -- ping google.com -c 3

qm exec gibt den Befehl an die VM weiter, lässt ihn dort ausführen und wartet darauf, dass der Befehl entweder erfolgreich abgeschlossen wird oder mit einem Fehlercode abbricht. Anschließend wird der Exit-Code sowie der Inhalt von stdout und stderr im JSON-Format zurückgeliefert. Alle Befehle werden dabei im Kontext des root-Users ausgeführt.

Länger laufende Befehle können mithilfe des Parameters --synchronous=0 in den Hintergrund geschickt werden. Du kannst den aktuellen Status eines solchen Prozesses mit dem Befehl qm guest exec-status $VMID $PID abfragen.

Zusätzliche VM-Informationen abfragen und Low-level-Aufgaben ausführen

Werfen wir als nächstes einen Blick auf den Befehl qm guest cmd. Hiermit führen wir keine Befehle innerhalb der VMs selbst aus. Stattdessen werden mit cmd verschiedene QGA-Befehle auf einem „niedrigeren“ Level ausgeführt. Diese Befehle sind eher zu Wartungszwecken und weniger zur Interaktion mit dem Gast-Betriebssystem gedacht.

Um dieses Feature zu nutzen, kommt folgender Befehl zum Einsatz:

qm guest cmd $VMID $Command

Nachfolgend habe ich eine Liste der gültigen Kommandos zusammengestellt. Analog zu qm guest exec ist die Ausgabe JSON-Formatiert.

KommandoBeschreibung
fsfreeze-freezeSendet den Befehl fsfreeze-freeze an die VM und „sperrt“ das Dateisystem des Gast-Betriebssystems
fsfreeze-statusFragt den Status von „fsfreeze“ ab, gibt „frozen“ oder „thawed“ zurück.
fsfreeze-thawEin zuvor „eingefrorenes“ Dateisystem wieder „aufzutauen“ bedeutet, die Kontrolle über das Dateisystem wieder dem Gast-Betriebssystem zu übergeben.
fstrimSendet den TRIM-Befehl an die Block-Devices der VM. Die VM muss dabei mit der discard-Option oder aktivierter SSD-Emulation konfiguriert sein. Zusätzlich muss das Gast-Dateisystem TRIM unterstützen. Hinweis: Da ein vollständiges fstrim einige Zeit benötigt, bricht der Befehl scheinbar mit der Fehlermeldung qmp command 'guest-fstrim' failed - got timeout ab. Überprüfe das Message-Log des Gast-Betriebssystems auf die Zeile guest-fstrim called, um festzustellen, ob der Befehl erfolgreich gesendet wurde.
get-fsinfoGibt alle gemounteten Dateisysteme zurück
get-host-nameGibt den Hostnamen des Gast-Betriebssystems zurück
get-memory-block-infoZeigt diverse Informationen über die RAM-Belegung der VM an
get-memory-blocksZeigt diverse Informationen über die RAM-Belegung der VM an
get-osinfoZeigt verschiedene OS-Informationen wie die verwendete Distribution, Kernel-Version und Architektur an
get-timeGibt die Systemzeit des Gast-Betriebssystems zurück
get-timezoneGibt die Zeitzone des Gast-Betriebssystems zurück
get-usersGibt alle aktuell im Gast-Betriebssystem angemeldeten Benutzer zurück
get-vcpusGibt Informationen über die aktuell konfigurierten virtuellen CPUs zurück
infoGibt eine Liste aller vom QGA unterstützten Befehle zurück
network-get-interfacesGibt eine Liste aller konfigurierten Netzwerk-Interfaces, einschließlich Traffic-Statistiken, zurück
pingPrüft, ob die VM aktiv und der qemu-guest-agent betriebsbereit ist. Wenn dieser Befehl in einen Timeout läuft, ist die VM entweder offline oder der qemu-guest-agent funktioniert nicht korrekt. Hinweis: Dies ist kein „traditioneller“ Ping über eine Netzwerkverbindung. Stattdessen versucht das Hostsystem, direkt über den QGA mit der VM zu kommunizieren.
shutdownSendet den „shutdown“-ACPI-Befehl an die VM
suspend-diskSendent den „suspend-to-disk“-ACPI-Befehl an die VM
suspend-hybridSendet den „suspend-hybrid“-ACPI-Befehl an die VM.
suspend-ramSendet den „suspend-to-RAM“-ACPI-Befehl an die VM

Zusammenfassung

Der QEMU Guest Agent bietet ein umfangreiches Interface zur Kommunikation zwischen dem Host-System und den VMs.

Du kannst entweder beliebige Befehle an das Gast-Betriebssystem senden oder den QGA auch für die Abfrage einiger Informationen über die VMs verwenden. Auch Befehle, die auf einer niedrigeren Ebene ausgeführt werden, sind möglich – so kannst Du beispielsweise VMs herunterfahren oder dem Host-System die Kontrolle über die Dateisysteme der Gäste übergeben. Das ist beispielsweise dann wichtig, wenn Du die in Proxmox integrierte Snapshot-Funktion verwenden willst. In diesem Fall werden die nötigen Schritte jedoch bereits durch das Proxmox-Webinterface abstrahiert – im Hintergrund wird jedoch auf genau die gleichen Mechanismen zurückgegriffen.

Derzeit wird über den qm-Befehl nur eine Teilmenge des QGA-Protokolls abgebildet. Da es etwas aufwändiger ist, auch die übrigen Befehle an die VMs zu schicken, werde ich dies in einem separaten Artikel behandeln.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.