Ich verwende auf meinem Root-Server KVM zur Virtualisierung. In einer der virtuellen Maschinen läuft meine Website https://kofler.info. Die virtuelle Festplatte dieser VM befindet sich in einer QCOW2-Image-Datei. Diese ist im Laufe der Jahre auf rund 30 GiB angewachsen (bzw. rund 32 GB bei dezimaler Rechnung). Tatsächlich beträgt die Virtual Size aber nur 24 GB (dezimal), und davon sind innerhalb der Maschine wiederum nur zwei Drittel genutzt. Da müsste es doch möglich sein, die QCOW2-Datei auzuräumen, oder?
Update 14.12.2019: Script, um nicht-allozierten Speicher aus QCOW2-Images zu entfernen.
Image-Datei aufräumen (von »außen«)
Die folgenden Kommandos wurden am Host ausgeführt, vorerst mit einer Backup-Datei des Images, um den laufenden Betrieb nicht zu stören:
qemu-img info ausgangspunkt.qcow2
image: ausgangspunkt.qcow2
file format: qcow2
virtual size: 24G (25769803776 bytes)
disk size: 32G
cluster_size: 65536
Format specific information:
compat: 0.10
refcount bits: 16
Die Image-Datei ist also ca. 32 GiB groß, obwohl die Nutzdaten maximal ca. 24 GiB betragen. Wie kann das sein? Der Overhead resultiert einerseits aus (vielfach nicht mehr benötigten Meta-)Daten der QCOW2-Datei, andererseits aus nicht mehr vorhandenen Snapshots, die im Laufe der Zeit erzeugt und wieder entfernt wurden. Mit qemu-img convert
können diese nicht mehr benötigten Ramsch-Daten entfernt werden. (Das Image darf dabei nicht in Betrieb sein!!)
qemu-img convert ausgangspunkt.qcow2 -O qcow2 aufgeraeumt.qcow2
Optional können Sie bei qemu-img convert
die Option -c
verwenden. Dann werden die Datenblöcke der Image-Datei zlib-komprimiert. Das dauert ziemlich lange (mehrere Minuten).
qemu-img convert ausgangspunkt.qcow2 -O qcow2 -c komprimiert.qcow2
Das Ergebnis (in binären MiB):
du -m *.qcow2
30003 ausgangspunkt.qcow2
23215 aufgeraeumt.qcow2
13722 komprimiert.qcow2
Das ist ja schon eine ordentliche Verbesserung!
Dateisystem aufräumen (von »innen«)
Ein Blick in die virtuelle Maschine hinein zeigt, dass von den 24 GiB Image-Größe 23 für das Root-Dateisystem vorgesehen sind, das verbleibende GiB für die Swap-Partition. Das Root-Dateisystem nutzt aber nur ca. zwei Drittel des Speicherplatzes:
df -h
/dev/vda1 23G 15G 7,4G 66% /
Das Problem ist, dass auch die ungenützten Speicherblöcke des Dateisystems alte, nicht mehr benötigte Daten enthalten. Nur wenn die ungenützten Speicherblöcke mit Nullen vollgeschrieben werden, kann das QCOW2-Image diese nun wirklich leeren Speicherblöcke aus dem Image entfernen. Der einfachste Weg, das zu bewerkstelligen, bietet das dd
-Kommando. Damit können Sie eine riesige Datei aus Nullen erzeugen. Danach synchronisieren Sie das Dateisystem und löschen die Datei wieder. Laut df
hat sich durch die Aktion nichts geändert.
dd if=/dev/zero of=zero bs=1M count=6500
sync
rm zero
df -h
/dev/vda1 23G 15G 7,4G 66% /
Tipp: Vermeiden Sie es, mit
dd
das gesamte Dateisystem vollzuschreiben! Das führt zu einer starken Fragmentierung, die nicht wünschenswert ist.
Image-Datei nochmals aufräumen (von »außen«)
Nach diesen Vorarbeiten ist es an der Zeit, die VM für ein paar Minuten hinunterzufahren. Mit qemu-img convert
kann nun eine neue, minimierte Image-Datei erzeugt werden:
mv kofler.info.qcow2 backup.qcow2
qemu-img convert backup.qcow2 -O qcow2 kofler.info.qcow2
du -m kofler.info.qcow2
9796 kofler.info.qcow2
Damit ist die Image-Datei auf ein Drittel ihrer ursprünglichen Größe geschrumpft. Die VM kann nun wieder gestartet werden.
Nebenwirkungen
Die hier beschriebene Vorgehensweise hat zwei Nachteile:
- Erstens ist die Ersparnis in diesem Umfang nicht von Dauer. Innerhalb der virtuellen Maschine werden neue ungenützte Speicherblöcke entstehen, selbst dann, wenn der Speicherbedarf des Dateisystems als Ganzes nicht steigt. Und auch im QCOW2-Image wird sich im Laufe der Zeit neuer ungenützter Speicher anhäufen. Und schließlich werden neue/geänderte Datenblöcke im QCOW2-Image nicht komprimiert (das wäre wohl zu langsam). Die zlib-Kompression gilt also nur für Daten, die sich nicht ändern. Damit die Ersparnis von Dauer ist, muss die hier skizzierte Aktion irgendwann (vielleicht in ein, zwei Jahren) wiederholt werden.
-
Zweitens hat die Komprimierung des Image (Option
-c
beiqemu-img convert
) natürlich eine relativ hohe Auswirkung auf die Geschwindigkeit. Datenblöcke müssen beim Lesen dekomprimiert werden. Der Effekt ist bei schnellen Datenträgern (SSDs) deutlich stärker bemerkbar als bei langsamen Datenträgern (also herkömmlichen Festplatten). Ob Sie bereit sind, diesen Nachteil in Kauf zu nehmen, hängt von den Anforderungen ab. In meinem Fall läuft die VM kofler.info ohnedies die meiste Zeit im Leerlauf, der Geschwindigkeitsunterschied ist daher für mich nicht relevant. Gegebenenfalls lassen Sie die Option-c
einfach weg, auch ohne die Komprimierung ist ja bereits eine deutliche Platzersparnis erreichbar.
Script für /var/lib/libvirt (Update Dez. 2019)
Das Thema lässt mich nicht los. Ich verwende den virt-manager mittlerweile auch intensiv am Desktop als VirtualBox-Alternative. Allerdings scheinen aktuelle virt-manager-Versionen beim Anlegen von QCOW2-Images generell den maximal vorgesehenen Speicherplatz zu allozieren. Die QCOW2-Dateien sind also von Anfang an viel zu groß.
Das folgende Script kann im Verzeichnis /var/lib/libvirt/images
in der Form shrink-images *.qcow2
aufgerufen werden. Von den oben erwähnten Maßnahmen wird nur die erste (und schnellste) ausgeführt. Auf meinem Rechner reichte das aus, um den Speicherplatz von 30 Testinstallationen von 670 GiB auf 240 GiB zu reduzieren. Denken Sie daran, dass Sie die virtuellen Maschinen stoppen, bevor Sie das Script ausführen!!
#!/bin/bash
# Aufruf: ./shrink-images name.qcow2
for filename in "$@"; do
bak=$filename.bak
du -h $filename
mv $filename $bak
qemu-img convert $bak -O qcow2 $filename
rm $bak
du -h $filename
echo ""
done
Quellen
- http://frippery.org/uml/index.html
- https://rwmj.wordpress.com/2010/05/18/tip-compress-raw-disk-images-using-qcow2/
- http://www.linux-kvm.org/images/9/92/Qcow2-why-not.pdf
- https://people.gnome.org/~markmc/qcow-image-format.html
- http://serverfault.com/questions/729110/how-to-really-reduce-the-size-of-kvm-vms-images
- http://www.noah.org/wiki/KVM
Was hier auch super hilft ich gleich ein DISCARD/TRIM-fähiges Dateisystem zu haben, denn dann ist der gesamte Aufwand überflüssig (konfigurierbar via qemu)! qcow2 kann das, aber es ergibt mehr Sinn hier gleich ZFS Volumes (oder der noch immer sehr instabile Clone BTRFS) zu verwenden, da die das auch können, aber nicht geschrumpft werden müssen wie qcow2.
Sehr interessant. Siehe auch:
https://lists.gnu.org/archive/html/qemu-devel/2013-08/msg01021.html
https://chrisirwin.ca/posts/discard-with-kvm/
http://dustymabe.com/2013/06/11/recover-space-from-vm-disk-images-by-using-discardfstrim/
Hallo,
kann es sein, dass in dem Befehl mit Komprimierung
„qemu-img convert ausgangspunkt.qcow2 -O qcow2 komprimiert.qcow2“
die Option „-c“ fehlt?
Natürlich, ausgerechnet das Wichtigste fehlt! Ärgerlich, aber ist schon korrigiert.