Discard für KVM-Gäste
Das qcow2-Imageformat in KVM erlaubt es die Abbilddateien als Sparse-Files zu erstellen. Sprase-Dateien belegen nur den tatsächlich verwendeten Speicherplatz. So lässt sich einer VM ein großzügiges Image bereitstellen, ohne dass der unbelegte Speicherplatz für alle anderen VMs verloren ist. Beim Backup können Sparse-Dateien schneller gesichert werden und auf SSDs sind sie gut für die Performance (sofern das Dateisystem auf dem sie liegen ebenfalls Discard unterstützt).
Das Ganze hat allerdings einen Hakten, solange die VM freie Blöcke nicht an den Hypervisor meldet, weiß dieser nicht, welche Teile das Image er verwerfen kann. Das heißt: Ohne die Mitarbeit der VM kann ein qcow2-Image nicht wieder kleiner werden. Dieser kleine Artikel beschreibt, wie eine KVM VM konfiguriert werden muss, damit Sparse-Dateien optimal genutzt werden können.
Datensicherung
Bevor man anfängt, die Konfiguration einer bestehenden VM zu verändern, ist es sehr empfehlenswert die bisher funktionierende Konfiguration zu sichern. Am einfachsten geht das über virsh dumpxml <VM> > backup.xml
.
Die Sicherung lässt sich dann über virsh define <Dateiname>
wieder einspielen.
VM Einstellen
Jetzt wo das Sicherheitsnetz steht, kann man beherzt zu virsh edit <VM>
greifen, um die Konfiguration der VM zu bearbeiten.
Erst einmal muss der Typ der VM ausreichend aktuell sein, um discard
zu unterstützen. Ein Maschinentyp ab pc-i440fx-2.1
ist ausreichend. Die aktuelle Version (Mai 2019) ist pc-i440fx-2.3
. Der von der VM verwendete Maschinentyp ist im Attribut machine
des Tags type
unter os
hinterlegt.
<os>
<type arch='x86_64' machine='pc-i440fx-2.3'>hvm</type>
<boot dev='hd'/>
</os>
Die Nutzung von discard
ist nur über das virtuelle SCSI device (virtio-scsi) möglich. Direkt über virtio angebundene Festplatten unterstützen kein discard
und müssen auf virtio-scsi umgezogen werden.
Small Computer Systems Interface
Unterhalb des Tags devices
muss zuerst der SCSI-Controller aktiviert werden. Am einfachsten geht das durch das Hinzufügen der Zeile <controller type='scsi' index='0' model='virtio-scsi'/>
. Virsh ergänzt dann alle weiteren Einstellungen automatisch:
<controller type='scsi' index='0' model='virtio-scsi'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</controller>
Wurde zu einer VM der SCSI Controller neu hinzugefügt, sollte die VM nochmal neu gestartet werden, damit der neue Controller erkannt wird. Grundsätzlich lässt sich das vorhanden sein des Controllers leicht über lspci
prüfen. Die Ausgabe sollte eine Zeile enthalten die der folgenden ähnelt:
00:04.0 SCSI storage controller: Red Hat, Inc Virtio SCSI
Zusätzlich sollte man nun die init-Ramdisk neu zu bauen, da diese ggf. bisher die SCSI-Treiber nicht enthalten hat und ansonsten der nächste Bootvorgang ein vorzeitiges Ende findet.
Bevor die bestehende virtio-Festplatte über virtio-scsi angebunden wird, sollte auch noch die GRUB-Konfiguration kontrollieren werden. Sind dort noch die Namen von Festplatten als vda1
oder ähnlich eingetragen, müssen diese unbedingt zuerst auf eine UUID- oder Namensbasierte Zuordnung umgestellt werden. Tut man dies nicht, geht das beim nächsten Neustart ebenfalls nicht gut aus.
Sind alle Anpassungen erfolgreich durchgeführt, kann die virtuelle Festplatte umkonfiguriert werden. Hierfür ergänzen wir zuerst einmal im driver
-Tag das Attribut discard='unmap'
. Dies sorgt dafür, das die entsprechenden Blöcke in der qcow2-Datei als ungenutzt markiert und an das Betriebssystem zurück gegeben werden. Unter target
wird das dev
-Tag auf sda
(oder sdb
, etc.) geändert, damit es zur neuen Anbindung über SCSI passt. Das bus
-Tag muss dann natürlich noch auf scsi
geändert werden.
Ein eventuell vorhandenes address
-Tag löschen wir einfach. Es wird durch virsh automatisch wieder mit den korrekten Einstellungen ergänzt.
Schlussendlich sieht das ganze dann ungefähr so aus:
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' discard='unmap'/>
<source file='/srv/vms/mydisk.qcow2'/>
<target dev='sda' bus='scsi'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='scsi' index='0' model='virtio-scsi'/>
Testlauf
Jetzt kann die angepasste VM (neu) gestartet werden. Hat diese erfolgreich gebootet, kann man als root fstrim -av
aufrufen. Das Kommando sollte nun ausgeben, wie viel Speicher es als frei markiert hat. Erscheint an Stelle dessen eine Fehlermeldung, muss nochmal die Konfiguration der VM geprüft werden.
Ein einfaches ls -l
zur Kontrolle der Veränderung des qcow2-Images fällt allerdings eher ernüchternd aus: Die Datei hat sich nur unwesentlich verkleinert. Dies hat damit zu tun, das qcow2 Sparse-Files unterstützt. Das heißt, ein qcow2-Image kann Löcher enthalten, die keinen Speicherplatz belegen. Das Ändert erst einmal nichts an der angezeigten Dateigröße. Um den tatsächlich belegten Speicherplatz zu ermitteln, eignet sich entweder du -h
oder ls -lsh
. Das Werkzeug du
zeigt grundsätzlich nur den tatsächlich auf dem Datenträger belegten Speicherplatz an und mit der Option -s
kann das auch das ls
-Kommand. Es schreibt diesen Wert dann zusätzlich in die erste Spalte seiner Ausgabe:
5.6G -rw-rw---- 1 libvirt-qemu libvirt-qemu 12G May 20 19:33 mydisk.qcow2
Das Image mydisk.qcow2
ist also nominell 12 GiByte groß, belegt auf dem Datenträger jedoch nur 5,6 GiByte.
Sharing is caring
Liegen die frei gewordenen Blöcke auf einer SSD hat das Discard bisher nur dazu geführt, dass mehr Speicherplatz frei ist. Um diese freien Blöcke schlussendlich an die SSD zu melden, muss auf dem Hostsystem ebenfalls fstrim
ausgeführt werden. Moderne systemd-basierte Distributionen bringen hierfür meist eine Unit mit dem einprägsamen Namen fstrim.timer
mit. Einmal über systemctl enable --now fstrim.timer
aktiviert sorgt diese Unit dafür, dass der VMHost einmal in der Woche die freien Blöcke an die SSD zurückgibt.