Unsere clusterfähige Speichervirtualisierung stellt global verfügbare Block-Devices typischerweise in einem einzigen Namespace zur Verfügung und bietet obendrein Funktionen wie ein automatisches Zugriffsmanagement, Live Storage-Migration, systemgestützte Allokation u. v. m. Intern wird mit einer direkten Block-Level-Virtualisierung unter Umgehung von Filesystemen gearbeitet. Die Vorteile (es geht dabei auch immer um große OLTP-Systeme) liegen auf der Hand.
Vorteile von Raw-Devices:
- sehr direkte Ansprache der Hardwarefähigkeiten → wenig Overhead / starke Performance
- optimaler Multiplattform-Support – "raw" wird von allen Betriebssystemen und Hypervisoren verstanden
- überzeugende Handhabung in Clusterumgebungen
- unkompliziert bei Backup und Restore, auch in Problemfällen.
Diese Vorteile spielen auch in VM-Umgebungen, etwa beim OSL UVE, eine Rolle. Typischerweise sprechen vollvirtualisierte VMs den bereitgestellten Massenspeicher als Block-Device und nicht als Filesystem an. Unser Raw-Device-Ansatz erübrigt so mehrfache Block-Redirektionen oder gar Veränderungen der Blockungsgröße im Request. Auch für die Live-Migration stellen Raw-Devices eine für allen bekannten Hypervisoren nutzbare solide und problemlose Technologie dar.
Im normalen Allzwecksystem nutzen Anwendungen in der Regel Dateisysteme. Sie ermöglichen erst eine komfortable Handhabung (Auffinden der Daten, strukturierte Ablage, Zugriffsmanagement, feingranulare Allokation usw.). Das bedingt eine höhere Komplexität und beeinträchtigt die Performance, wobei letzteres durch ausgeklügelte Caching-Verfahren und eine enge Verknüpfung mit dem Kern oft in weitem Umfang ausgeglichen werden kann. Dies gilt so ohne weiteres jedoch nur für lokale Dateisysteme. Clusterdateisysteme sehen sich einer Vielzahl von eigentlich schwer vereinbaren Anforderungen gegenüber - die "Quadratur des Kreises" gelingt meist nur unvollständig. Speziell in VM-Umgebungen hat sich allerdings der dateibasierte Ansatz durchaus etabliert, vor allem da, wo es nicht um allerhöchste Performance geht.
Vorteile der dateibasierten Block-Device-Emulation im Hypervisor:
Daten-Fragmentierung, zumindest theoretische Performanceeinbußen, komplexere Herausforderungen beim Clustering und bei der Live-Migration und größere Auswirkungen bei Hardwareausfällen oder Störungen der Filesystemintegrität sind die Kehrseite, die die Platzhirsche jedoch für die wichtigsten, alltäglichen Aufgaben so gut im Griff haben, daß Zufriedenheit bei den Anwendern vorherrscht. Die meisten Disk-Image-Formate arbeiten mit Blockzuordnungstabellen innerhalb der Datei. Daneben führt das verwendete Dateisystem davon unabhängige, eigene Zuordnungstabellen. Bezieht man diese Mehrfach-Redirektionen in die Betrachtung mit ein, ist es bemerkenswert, daß die Performance in der Praxis zumeist "stimmt".
Speziell der Aspekt durch Software künstlich gesteigerter Speichereffizienz kann durch einen blockbasierten Treiber schwerlich bedient werden. Falls doch, so wäre der Aufwand immens hoch, vergleichbar mit der Implementierung eines Dateisystems. Die Performancevorteile eines blockbasierten Treibers wären dahin. Sie aufzuwiegen gelänge nur mit einer sehr tiefen Integration mit dem Betriebssystemkern, was dem für OSL wichtigen Prinzip der Plattformneutralität widerspräche. So lag es also nahe, sich auf eines der wichtigsten Unix-Prinzipien zu besinnen: "Baue auf die Arbeit anderer auf."
Auf den von OSL SC und UVE unterstützen Plattformen stehen ausgereifte und performante Dateisysteme zur Verfügung, die - auch losgelöst von VM-Imageformaten - die notwendigen Funktionen bieten, aufgrund der tiefen Integration ins Betriebssystem oft sogar mit besserer Performance.
Abweichend vom Prinzip des Shared-Storage-Clusters, das der OSL-Speichervirtualisierungsengine eigentlich zugrunde liegt, fügen wir nun die Möglichkeit hinzu, lokalen Massenspeicher direkt in die Virtualisierung einzubinden.
Die Abbildung zeigt im linken Teil einen klassischen Storage-Cluster mit zentralem RAID-Speicher. Node 2 verfügt daneben über lokalen Filesystemspeicher. Mit den Bordmitteln des Betriebssystems oder per Hardware kann das Dateisystem gegen Plattenausfälle geschützt werden. Das Dateisystem selbst agiert nun als Storage-Pool, in dem Dateien an die Stelle sonst verwendert LUNs oder Festplatten treten. Die rechte Seite zeigt, wie ein Dateisystem mit 8TiB Netto-Kapazität 2 Physical Volumes mit je 10 TiB virtuellem Speichervolumen, insgesamt also 20 TiB darstellen kann. Die schematische Darstellung zeigt, wie nur geschriebene Blöcke der jeweiligen Physical Volumes auf Datenblöcke im entsprechenden Dateisystem gemappt werden, der Rest bleibt frei und liefert beim Lesen Null-Bytes. Zu beachten ist, daß die Applikationen "Green" und "Red" - anders als die anderen Applikationen, die ausschließlich Shared Storage nutzen - nicht ohne weiteres auf einen anderen Knoten migriert werden können. Dies, weil ihre Daten, wie im Schaubild zu sehen, ganz oder teilweise nur lokal gespeichert sind.
Im folgenden wird der Umgang mit dem LFS-Subsystem in einer Beispielsession in einem OSL Unified Virtualisation Environment gezeigt. In der LFS-Logik tritt ein Dateisystem an die Stelle einer Physical Volume Group, hier "lfs1". Wir erzeugen zunächst auf dem UVS in einem Dateisystem mit einer Nettogröße von ca. 8GiB ein emuliertes Physical Volume "lfs1-0" mit einer Größe von 16GiB:
uvs48-1# df -h | grep lfs /dev/sdb1 8.4G 3.6M 7.9G 1% /dvsc/lfs/lfs1 uvs48-1# pvadmin -c lfs1-0 -S 16g -g lfs1 -o sparse INFO (pvadmin): creating file ... INFO (pvadmin): file creation done lfs1's overcommit rate is 1.91 : 1, usage 6% uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 3648k 8069m+ 1% 1.91 lfs1-0@0 16g 8k - 0% -
Durch das Anlegen des über die Kapazität des Dateisystems hinausgehende Physical Volumes beträgt die "overcommit rate - ocr" in diesem Pool 1,91:1, die reale Auslastung des Dateisystems jedoch nur 1%.
Nach dem "Refresh" der Speichervirtualisierung ("dvboot") fahren wir mit dem Anlegen eines Application Volumes - hier des Root-Volumes für eine VM mit 8GiB Größe - fort.
uvs48-1# dvboot ... uvs48-1# pvadmin -lvvh lfs1-0 0 lfs1-0 (ok) 16g over 1 path(s) >[ 1] (ok) /dvsc/lfs/lfs1/lfs1-0@0 uvs48-1# smgr -c vm1_root -S 8g lfs1-0
Nachfolgend wird ein Linux in der vm1 mit dem Root-Volume vm1_root installiert. In der VM wurden 1,2GiB für Swap zugewiesen, ansonsten stellt sich der Speicherverbrauch nach der Installation wie folgt dar:
vm1# df -h Filesystem Size Used Avail Use% Mounted on /dev/vda2 6.8G 2.4G 4.2G 37% / devtmpfs 981M 0 981M 0% /dev tmpfs 989M 0 989M 0% /dev/shm tmpfs 989M 9.5M 979M 1% /run tmpfs 989M 0 989M 0% /sys/fs/cgroup
Per "lfsadmin" prüfen wir wieder die Auslastung von Volume und LFS-Pool auf dem UVS:
uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 2806m+ 5323m+ 35% 1.91 lfs1-0@0 16g 2544m+ - 15% -
Während in der VM nur 2,4GiB belegt sind, beansprucht das Physical Volume 2,8GiB. Das rührt daher, daß im Root-System der VM während der Installation beanspruchter zusätzlicher Speicher wieder freigegeben worden ist, was jedoch nicht zu einem Update dieser freigegebenen Datenblöcke auf dem emulierten PV führt.
Die Implementierung des entsprechenden Backends in den OSL Virtual Storage Domains (VSD) beherrscht auch die Deallokation von Datenblöcken, die nur Null-Bytes beinhalten. Um dabei möglichen Problemen (vgl. lwn.net/Articles/864363/) bestmöglich entgegenzuwirken, werden eine Reihe zusätzliche Maßnahmen im Treiber unternommen. Um die Wirkungsweise der Deallokation zu illustrieren, füllen wir zunächst das Dateisystem (in der VM) mit Daten und erzeugen 10 tar-Archive des Verzeichnisses /usr/bin unter /home:
vm1:/home # ls -lh total 1.4G -rw-r--r-- 1 root root 134M Jul 29 00:37 bin0.tar -rw-r--r-- 1 root root 134M Jul 29 00:35 bin1.tar -rw-r--r-- 1 root root 134M Jul 29 00:35 bin2.tar -rw-r--r-- 1 root root 134M Jul 29 00:36 bin3.tar -rw-r--r-- 1 root root 134M Jul 29 00:36 bin4.tar -rw-r--r-- 1 root root 134M Jul 29 00:36 bin5.tar -rw-r--r-- 1 root root 134M Jul 29 00:36 bin6.tar -rw-r--r-- 1 root root 134M Jul 29 00:36 bin7.tar -rw-r--r-- 1 root root 134M Jul 29 00:37 bin8.tar -rw-r--r-- 1 root root 134M Jul 29 00:37 bin9.tar
Der Blick auf Pool und Volume zeigt eine gestiegene Auslastung, die sich auch durch das Löschen der Dateien in der VM nicht ändert:
uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 4124m+ 4020m+ 51% 1.91 lfs1-0@0 16g 3799m+ - 23% - vm1:/home # rm *.tar vm1:/home # du -sh . 4.0K . uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 4125m+ 4020m+ 51% 1.91 lfs1-0@0 16g 3799m+ - 23% -
Bewegung kommt allerdings in die Sache, wenn wir nun tatsächlich Nullen auf die Platte schreiben. Die Herausforderung besteht dabei darin, es nicht zu übertreiben, weil die hier geschriebenen Daten aus Sicht des Gast-Systems dessen Dateisystem füllen bzw. sogar überfüllen können.
vm1:/home # dd if=/dev/zero of=zerofile bs=1024k count=4000 4000+0 records in 4000+0 records out 4194304000 bytes (4.2 GB) copied, 24.4122 s, 172 MB/s vm1:/home # df -h . Filesystem Size Used Avail Use% Mounted on /dev/vda2 6.8G 6.3G 204M 97% / uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 2909m+ 5227m+ 36% 1.91 lfs1-0@0 16g 2635m+ - 16% -
Mit diesem Kunstgriff sind wir wieder in der Sparse-Welt angekommen. Während aus Sicht des Gastes 6,3 GiB verbraucht sind, sind es im LFS-Pool auf dem UVS nur noch 2,9GiB. Ein Löschen der Datei "zerofile" gibt den entsprechenden Platz im Gast wieder frei, auf dem UVS uns seinem LFS-Pool ändert sich indes nichts.
Mit der Live-Migration der OSL Virtual Storage Engine ist es nun auch bei laufender VM bzw. Applikation möglich, zwischen verschiedenen Speichertypen zu wechseln. Nachfolgend wird gezeigt, wie ich bei laufender VM von lokalem auf globalen (shared) Storage wechseln kann. Dazu wird ein Shadow-Volume angelegt, das die neue Datenlokation definiert und in einem zweiten Schritt das Root-Volume dorthin migriert:
uvs48-1# smgr -c shadow -S 8g d00 uvs48-1# avmove vm1_root shadow
Der Abschluß der Migration wird uns im Clusterlog angezeigt, hier mit einer Geschwindigkeit von 292MiB/s (nicht dargestellt). Das Volume befindet sich nun im “Shared Storage“ auf dem Physical Volume “d00“:
uvs48-1# avadmin -lvv vm1_root 0 vm1_root 16777216 of 16777280 blocks "simple" in 1 pieces, 32 block clusters [ 1] d00 [9284096...26061375]
Das in der bisherigen Session verwendete Dateisystem war btrfs, das auch Datenkompression beherrscht. Um letztere auf das gesamte Root-Volume von “vm1“ anzuwenden, verwenden wir wieder die Live-Datenmigration der Storage-Engine, schalten jedoch zunächst für das Physical Volume die Datenkompression ein:
uvs48-1# btrfs property set /dvsc/lfs/lfs1/lfs1-0@0 compression zlib uvs48-1# btrfs property get /dvsc/lfs/lfs1/lfs1-0@0 compression compression=zlib uvs48-1# smgr -c shadow -S 8g lfs1-0 uvs48-1# avmove vm1_root shadow
Die Synchronisation läuft diesmal mit einer Geschwindigkeit von nur 130MiB/s. Das ist immer noch ordentlich, zeigt jedoch an, daß die Kompression tatsächlich Zeit braucht. Das Root-Volume von “vm1“ liegt nun wieder im LFS-Pool. Interessant ist insbeondere, was jetzt die Pool- und Volumestatistik anzeigt:
uvs48-1# avadmin -lvvh vm1_root 0 vm1_root 8192m of 8192m+ "simple" in 1 pieces, 16k clusters [ 1] lfs1-0 [0...16777279] uvs48-1# lfsadmin -lph group/volume total used avail pct ocr lfs1 8598m+ 1712m+ 6418m+ 22% 1.91 lfs1-0@0 16g 2558m+ - 15% -
Et voilà: Das Root-Volume von “vm1“ beansprucht bei einer scheinbaren Größe von 8GiB effektiv nur noch 1,7GiB in unserem LFS-Pool. Interessant ist, daß die Kompression für das PV selbst unsichtbar ist. Auf diesem Layer stellt sich der Speicherverbrauch einschließlich Sparse-Funktionalität mit 2,5GiB dar.
Je nachdem, was einem wichtig ist, kann man zwischen maximaler Performance und maximaler Effizienz mit mehreren Zwischenstufen (sparse, compression) den für das jeweilige Anwendungsszenario passenden Kompromiss wählen. Dank Live-Migration ist man dabei nicht endgültig festgelegt, sondern kann bei Bedarf auch die Speicherklasse ändern.
An diesem Punkt stellt sich die Frage: Wie weiter, wenn der lokale Knoten ausfällt? Klar ist, daß sich dieses Problem ohne Replikation auf Speicher außerhalb des Knotens nicht lösen läßt. Sowohl OSL Storage Cluster als auch OSL UVE verfügen jedoch über die entsprechenden Möglichkeiten, um das zu lösen. Die Grafik zeigt schematisch die LFS-Integration in einem redundant ausgelegten Slim-UVE.
Im Slim-UVE (d. h. ohne externen Shared Storage) werden die internen Platten der UVS per RSIO auf dem jeweils anderen UVS dargestellt, so daß dieser die Platten wie lokale Platten, also auch für die Spiegelung von Application Volumes nutzen kann.
Das gleiche Prinzip wird nun auch auf Physical Volumes in LFS-Pools angewendet. Sie werden auf dem anderen UVS als “remote“ Physical Volume dargestellt und können z. B. als Teil einer Spiegelkonfiguration genutzt werden. Auf diese Art kann sichergestellt werden, daß die Daten auch bei Ausfall eines UVS mit seinem internen Speicher / LFS weiter verfügbar bleiben. Anzumerken ist noch, daß Physical Volumes in der täglichen Arbeit sich immer gleich verhalten, egal ob sie nun über lokale Platten, remote Disks, SAN-LUNs oder die LFS-Emulation realisiert sind. So ist es auch möglich, die LFS-Pools eines UVS auf LFS-Pools des anderen UVS zu spiegeln.
Die UVC (Unfied Virtualisation Client, das sind die Knoten, auf denen die Vms laufen) bekommen von all diesen “Tricks“ nichts mit. Ihr I/O-Stack ist auf maximale Performance und minimale CPU-Belastung optimiert. Sie haben nichts mit Sparse, Dateisystemen und/oder Datenkomprimierung zu tun, sondern greifen auf die Dienste der UVS zurück.
Die OSL Virtual Storage Engine benutzt eigene, auf den Anwendungszweck “clusterfähige Block-Level-Virtualisierung“ hin optimierte Datenformate. Auch bekannte Volume-Manager verwenden intern bestimmte proprietäre Abbildungsverfahren. Will man mit großen Datenbeständen von einem bisher verwendeten Volume-Manager auf die OSL-Engine wechseln, dann kann das durchaus eine Herausforderung sein, denn unter Umständen kommt man an einer mehr oder weniger zeitaufwendigen Datenkopie nicht vorbei.
Das LFS-Subsystem bietet hier nun eine neue Möglichkeit: Vorhandene fremde Devices können in einen LFS-Pool importiert werden. Ein Application Volume über das gesamte importierte Gerät hinweg bringt dieses ohne weitere Umwandlung in die OSL Virtual Storage Engine. Die Anwendung kann damit sofort gestartet werden und die eigentliche Storage-Migration kann bei laufender Anwendung im Hintergrund stattfinden.
Für die Beispielsitzung verwenden wir als Platzhalter für einen externen Volumemanager ein Loopback-Device und haben vor dem Beginn der Migration darauf ein Dateisystem erzeugt und darin Dateien angelegt. Nach dem Import des Gerätes erfolgt die bereits bekannte Live-Migration über ein Shadow-Volume.
uvs48-1# pvadmin -i loop@0=/dev/loop1 -g lfs1 lfs1's overcommit rate is 1.91 : 1, usage 25% uvs48-1# dvboot ... uvs48-1# pvadmin -lvvv loop@0 0 loop (ok) 204800 blocks over 1 path(s), 0 io >[ 1] (ok) /dvsc/lfs/lfs1/loop@0 [0...204799], 0 io uvs48-1# smgr -c av-loop -S 204800 -F lsimple loop uvs48-1# mount /dev/av0/av-loop /mnt uvs48-1# ls -l /mnt total 13 -rw-r--r-- 1 root root 11 Jul 29 23:09 datei -rw-r--r-- 1 root root 0 Jul 29 23:07 hallo drwx------ 2 root root 12288 Jul 29 23:05 lost+found uvs48-1:/mnt # cat /mnt/datei Probedaten uvs48-1# smgr -c shadow -S 204800 d00 uvs48-1# avmove av-loop shadow INFO (avmove): moving in universe 0 from av-loop to shadow uvs48-1# avadmin -lvv av-loop 0 av-loop 204800 of 204864 blocks "simple" in 1 pieces, 32 block clusters [ 1] d00 [20544...225407] uvs48-1# pvadmin -x loop
Die Session verdeutlicht, daß direkt nach dem Import des Gerätes über die Storage Engine darauf zugegriffen werden kann, daß die Daten gefunden werden und bei laufender Anwendung (hier montiertem Dateisystem) die Daten auf ein natives Format im globalen Datenpool verschoben werden können. Am Ende kann das Device wieder exportiert (und ggf. gelöscht) werden.
Mit dem LFS-Subsystem werden interessante Leistungsmerkmale moderner Filesysteme, wie etwa Sparse Files (Überallokation) und Datenkompression auch für die Blockdevices in der clusterfähigen Storage-Engine von OSL nutzbar. Man hat somit mehr Möglichkeiten, den passenden Kompromiss zwischen Performance, Portabilität und Storage-Effizienz zu wählen. In Verbindung mit der RSIO-Technologie wird der “Local File Storage“ trotzdem global nutzbar und kann mit den bekannten Spiegelmechanismen auch gegen Ausfälle abgesichert werden. Die Live Storage Migration ermöglicht darüber hinaus auch Umwandlungen zwischen verschiedenen Speicherklassen im laufenden Betrieb.