Die VSD-basierte OSL Storage Engine 4.8 kann eine große Zahl von Backend-Technologien unterstützen. In erster Linie sind dies natürlich Block-Devices. Mit der Einführung von LFS (s. aktuelles Thema "LFS - Local File Storage in der OSL Storage Engine 4.8") werden durch die Engine global (also auch für die UVCs, d. h. die VM-Hypervisor-Nodes), verfügbare virtuelle Block-Devices auf Dateien abgebildet. So erweitert sich der Funktionsumfang um Leistungsmerkmale moderner Dateisysteme, also Thin Provisioning und Datenkomprimierung. Die Besonderheit bei dem von OSL gewählten Ansatz ist, daß z. B. im UVE direkt die Fähigkeiten des Betriebssystems genutzt werden und kein Umweg über eigene VM-Disk-Formate notwendig ist. Der Anwender profitiert von zahlreichen Optimierungen des Betriebssystemlayers mit Blick auf Dateisysteme.
Der nach Thin Provisioning und Datenkomprimierung logisch folgende Schritt ist die Deduplizierung. Die speziellen Anforderungen dieser Technologie führen in der Implementierung eher in Richtung Dateisysteme bzw. Treiber mit dateisystemartigen Zuordnungstabellen – aus unserer Sicht also kein typisches Thema für unsere Block-Device-Virtualisierung. Also richtet sich der Blick auf bereits verfügbare Lösungen.
Von den Betriebssystemanbietern bzw. Entwicklern werden im wesentlichen zwei Ansätze verfolgt: Bei den Dateisystemen machten zunächst Netapps WAFL und das von Sun Microsystems entwickelte ZFS auf sich aufmerksam. Damit hat sich zunächst in der Solaris-Welt vieles geändert, es folgten auch Portierungen auf andere Betriebssysteme. Etliche, aber längst nicht alle vom Marketing hochgeschraubten Erwartungen konnten in der Praxis erfüllt werden. So stellte sich dann auch vor allem beim Thema Deduplizierung eine gewisse Ernüchterung ein. Das Unternehmen Permabit wählte einen anderen Weg und implementierte seine Technologie als Block-Device-Treiber unter Linux. Die Stärke hier: Es wurde sich auf das Notwendige und Machbare konzentriert. Im Ergebnis gibt es zwar Beschränkungen, wie etwa 256TiB physischen Backend-Storage und 4PiB logisches Datenvolumen, dafür aber hat sich die Lösung dem Vernehmen nach seit 2013 in zahlreichen produktiven Umgebungen bewährt und punktet – auch in unseren Tests – mit einer überzeugenden Performance. Die technischen Randbedingungen sind für viele Anwender darstellbar, die Limitierungen (4PiB) für viele (noch) nicht relevant. Und: Natürlich kann man auch mehrere solche Dedup-Engines unter einem Dach wie UVE zusammenführen, so daß auch größere Einheiten realisierbar sind.
Seit der Übernahme von Permabit durch Red Hat wurde dieses Projekt zu Open Source, später zu einem Device-Mapper-Target gewandelt und ist seit dem Kernel 6.9 praktisch allgemein verfügbar. Anwendern von OSL Storage Cluster und OSL Unified Virtualisation Environment steht sie damit in der linuxbasierten Welt auch zur Verfügung, z. B. in der SuSE-Welt mit Tumbleweed.
Es gibt bereits zahlreiche Quellen, die das Thema Deduplizierung ausführlich beleuchten, also die Technologien sowie die Vor- und Nachteile. So stehen diese Themen hier nicht so sehr im Mittelpunkt. Es soll vielmehr die Einbindung in den UVE gezeigt werden und ein Eindruck von den in der Praxis zu erwartenden Ergebnissen vermittelt werden.
Der entscheidende Bestandteil ist natürlich der Deduplizierungstreiber, der ab Linux- Kernel 6.9 im OS enthalten ist. Die frühere, geradlinige Bedienerschnittstelle ist einer Integration in das Device-Mapper-Framework gewichen. Wer dessen sehr mächtige, vor allem aber auch sehr rätselhafte Logik verinnerlicht hat, findet hier ein ggf. sehr weites Betätigungsfeld. Allen, die eher am fertigen Ergebnis einschließlich passender Parametrisierung interessiert sind, bieten OSL und Partner die fertige Einrichtung im UVE an. Und dann wird es im Alltag erfreulich einfach: Durch die Integration in das LFS-Framework kann man wie gewohnt Volumes erzeugen und hat alle wichtigen Informationen auf einen Blick beisammen.
Die nebenstehende Grafik gibt einen Einblick in die Gesamtarchitektur. Die eigentliche Deduplizierung findet ausschließlich auf dem bzw. den UVS statt. Als Backend-Storage-Devices kommen nach unserer Erfahrung nur leistungsfähige Enterprise-SSDs in Frage, im Interesse der Verfügbarkeit und Einfachheit hinter einem PLP-RAID-Controller. Im UVE-Framework arbeitet man dann wie gewohnt mit Application Volumes, die über RSIO direkt an die VMs auf den UVC (Hypervisor Nodes) angeschlossen sind. So kann ein allumfassender, globaler Deduplizierungspool bereitgestellt werden, was wichtig für hohe Deduplizierungsraten ist. An den kritischen Punkten stehen kurze Latenzen, hohe Bandbreiten, ausreichend Memory und CPU-Leistung zur Verfügung. Die UVC und damit die VMs haben damit gar nichts zu tun. Ihnen stehen weiterhin alle Ressouren des Hypervisor-Nodes ohne Einschränkungen zur Verfügung.
Außerhalb des Themas noch ein Wort zum OSL Storage Cluster: Auch hier stehen natürlich das LFS-Subsystem und RSIO zur Verfügung, so daß alle Möglichkeiten von Deduplizierung mit ausschließlich lokalem Storage-Backend bis zu einem clusterweiten, gemeinsamen Dedup-Pool mit den üblichen I/O-Schnittstellen per Application Volumes (Block Devices) zur Verfügung stehen.
Details zur internen Funktionsweise des DM-Drivers finden sich im Web*. An dieser Stelle soll vereinfacht gezeigt werden, was man als Anwender erwarten darf:
Die Block-Devices der VMs werden im UVE als Application Volumes dargestellt, die ihrerseits nun in einem gemeinsamen Deduplizierungspool liegen. Jedes dieser Volumes enthält individuelle Datenblöcke, mit hoher Wahrscheinlichkeit jedoch auch Null-Blöcke und Blöcke, die mit anderen identisch sind. Dies leuchtet ein, wenn man bedenkt, daß sicherlich mehrere VMs mit den gleichen Betriebssystemdateien installiert werden. Die Dedup-Engine eliminiert nun zuerst NULL-Blöcke, die nicht gespeichert werden müssen und bei späteren Lesevorgängen schnell "aus heißer Luft" erzeugt werden können. Weiterhin werden mehrfach vorhandene, identische Blöcke auf eine einzige Instanz reduziert und lediglich die Referenzen darauf in kompakter Form gespeichert. Schlußendlich werden die so erhaltenen, deduplizierten Datenblöcke nach Möglichkeit komprimiert. Auf diese Weise kann das tatsächlich zu speichernde Datenvolumen in der Praxis erheblich reduziert werden. Ein wichtiger Punkt: Kapitale Fehler oder Ausfälle des Dedup-Systems lassen eine Wiederherstellung quasi unmöglich erscheinen. Dies ist aber auch bei modernen, tree-basierten Dateisystemen wie ZFS oder BTRFS der Fall. Beim Dedup-System kommt – sofern man es nicht offline sichern kann – jedoch erschwerend das hohe zu sichernde Brutto-Datenvolumen hinzu. Wie bei allen neuen und besonders ausgeklügelten Systemen scheinen daher eine gesunde Vorsicht und Sicherheitsüberlegungen angebracht zu sein. Von daher sollte insbesondere bei den Speichermedien, RAID-Controllern, USV usw. nicht an der falschen Stelle gespart werden, Weiterhin ist zu beachten, daß ein Volllaufen des Pools problematisch sein kann, auch das muß man – wie bei allen Überprovisionierungsmechanismen – im Auge haben. Auf der Habenseite stehen aber eine längere Reife der Technologie, sehr gute Deduplizierungsraten und damit Einsparmöglichkeiten und in nicht seltenen Fällen sogar Performancegewinne, da der tatsächliche I/O im Backend u. U. nur einen Teil des Bruttovolumens ausmacht bzw. aufgrund der internen Funktionsweise bei tatsächlicher Deduplizierung lesend stattfindet, was wiederum Caching-Strategien der Backend-Devices oder RAID-Controllern entgegenkommt.
Um die allgemeine Handhabung und etwaige Unterschiede in der Performance aufzuzeigen, haben wir in unserem Demo-UVE zunächst eine Reihe von VMs bereitgestellt, die als Backend-Storage eine etwas ältere SATA-SSD verwenden:
Aus dieser bunten Mischung wählen wir die recht schwach ausgebaute vm7 (2 VCPUs, 2GiB RAM) zur Ausführung mit KVM als Hypervisor aus und führen zunächst mit dem konventionellen SSD-Setup mehrfach folgende Tests durch (Durchschnittswerte):
- Start der VM bis zum X11-Anmeldebildschirm : | 32s |
- In der VM Erstellung eines tar-Archivs von /usr/lib64 (2.555 MiB ): | 72s |
Damit liegen einfache Vergleichswerte vor. Nun verschieben wir – zwecks Test der Effizienz – die VMs 1-7 in den Dedup-Speicherpool. Zunächst ein Blick auf das Datenvolumen:
# smgr -qa used by vm1@0 : 12288m 12g 0.012t used by vm2@0 : 12288m 12g 0.012t used by vm3@0 : 20480m 20g 0.020t used by vm4@0 : 20480m 20g 0.020t used by vm5@0 : 8192m 8g 0.008t used by vm6@0 : 20480m 20g 0.020t used by vm7@0 : 20480m 20g 0.020t used by vm8@0 : 20480m 20g 0.020t used by vm9@0 : 20480m 20g 0.020t used by vbox1@0 : 12288m 12g 0.012t used by vbox2@0 : 16000m 16g 0.015t used by vm_nvme@0 : 20480m 20g 0.020t
Die virtuellen Maschinen vm1 bis vm7 nehmen also insgesamt 152 GiB in Anspruch. Um diese im Dedup-LFS-Pool unterzubringen, erzeugen wir uns dort ein hinreichend großes Physical Volume, hier z.B. mit einer Größe von 400GiB:
# pvadmin -c lfs_d00 -g LFS01 -S 400g -o sparse INFO (pvadmin): creating file ... INFO (pvadmin): file creation done LFS01's overcommit rate is 0.04 : 1, usage 2% # lfsadmin -lph group/volume total used avail pct ocr dduse ddsav LFS01 9t+ 196g+ 9t+ 2% 0.04 0% 99% lfs_d00@0 400g 8k - 0% - - -
Damit steht nun der Speicher zur Verfügung. Der noch unbenutzte Dedup-Pool verbraucht für seine interne Organisation bereits 1% seines Speichervolumens, 99% sind noch frei.
Um die Daten dorthin zu verschieben, erzeugen wir zunächst sogenannte Schatten-Volumes, z. B. für unsere ausgewählte VM:
# smgr -c s_vm7_001 -S 41943040 lfs_d00 s_vm7_001@0 created
Damit steht auf dem zuvor angelegten Dedup-Ziel-PV lfs_d00 der Zielcontainer für das Verschieben zur Verfügung, das wir gleich anstoßen:
# avmove vm7_001 s_vm7_001 INFO (avmove): moving in universe 0 from vm7_001 to s_vm7_001
Um das für alle oben genannten VMs zu tun, habe ich natürlich eine for-Schleife in der Shell genutzt. Das Verschieben selbst dauerte für alle VMs übrigens insgesamt 7:24 Minuten, was bedeutet, daß uns der Dedup-Pool die Daten mit einer durchschnittlichen Geschwindigkeit von ca. 350 MiB/s abgenommen hat. Das ist recht ordentlich. Man muß auch in Rechnung stellen, daß wir nur von einer Quell-Platte gelesen haben.
Das Volume liegt nun im Dedup-Pool auf unserem zuvor angelegten lfs_d00:
# avadmin -lvvv vm7_001 0 vm7_001 41943040 of 41943104 blocks "simple,master" in 1 pieces, 32 block clusters [ 1] lfs_d00 [192938368...234881471], 0 io
An dieser Stelle lohnt wieder ein Blick auf die LFS-Statistik:
# lfsadmin -lph group/volume total used avail pct ocr dduse ddsav LFS01 9t+ 348g+ 9889g+ 4% 0.04 7% 78% lfs_d00@0 400g 152g+ - 38% - - -
Wir sehen, daß unsere 152 GiB angekommen sind (Spalte used) und das sich etwas in der Dedup-Statistik getan hat. Der physische Speicher ist nun zu 7% ausgelastet. Da die hier genutzte NVMe-SSD 475GiB bereitstellt, sind das 33,25GiB. Die Dedup-Space-Reduction-Percentage (ddsav) beträgt nun 78%, d. h. die Daten beanspruchen nur 100% - 78% = 22% ihres originären Volumens. Die Deduplizierungsrate liegt also bei 4,55 : 1. Nicht schlecht!
Damit ist es Zeit für die Wiederholung unseres vorherigen einfachen Tests:
- Start der VM bis zum X11-Anmeldebildschirm : | 32s (32s) |
- In der VM Erstellung eines tar-Archivs von /usr/lib64 (2.555 MiB ): | 46s (72s) |
Die Werte in Klammern sind die Vergleichsgrößen aus dem eingangs durchgeführten Test gegen das normale SSD-Backend. Wir sehen: In keinem der beiden einfachen Anwendungsfälle schneidet der Test gegen das Dedup-Konstrukt schlechter ab, im Falle des tar-Archivs sogar signifikant besser. Dabei spielen die leistungsfähigere SSD, diverse Caches und vermutlich auch der Dedup-Vorgang eine Rolle. Eine genauere Betrachtung dieses Themas würde hier zu weit führen. Fakt ist aber, daß beim Schreiben des tar-Archivs definitiv und ganz überwiegend Block-Duplikate erstellt werden.
Aber auch ohne Deduplizierungsmöglichkeit ist die erzielbare Schreibrate noch respektabel, nachfolgend kurz gezeigt mit einem Beispiel, ausgeführt in der vm7:
# dd if=/dev/urandom of=/dev/null bs=1024k count=512 512+0 records in 512+0 records out 536870912 bytes (537 MB, 512 MiB) copied, 1.82516 s, 294 MB/s # dd if=/dev/urandom of=/var/tmp/randfile bs=1024k count=512 512+0 records in 512+0 records out 536870912 bytes (537 MB, 512 MiB) copied, 2.92359 s, 184 MB/s
Stellen wir in der Beurteilung die streng sequentiellen R/W-Vorgänge und die beim Lesen von /dev/urandom erreichte Performance in Rechnung, ist das Ergebnis durchaus zufriedenstellend.
Ab Linux-Kernel 6.9 (der im gesamten OSL Stack unterstützt wird) steht eine insgesamt beeindruckende Dedup-Engine zur Verfügung. In Verbindung mit geeigneter Hardware scheint sie gewöhnlichen Lastanforderungen allemal gewachsen und punktet mit großen Deduplizierungsraten. In das OSL UVE ist sie über das LFS-Subsystem eingebunden (CLI und GUI) und im Alltag einfach zu handhaben.
Referenzen und Anmerkungen: