Pokud jste se rozhodli pro ZFS, tak asi už víte proč. Jinak napoví Google: ZFS The Last Word in File Systems. V tomto příspěvku spíše upozorním na některá omezení (jak ZFS obecně, tak současné implementace v linuxu) a popíši vlastní použití v případě malé domácí sítě a zálohování dat.
ZFS on Linux nebo ZFS-FUSE?
Používáte-li 64bitovou architekturu, zvolte ZFS on Linux. ZFS-FUSE (také známý jako ZFS for Linux) je s vývojem trochu více pozadu, má omezení daná FUSE a vždy asi bude mít nižší výkon. V současné době (únor 2012) je největším praktickým omezením ZFS-FUSE nemožnost procházet snapshoty – je nutné je nejprve naklonovat (tj. vyžadují extra volný prostor).
Struktura ZFS
ZFS zahrnuje jak práci s logickými svazky (vdev) tak i souborovými systémy (dataset). Typická struktura vypadá následovně:
mypool -- aka zpool mirror -- aka vdev ata-WDC_WD10EARX-00N0YB0_WD-WCC0T0755937 -- fyzický harddisk A ata-WDC_WD10EARX-00N0YB0_WD-WMC0S0037808 -- fyzický harddisk B mirror ata-WDC_WD10EARX-00N0YB0_WD-WCC0T0755222 -- fyzický harddisk C ata-WDC_WD10EARX-00N0YB0_WD-WMC0S0037111 -- fyzický harddisk D
Slovy:
- Úplně nejvyšší vrstva je souborový systém, v ZFS zvaný obecně dataset.
- Datasety jsou obsaženy v zpoolu. Nově vytvořený zpool obvykle automaticky obsahuje i výchozí dataset shodného jména.
- Zpool se skládá z virtuálních zařízení zvaných vdev. Vdev je typu raid0, mirror, raid-z – popisuje tedy i typ případné redundance.
- Vdev se skládá buď z blokových zařízení (celý hdd, diskový oddíl) nebo souborů na jiných souborových systémech (má smysl snad jen při testování).
V případě nevratného poškození jakéhokoliv vdev dojde i ke ztrátě zpoolu. Ve výše uvedeném příkladu je disk B kopií (zrcadlem) disku A a podobně D je kopií disku C. Selže-li současně disk A a D, nic se neděje, neb všechny vdev jsou stále funčkní, byť v degradovaném režimu. Selže-li současně A a B, pak je ztracen i zpool mypool.
Co se moc nezdůrazňuje
Před migrací na ZFS si promyslete, co vlastně chcete: úložiště bez redundance (tj. nemožnost automatické opravy poškozených dat), redundanci v rámci jednoho fyzického disku (copies=2), RAID-1 (mirroring) či vylepšený RAID-5/6 (raidz1, raidz2, či raidz3). Některé změny existující struktury totiž nelze snadno provést a obvykle bývá nutno daný ZFS pool zrušit a data obnovit ze zálohy na nově vytvořenou strukturu.
Například:
- Situace: pool1 mirror sda sdb (tj. mirror se dvěma disky) -> pomocí zpool split pool1 pool2 lze zrušit mirror, vzniknou dva neredundantní pooly pool1 a pool2 a každý bude mít přiřazen jeden z disků sda a sdb. pool2 bude klonem pool1.
- Situace: pool1 sda sdb (tj. neredundantní úložiště rozložené na dva disky) -> příkaz zpool split nelze použít. Ani není jiná cesta, jak uvolnit např. disk sdb, aby šel vyjmout z pool1 a použít někde jinde… Obdobné je to s raidz.
Pravidlo je celkem jednoduché – jakmile jednou vytvoříte nějaké „vdev“, tento už je obvykle neměnný. Více detailů lze nalézt v dokumentaci k Solarisu. Přidávat nové disky či v případě mirror/raidz vyměňovat ty poškozené obvykle není problém, ale ubírat, to už ano.
Vyplatí se několikrát si přečíst ZFS Best Practices Guide, ale i hledat zkušenosti ostatních, např. Home Server: RAID-GREED and Why Mirroring is Still Best, ZFS: Read Me 1st.
Malá domácí síť a zálohování
Je to jako se vším: kompromis mezi náklady (investice, provoz, hluk) a zabezpečením dat. Ceny za GB disků sice klesají (a kvůli povodním v třetím světě občas i rostou), ale ne tak rychle, jak bych si přál; zatím to řeším následovně:
- Pracovní stanice:
- SSD disk pro systém, ext4;
- 2 klasické plotnové disky pro $HOME a sdílená data v konfiguraci raid1 (mirror).
- Malý server:
- notebookový plotnový disk pro systém, ext4;
- klasický plotnový disk pro data, ZFS bez redundance.
- Ostatní počítače (mythtv, atd.), mají obvykle jen jeden disk, ZFS jsem nenasadil.
Ochranu před ztrátou dat kvůli selhání disku řeším zálohami duplicitně na dva externí disky, přičemž:
- každý z těchto disků samostatně pojme data ze všech počítačů v síti;
- na externích discích používám ZFS s maximální kompresí (compress=gzip-9);
- zálohované disky, které používají ZFS, zálohuji pomocí „zfs send | zfs receive“. Jednotlivé snapshoty umožňují přístup ke starším zálohám.
- zálohované disky, které nepoužívají ZFS, zálohuji pomocí rsync s využitím snapshotů ZFS mezi zálohami.
Ochranu před vlastními chybami (tj. ztráta dat kvůli nechtěnému smazání) řeším pomocí skriptu zfs-auto-snapshot. Až na chybějící GUI je to funkčně totéž jako Time Machine – formou automatizovaného vytváření a mazání snapshotů na ZFS discích v počítačích. Více informací ohledně přístupu ke snapshotům viz tento příspěvek v projektu ZFS on Linux (vyžaduje autofs, nefunguje pro zfs-fuse).
Pokud připojujete externí disk, na který je záloha kopírována, ke stejnému počítači, jehož disky jsou zálohovány, vyplatí se:
- vytvořit na tomto externím disku samostatný pool odlišného jména (např backup_pool), než jsou pooly zálohované;
- importovat backup_pool do alternativního přípojného bodu:
# zpool import -o altroot=/media/backup_pool backup_pool
- a nastavit pro tento nejvýše nadřazený souborový systém (tj. pool) uživatelskou vlastnost, která zabrání skriptu zfs-auto-snapshot ve vytváření snapshotů na tomto disku:
# zfs set com.sun:auto-snapshot=false backup_pool
Pro využití inkrementálních záloh na externím disku je třeba „podržet“ snapshot, který byl v minulosti zálohován, i na zálohovaném disku. Tzn., že je poměrně nevhodné zálohovat některý ze snapshotů vytvořený skriptem zfs-auto-snapshot (protože tento dříve či později bude automaticky smazán), ale raději vytvořit ručně vlastní a tento nemazat alespoň do příští zálohy.
Potíže s fragmentací
Kromě nesporných výhod má ZFS i jednu hodně nepříjemnou vlastnost, která je důsledkem zápisu dat systémem „copy-on-write“ (COW). Tou je rostoucí fragmentace úměrně zaplnění poolu. Vysoká fragmentace se projeví velkým počtem IO operací a nízkou přenosovou rychlostí. Rapidní nárůst negativních efektů se obvykle objeví při cca 80% zaplnění poolu. Největší problém nastane při zápisu a současně čtení (i malé IO pro zápis významně ovlivní čtení byť i nefragmentovaných bloků).
Vzhledem k tomu, že ZFS nemá nástroj na defragmentaci, řešením je rozšiřovat pool o další disky (vdev) nebo celý pool a datasety vytvořit znovu ze zálohy. (V případě použití zfs send je zřejmě třeba obnovit pouze poslední stav – tj. bez snapshotů neb ty by do jisté míry obnovily i existující fragmentaci. Dost možná, že ani toto nepomůže a je nutné použít zfs destroy na všechny datasety, ručně je vytvořit znovu a _zkopírovat_ obsah ze zálohy…)
Pomocí debugovacího příkazu zdb a tohoto skriptu fragments.awk lze orientačně zjistit míru defragmentace v datasetu:
# zdb -ddddd mypool/mydataset | gawk --non-decimal-data -f fragments.awk
A nakonec obligátní pamatováček
Vytvoření poolu na dvěma disky v režimu mirror a současně file systému, připojí se do /mypool
# zpool create mypool mirror /dev/disk/by-id/some-disk-id /dev/disk/by-id-some-other-id
další volby:
altroot … všechny podřízené datasety (souborové systémy) budou připojovány pod /altroot. Hodí se pro externí disk, na který se zálohuje. Nejedná se o trvale nastavený přepínač, je třeba jej vždy použít explicitně.
Vytvoření dodatečných, podřízených datasetů v rámci existujícího poolu
# zfs create newdataset mypool
další volby:
mountpoint=/some/path … souborový systém se připojí jinam, než do /mypool (či /altroot).
compression=lz4 … transparentní komprese dat, možno ponechat aktivní pro celý pool, neb obtížně komprimovatelná data nekomprimuje (tj. šetří CPU).
atime=off … vypnutí zápisu času posledního čtení souboru.
Připojení a odpojení poolu
# zpool import -d /dev/kde/je/zfs/disk -o altroot=/media/zaloha backup_pool # zpool export backup_pool
Vlastnost „altroot“ je dočasná a hodí se pro situace, kdy nechceme, aby se importované souborové systémy připojily dle svých vlastností (v případě importu záloh by mohlo dojít ke kolizi s aktuálními přípojnými místy).
Přidání cache pro zpool
L2ARC cache je dočasné úložiště pro ukládání často používaných dat. Vzhledem k rychlé přístupové době je pro tento účel možno využít i např. SD kartu či USB flash disk. Pokud dojde k poškození L2ARC, souborový systém to nijak neovlivní.
# zpool add mypool cache /dev/sdX
Vytvoření swap na ZFS
ZFS primárně nepodporuje swap, nicméně toto omezení lze obejít pomocí vytvoření virtuálního svazku (zařízení připojeného do /dev/zdX).
# zfs create -V 1gb pool/swap # mkswap -L swap /dev/zdX # swapon /dev/zdX
Toto nefunguje se ZFS-FUSE.
ZFS stream
# zfs send pool/dataset@snapshot | ssh root@host -c blowfish zfs receive -v other_pool/other_dataset
Další volby:
zfs receive -nv … nic nekopíruje, pouze ukáže, jak se bude jmenovat pool/dataset@snapshot na cílovém počítači
ssh -c blowfish … použití výpočetně méně náročné šifry urychlí kopírování mezi nevýkonnými počítači.