Za jídlo, šaty a vzduch otročíme na programech z temných světů

Virtual Data Optimizer

Vzhledem k tomu o jaké věci se zajímám a s jakýma lidma se stýkám, nemůže se nikdo divit, že neznám každou novou technologii. Alespoň tak každoroční linuxová školení, na která mě zaměstnavatel posílí, mají nějaký přínos. Letos jsem si už z prvního dne odnesl poznání, že existuje VDO, neboli Virtual Data Optimizer.

VDO je kernelový modul, který umožňuje lepší využití blokových zařízení. Používá k ve třech po sobě jdoucích krocích tři principy:

  1. Eliminace zero-bloků – hned v první fázi jsou k dalšímu zpracování poslána jen skutečná data, bloky nul jsou uloženy jako metadata a nic nezabírají.
  2. Deduplikace – data bez nulových bloků jsou následně deduplikována, tj. zjišťuje se, zda už někde na disku stejná data jsou. Pokud ano, záznam o dalším jejich výskytu se opět vloží jen do metadat a další místo není zabráno.
  3. Komprese – to, co prošlo až do poslední fáze je opravdu zapotřebí někam na disk zapsat a než se tak stane, je to ještě zapakováno pomocí LZ4.

Vypadá to skvěle, jsou tu ale i jistá úskalí, vše se totiž děje na úrovni blokového zařízení, tedy ještě pod filesystémem. Jelikož se mi podařilo během školení dostat o chlup dál, než vyučující zamýšlel – zvládl jsem VDO vytvořit, zaplnit, rozbít, rozšířit a opravit (cílem přitom bylo zůstat pouze u prvního bodu) – můžu tato úskalí případná ukázat.

Tvorba VDO zařízení

Začněme ale na začátku, na rozbíjení přijde čas později. Vytvoříme si loopback device, na kterém budeme simulovat disk.

# dd if=/dev/zero of=./fakedisk1.img bs=131072 count=65536
# losetup -fP ./fakedisk.img
# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0    7:0    0     8G  0 loop 

Nad loopbackem vytvoříme VDO zařízení, kernelu se to nebude líbit, nerad dělá virtuální věci nad virtuálními věcmi, takže ho přinutíme parametrem --force, ten v reálu není třeba.

# vdo create --name=vdo1 --device=/dev/loop0 --vdoLogicalSize=12G --force
Creating VDO vdo1
Starting VDO vdo1
Starting compression on VDO vdo1
VDO instance 0 volume is ready at /dev/mapper/vdo1

Nad osmigigabajtovým diskem loop0 tedy vytváříme dvanáctigigový virtuální disk vdo1, přičemž to druhé číslo jsme si zcela objektivně vycucali z prstu a doufáme, že to bude v pohodě. Tady je právě to největší úskalí VDO – systém vidí při použití /dev/mapper/vdo1 disk o kapacitě 12 GB, že je založen na fyzickém zařízení o velikosti 8 GB ho vůbec nezajímá, neví o tom. Pokud ukládáte data, která jsou málo duplicitní či špatně komprimovatelná, ke 12 GB se ani nepřiblížíte a nikdo vás neupozorní, že místo došlo. Jen v dmesg se objeví I/O errory a začnou se dít zlé, ošklivé a nepěkné věci.

Teď ale máme krásný, nový disk o jehož kvalitách se můžeme přesvědčit příkazem vdostats:

# vdostats --human-readable
Device                    Size      Used Available Use% Space saving%
/dev/mapper/vdo1          8.0G      4.0G      4.0G  50%           N/A

Toto je jediné místo, kde uvidíte, jak je zaplněno fyzické zařízení. Také zde vidíte, že hned po vytvoření je obsazeno 4 GB místa – to jsou metadata pro fungování VDO, nemá tedy smysl dávat ho na malé disky, chce to alespoň tak velký disk, aby úspora vzniklá kompresí vyrovnala tyto čtyři gigabajty.

Když na novém zařízení vytvoříme filesystém, připojíme ho a koukneme se na jeho parametry, uvidíme jiná čísla:

# mkfs.ext4 /dev/mapper/vdo1
# mount /dev/mapper/vdo1 /mnt/looptest/
# cd /mnt/looptest
# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   12G   41M   12G   1% /mnt/looptest

Používání VDO

A teď nějaké to testování provozu VDO úložiště:

# dd if=/dev/zero of=nuly.bin bs=131072 count=8192
# dd if=/dev/urandom of=bordel1.bin bs=131072 count=4096
# cp bordel1.bin bordel2.bin
# cp bordel1.bin bordel3.bin

Vytvořili jsme čtyři soubory: gigabajtový soubor plný nul, půlgigabajtový soubor plný pseudonáhodného bordelu a dvě jeho kopie. Jak vypadá obsazení disku?

# ls -lh
total 2.6G
-rw-r--r-- 1 root root 512M Nov 19 11:15 bordel1.bin
-rw-r--r-- 1 root root 512M Nov 19 11:15 bordel2.bin
-rw-r--r-- 1 root root 512M Nov 19 11:15 bordel3.bin
-rw-r--r-- 1 root root 1.0G Nov 19 11:14 nuly.bin
 
# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   12G  2.6G  8.6G  23% /mnt/looptest
 
# vdostats --human-readable
Device                    Size      Used Available Use% Space saving%
/dev/mapper/vdo1          8.0G      4.5G      3.5G  56%           80%

Vše je asi dle očekávání pozorného čtenáře v souladu s třemi principy, které jsem popsal v úvodu: filesystém eviduje přes dva a půl gigabajtu dat, VDO ale gigabajt nul uložilo jen jako informaci o tom, že takový soubor existuje, skutečné místo zabírá pouze první půlgigový soubor s bordelem a jeho dvě kopie existují opět pouze v metadatech. Je dobré zmínit, že zařízení založené na VDO se standardně chová jako SSD i když jde fyzicky o plotnový disk. Tedy při mazání nedochází k uvolňování místa, je zapotřebí pravidelně používat fstrim nebo – pokud používáte filesystém, který to umí sám rovnou – připojovat s parametrem discard.

A teď k těm úskalím. Ideální situace pro VDO je, že máte velké pole, které není ani náhodou plné a vy si ho pomocí VDO ještě zvětšíte. Z deseti terabajtů hardwarových máte dvanáct-třináct terabajtů virtuálních a je to v pohodě, protože na nich leží sotva pět terabajtů dat a uživatelé vám přisypou maximálně několik giga dat nových za den. Slunce svítí, kytičky kvetou, ptáčci zpívají, lepší to už ani být nemůže. Může to být už jen horší, pokazit se mohou (mj.) tyto dvě věci:

  1. Může dojít místo na virtuálním disku
  2. Může dojít místo na fyzickém disku

Co s tím ?

Došlo místo na virtuálním disku

Jinými slovy, komprimovalo a deduplikovalo se více, než jste čekali, df -h hlásí plno, ale pomocí vdostats vidíte, že ještě plno není a vaše fyzické úložiště není optimálně využito. Tohle je ta jednodušší situace:

# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   12G  2.6G  8.6G  23% /mnt/looptest
# cd /
# umount /mnt/looptest
# vdo growLogical --name=vdo1 --vdoLogicalSize=13G
# e2fsck -f /dev/mapper/vdo1
# resize2fs /dev/mapper/vdo1
# mount /dev/mapper/vdo1 /mnt/looptest
# cd /mnt/looptest
# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   13G  2.6G  9.5G  22% /mnt/looptest

I když na mém VDO simulovaném nad loopback device místo bylo, zvětšil jsem jeho virtuální kapacitu o jeden gigabajt. Pokud by snad na disk byla i nadále ukládána dobře komprimovatelná data, dá se to opakovat dál a dál.

Došlo místo na fyzickém disku

V tomto okamžiku slunce zašlo za mrak, kytičky spálil mráz a ptáčci chcípli. Když se pokusíte uložit něco na zařízení, jehož filesystém hlásí spoustu volného místa, ale fyzický disk vespod už žádné nemá, nastane peklo. Poslední operace zápisu selže, data se neuloží, vy se to ale na první pohled nedozvíte. Vše totiž z pohledu uživatele proběhne korektně, chyby se objeví pouze v dmesg jako I/O error, disk se následně přepne do read-only režimu a končíte:

# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   13G  5.6G  6.5G  47% /mnt/looptest

# vdostats --human-readable
Device                    Size      Used Available Use% Space saving%
/dev/mapper/vdo1          8.0G      7.4G      0.6G  93%           37%
 
# dd if=/dev/urandom of=grand-finale.bin bs=131072 count=8192
8192+0 records in
8192+0 records out
1073741824 bytes (1.1 GB) copied, 5.31326 s, 202 MB/s
 
# df -h .
Filesystem        Size  Used Avail Use% Mounted on
/dev/mapper/vdo1   13G  6.6G  5.5G  55% /mnt/looptest
 
# vdostats --human-readable
Device                    Size      Used Available Use% Space saving%
/dev/mapper/vdo1          8.0G      8.0G      0.0G 100%           34%
 
# dmesg | tail
[93859.978067]	EXT4-fs warning (device dm-0): ext4_end_bio:302: 
 		I/O error -28 writing to inode 19 (offset 520093696
 		size 8364032 starting block 1750055)
[93859.978071]	Buffer I/O error on device dm-0, logical block 1750055
[93864.336428]	JBD2: Detected IO errors while flushing file data on dm-0-8
[93864.339959]	Aborting journal on device dm-0-8.
[93864.340463]	Buffer I/O error on dev dm-0, logical block 1606659,
 		lost sync page write
[93864.340476]	JBD2: Error -5 detected when updating journal superblock
 		for dm-0-8.
 
#mount | grep vdo1
/dev/mapper/vdo1 on /mnt/looptest type ext4 (ro,relatime,data=ordered)

Pěkné a jak to teď opravit?

V reálném světě bychom přihodili další disk do RAID pole, na kterém máme data fyzicky uložená, počkali až se rebuildne a pak přes něj roztáhli VDO. V naší malé simulaci pomocí loopback device se to dá vyzkoušet taky. Nejdříve si zvětšíme „fyzické úložiště“:

# umount /mnt/looptest
# vdo stop --name=vdo1
# losetup -D
# dd if=/dev/zero of=fakedisk2.img bs=131072 count=16384
# cat fakedisk2.img >> fakedisk1.img
# losetup -fP ./fakedisk1.img
# lsblk
NAME           MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
loop0            7:0    0    10G  0 loop  

Disk je tedy větší, teď je třeba modifikovat VDO a následně ho rebuildnout:

# vdo start --name=vdo1
# vdo growPhysical --name=vdo1
# vdostats --human-readable
Device                    Size      Used Available Use% Space saving%
/dev/mapper/vdo1         10.0G      8.0G      2.0G  80%           34%

A je to, VDO je zase použitelné. Filesystém uvnitř žádnou změnu ani nezaznamenal, od počátku viděl kapacitu jinou, takže nemá problém. Jelikož ale poslední operace nedoběhla správně, je samozřejmě před připojením lepší udělat fsck.ext4. Vzhledem k žurnálovacímu filesystému byste neměli přijít o nic víc, než právě o poslední neúspěšný zápis.


Jak jsem k novinkám obvykle skeptický (Wayland, systemd), tohle se mi líbí. Jde o původně proprietární technologii, kterou RedHat pořídil a otevřel světu. Udělal to relativně nedávno, takže jde zatím o doménu hlavně RHEL, CentOS a Fedory. Z distribucí, které zajímají mě (Slackware, Void, Devuan, Gentoo) jsem nějaké zmínky našel akorát u Gentoo, jak jsou na tom mainstreamové, morem a cholerou prolezlé distribuce, nevím. Jakmile se ale tam možnost objeví, hodím data z domácího mini-RAID-pole někam pryč, hodím na něj VDO a po návratu dat budu zvědav, kolik místa jsem ušetřil.

PS: Tento článek je upraveným archivním souhrnem tří článků, které vyšly na mém stručnějším blogu Technomorous. Pokud byste měli zájem, najdete je zde: 1, 2, 3. Nic víc se v nich ale nedočtete.