Skip to content

Let’s get dirty – Proxmox IO Caching

In meinem Proxmox Server habe ich folgende Beobachtung gemacht. Beim Schreiben einer großen Datenmenge innerhalb einer VM hat mein Proxmox Server selbst zwischenzeitlich nicht mehr reagiert, VMs und der Server selbst waren nur mit langen Wartezeiten mittels SSH erreichbar. Alles schien zu “hängen”. Ich konnte sehen, dass die “Wait IOs” in TOP bei ca. 80% waren. Weiterhin konnte ich sehen, dass die Speicherauslastung meines Proxmox Hosts unerklärlich hoch war. Dieser Zustand hielt für ca. 2 Minuten an, bevor es sich dann von selbst nach und nach normalisierte. Aber was war das genau?

Proxmox basiert auf einem Linux Betriebssystem (Debian). Hier ist im Standard ein “Disk Caching” Mechanismus aktiviert. Es werden hier auch Schreiboperationen im Speicher des Proxmox Hosts gecached / gepuffert, bevor sie dann tatsächlich auf die Platten geschrieben werden. Normalerweise geschieht dies im Hintergrund und asynchron. Sollte es aber dazu kommen, dass große Datenmengen geschrieben werden, läuft der für das Caching vorgesehene Speicherbereich des Proxmox Hosts voll (erkennbar an der hohen Speicherauslastung) und das zurückschreiben der Daten im Speicher auf Platte läuft nicht länger asynchron im Hintergrund. Alle anderen Prozesse (also auch die VMs) müssen warten, bis der Cache auf Platte geschrieben wurde. Anschließend geht es wie gewohnt weiter.

Jetzt kommt aber der positive Aspekt. Wie alles unter Linux, ist auch dieses Verhalten einstellbar. Dazu schauen wir uns die folgenden Kernel Parameter an:

sysctl -a | grep dirty

vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200

Schauen wir uns die einzelnen Parameter an.

vm.dirty_background_ratio (10): Dieser Wert gibt an, wieviel Prozent des verfügbaren Speichers (in meinem Fall 64GB) als “dirty Pages” verwendet werden dürfen, bevor ein Zurückschreiben der Pages auf die Platten gestartet wird. Es sollten also in meinem konkreten Fall 6,4 GB dafür zur Verfügung stehen. Ab dann, fängt das Betriebssystem an, die Pages im Hintergrund auf die Platte zu schreiben.

vm.dirty_ratio (20): Die “dirty ratio” gibt an, wieviel Speicher insgesamt für “dirty Pages” zur verfügung stehen. Wird dieser Wert erreicht. Werden alle IO Operationen pausiert, bis der Cache auf Platte geschrieben wurde. In meinem Fall stehen also insgesamt rund 12,8GB an Speicher als Cache zur Verfügung. Diese 12,8GB werden auch ziemlich genau erreicht, als mein System ins “hängen” gekommen ist.

vm.dirty_background_bytes und vm.dirty_bytes: Hierbei handelt es sich nur um die Möglichkeit die dirty_ratio und dirty_background_ratio nicht in Prozent sondern in Byte anzugeben. Solltet ihr das so einstellen wollen, müsst ihr die dirty_background_ratio und dirty_ratio auf 0 setzen.

vm.dirty_expire_centisecs (3000): Dieser Wert kontrolliert, wie lange eine “dirty page” im Speicher verweilen darf bevor des Hintergrundschreibprozess anläuft. In meinem Fall also 30 Sekunden.

vm.dirty_writeback_centisecs (500): Dieser Wert steuert, wie oft der Hintergrundprozess den Speicher prüft ob es etwas zu tun gibt. In meinem Fall alle 5 Sekunden.

Generell haben wir nun mehrere Möglichkeiten dem Problem entgegenzutreten.

Variante 1 – Verkleinern / deaktivieren des Caches: Wenn wir die zwei Werte für dirty_ratio und dirty_background_ratio bspw. halbieren, wird dies dazu führen, dass weniger Speicher unseres Hosts für Caching verwendet wird. Ein weiterer Vorteil ist, dass wir keinen oder weniger Datenverlust erleiden, sollte der Server ausfallen. Diese Variante macht dann Sinn, wenn wir ein schnelles Plattensystem im Einsatz haben, dass eventuell selbst mit Caches arbeitet.

Variante 2 – Verkleinern und vergrößern des Caches: Diese Möglichkeit habe ich genutzt. Ich habe bei mir die dirty_background_ratio reduziert und die dirty_ratio erhöht. Das führt dazu, dass mehr Hauptspeicher des Systems für Caching verwendet werden kann, der Hintergrundprozess, der die “dirty pages” auf Platte schreibt, aber wesentlich früher einsetzt. Dieses Vorgehen ist aus meiner Sicht nur vertretbar, wenn es sich um ein unkritisches / unproduktives System handelt. Bei einem Systemausfall wäre das Risiko ansonsten zu hoch, dass Daten verloren gehen.

Setzen können wir die Kernel Parameter mit folgenden Befehlen. Hier wie in meinem Beispiel:

vi /etc/sysctl.conf

# Hier setzen wir die Werte nach unserem Belieben
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5

Im Anschluss aktivieren wir mit sysctl --system die neue Konfiguration.

Philip

Leave a Reply

Your email address will not be published. Required fields are marked *