Portál AbcLinuxu, 26. dubna 2024 08:41
Jedním z největších trháků OpenSolarisu (a vlastností nejvíc propíranou) je souborový systém ZFS a právě o něm bude třetí díl seriálu. Ale nebojte se, zabrousíme i kousek stranou k NFS a CIFS.
Se ZFS, tedy něcoodZ file system je to trochu složitější. To Z v názvu mělo původně znamenat zettabyte, kde zetta je (nepříliš známý) Si prefix pro 10^21, ale to není úplně maximální kapacita ZFS, a krom toho je to dost ošklivé slovo, takže od něj tvůrci později ustoupili a teď se říká, že ZFS prostě proto, že jde o "last word in filesystems" (poslední slovo v oblasti souborových systémů).
ZFS vzniklo tak, že skupinka techniků vedená Jeffem Bonwickem dostala za úkol vytvořit něco nového, bez zpětné kompatibility nejen co se týká API, ale i co se týká samotného přístupu k věci. Podle jejich slov bylo jejich hlavním cílem zbavit se problémů s volume managery a jejich interakce se souborovými systémy, zbavit se nástrojů jako fsck, vylepšit bezpečnost dat, ušetřit práci správcům, a vůbec udělat souborový systém trochu chytřejší, než bylo v kraji zvykem. Nakolik se jim to podařilo, uvidíme podrobně za chvíli, ale pro teď můžu prozradit, že ZFS skutečně je kombinace volume manageru a souborového systému, že je vždycky konzistentní a nepotřebuje fsck, dělá kontrolní součty kdečeho a umí opravovat chyby v datech a spoustu dalších věcí. ZFS nicméně není sdílený ani clusterový souborový systém.
Připadá vám myšlenka kombinovat souborový systém a volume manager šílená? Adrewovi Mortonovi, který stojí za slovním spojením v nadpisu, taková zřejmě připadala. Ono to ale mění víc věcí, než by se mohlo na první pohled zdát, a celé se to váže k věci, které se v marketingových materiálech říká "pooled storage model".
Tedy, místo toho, abyste jednotlivé kusy úložišť (lhostejno jestli levných SATA disků nebo logických jednotek ze síťového pole v ceně menší vilky) přiřadili nějakým svazkům nebo souborovým systémům, všechny je vložíte do jednoho poolu, který je přístupný všem souborovým systémum, a ty mají všechny k dispozici plnou kapacitu a rychlost všech jednotek. Na ukázku si půjčím rpool své stanice:
jakub@ferda:~/zfs$ zfs list NAME USED AVAIL REFER MOUNTPOINT rpool 12.7G 138G 74.5K /rpool rpool/ROOT 3.37G 138G 18K legacy rpool/ROOT/opensolaris-1 3.37G 138G 3.29G / rpool/dump 1023M 138G 1023M - rpool/export 6.28G 138G 21K /export rpool/export/home 3.55G 138G 19K /export/home rpool/export/home/jakub 3.55G 138G 2.73G /export/home/jakub rpool/export/media 2.73G 138G 2.73G /export/media rpool/swap 2G 140G 12.3M -
Ano, rpool, rpool/export, rpool/export/home a další jsou souborové systémy. Je vidět, že pool má 140 GB, 2 GB jsou rezervovány swapu a zbytek je volný, k dispozici pro všechny. Mohu samozřejmě nastavit kvótu nebo rezervovat místo jednotlivým souborovým systémům, ale standardně se nemusím starat o to, jestli jsem náhodou nedal prostoru na média moc místa a nebo udělal root příliš malý. Autoři ZFS rádi používají přirovnání, že ZFS se má k diskům tak, jak se má virtuální paměť k RAM, tam také nemusíte alokovat x MB nějaké aplikaci, stačí přihodit paměť a ta je k dispozici všem aplikacím.
Tomu, že se souborové systémy chovají jako adresáře se budeme věnovat později, teď si pojdmě vytvořit vlastní pool:
jakub@ferda:~/zfs$ mkfile 1g pdsk1 pdsk2 pdsk3 pdsk4 pdsk5 jakub@ferda:~/zfs$ pfexec zpool create tank ~/zfs/pdsk* jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 4.96G 76.5K 4.96G 0% ONLINE - jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: none requested config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk2 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk3 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk4 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk5 ONLINE 0 0 0 errors: No known data errors
Co jsme se dozvěděli? Právě jsem vytvořil pool jménem tank, z pěti "disků" velikosti 1 GB. Pool má velikost necelých 5 GB, takže jde podle všeho o RAID 0. To ale není moc dobrý způsob jak ukládat data, že? Zkusíme to znovu se složeným a trochu bezpečnějším RAIDem.
jakub@ferda:~/zfs$ pfexec zpool destroy tank jakub@ferda:~/zfs$ pfexec zpool create tank mirror ~/zfs/pdsk1 ~/zfs/pdsk2 mirror ~/zfs/pdsk3 ~/zfs/pdsk4 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 1.98G 75K 1.98G 0% ONLINE - jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: none requested config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 mirror ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk2 ONLINE 0 0 0 mirror ONLINE 0 0 0 /export/home/jakub/zfs/pdsk3 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk4 ONLINE 0 0 0 errors: No known data errors
Tady máme RAID 10. (Proč tam pořád píši to "tank"? Jen "zpool status" nebo "zpool list" by fungoval, ale nechci, aby se mi tam pletl dříve zmíněný rpool). Na pdsk5 se nedostalo, protože nemá partnera. Tak mu ho vytvoříme (aby mu nebylo smutno) a předvedeme ještě RAID 5, tady nazvaný RAIDZ1, protože obsahuje mechnismy, které obchází RAID 5 write hole (en.wikipedia.org/wiki/Standard_RAID_levels#RAID_5_Performance). RAIDZ2 je potom RAID 6.
jakub@ferda:~/zfs$ mkfile 1g pdsk6 jakub@ferda:~/zfs$ pfexec zpool destroy tank jakub@ferda:~/zfs$ pfexec zpool create tank raidz ~/zfs/pdsk1 ~/zfs/pdsk2 ~/zfs/pdsk3 raidz ~/zfs/pdsk4 ~/zfs/pdsk5 ~/zfs/pdsk6 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 5.97G 141K 5.97G 0% ONLINE - jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: none requested config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 raidz1 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk2 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk3 ONLINE 0 0 0 raidz1 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk4 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk5 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk6 ONLINE 0 0 0 errors: No known data errors
Máme tedy RAID 50. S disky se dají dělat ale i další kejkle. Mohu udělat z nemirrorované konfigurace mirrorovanou (a naopak) nebo přidat celou skupinu disků do poolu, pokud potřebuji zdalší místo. ZFS umí i nahradit menší disk větším.
jakub@ferda:~/zfs$ pfexec zpool destroy tank jakub@ferda:~/zfs$ pfexec zpool create tank ~/zfs/pdsk1 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 1016M 72K 1016M 0% ONLINE - jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: none requested config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 errors: No known data errors jakub@ferda:~/zfs$ pfexec zpool attach tank /export/home/jakub/zfs/pdsk1 /export/home/jakub/zfs/pdsk2 jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: resilver completed after 0h0m with 0 errors on Sun Mar 8 21:27:13 2009 config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 mirror ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 44K resilvered /export/home/jakub/zfs/pdsk2 ONLINE 0 0 0 70.5K resilvered errors: No known data errors jakub@ferda:~/zfs$ pfexec zpool add tank mirror ~/zfs/pdsk3 ~/zfs/pdsk4 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 1.98G 93K 1.98G 0% ONLINE - jakub@ferda:~/zfs$ zpool status tank pool: tank state: ONLINE scrub: resilver completed after 0h0m with 0 errors on Sun Mar 8 21:27:13 2009 config: NAME STATE READ WRITE CKSUM tank ONLINE 0 0 0 mirror ONLINE 0 0 0 /export/home/jakub/zfs/pdsk1 ONLINE 0 0 0 44K resilvered /export/home/jakub/zfs/pdsk2 ONLINE 0 0 0 70.5K resilvered mirror ONLINE 0 0 0 /export/home/jakub/zfs/pdsk3 ONLINE 0 0 0 /export/home/jakub/zfs/pdsk4 ONLINE 0 0 0 errors: No known data errors jakub@ferda:~/zfs$ pfexec zpool destroy tank jakub@ferda:~/zfs$ pfexec zpool create tank ~/zfs/pdsk1 ~/zfs/pdsk2 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 1.98G 75K 1.98G 0% ONLINE - jakub@ferda:~/zfs$ mkfile 2g ndsk1 ndsk2 jakub@ferda:~/zfs$ pfexec zpool replace tank ~/zfs/pdsk1 ~/zfs/ndsk1 jakub@ferda:~/zfs$ pfexec zpool replace tank ~/zfs/pdsk2 ~/zfs/ndsk2 jakub@ferda:~/zfs$ zpool list tank NAME SIZE USED AVAIL CAP HEALTH ALTROOT tank 3.98G 94.5K 3.98G 0% ONLINE -
Jak je vidět, když nahradím oba disky většími, kapacita poolu se zvýší. Umí tohle váš volume manager?
Co je nepříjemné, je, že ZFS neumí odstranit zařízení z poolu. Vyměnit ho za jiné nebo udělat ze zrcadlené konfigurace nezrcadlenou jde, ale pokud si vytvořím (dejme tomu) RAID 0 ze dvou disků, už z něj nikdy jeden disk neudělám. Údajně se na tom pracuje (v TODO listu již je to dlouho, ale teď to prý začalo vadit nějakému velkému zákazníkovi, takže na tom někdo skutečně začal dělat), ale ve spoustě použítí to nevadí.
Jaké má tohle propojení výhody, krom toho, že nemusím přemýšlek, kolik místa kam přiřadit? No, hlavní důsledky jsou dva, rychlost a bezpečnost. Tady v psaných příkladech to není vidět, ale pokud vytvořím nový pool, mám ho hned a nemusím počkat, až systém sesynchronizuje disk, protože ZFS samozřejmě ví, že v prázdném poolu není co synchronizovat. A když budu měnit vadný disk za jiný a v poolu mám 100 GB dat, bude ZFS kopírovat jen 100 GB dat, i když půjde o terabytové disky. Pokud jde o bezpečnost, ZFS dělá kontrolní součty kde čeho, a pokud narazí na to, že je nějaký kontrolní součet špatně, zkusí vzít data z jiného místa a taktně upozorní správce, že s diskem by mohlo být něco v nepořádku. Pokud žádné jiné misto, ze kterého by šlo vzít data, není, odmítne data vydat úplně -- politika Solarisu je v tomhle oznámit chybu a zastavit běh aplikace, raději než vydat špatná data, která by mohla vést k naprosto nepředvídatelému (a třeba také nikdy neodhalenému) chování.
Jen malá odbočka. Jak vlastně vypadá ZFS uvnitř? Proč nepotřebuje fsck, jak ručí za správnost dat? Když to zjednoduším (a vypustím nižší vrstvy), ZFS vypadá jako strom. Co je ale zajímavé, je to, že jde o strom, který zhusta praktikuje copy-on-write, a kvůli tomu zůstává konzistentní napříč různými operacemi.
Dejme tomu, že se rozhodnu vytvořit nový soubor ve svém domovském adresáři. Vytvořím soubor, souborový systém uloží jeho datové bloky a vytvoří nový blok pro adresář, do kterého nový soubor ukládám, uloží ho někam do volného místa a původní adresář nechá, kde byl. Takhle bude postupovat, dokud nevytvoří aktualizovanou kopii kořenového adresáře a nezapíše ji do superbloku. Tohle je první chvíle, kdy se něco přepisuje, a jde o atomickou operaci. Takže jsem buď úspěšně uložil nový soubor a mám nový kompletní a konzistentní strom (ZFS zapisuje superblok, až když si je jisté všemi nižšími úrovněmi), nebo mi někde v průběhu vypadl proud a pak se sice nový soubor nezapsal, ale superblok pořád úspěšně odkazuje na předešlou a neporušenou verzi dat.
Všechny vrstvy stromu mají kontrolní součty a ukládají se ve více kopiích (standarně mají data jednu kopii, metadata 2 + počet kopií dat, jde to ale změnit). Pokud bych měl ale o konzistenci dat pochybnosti, mohu požádat pool, aby se "vykartáčoval" pomocí zpool scrub, systém potom projde všechna data a přepočítá jejích kontrolní součty, a pokud neodpovídají, opraví je z replik. Manuál doporučuje kartáčovat disky pravidelně, každý týden až měsíc.
Pokud jde o pořadí operací, ZFS dává přednost čtení a zápisy si řadí do fronty a provede je, až když už v ní visí dlouho, nebo když nemá co dělat. Logika za tím je ta, že nikoho nezajímá kdy proběhne zápis, zatímco na čtení obvykle někdo čeká. Co když ale někdo chce, aby byl zápis zcela jistě proveden, než mu ZFS vrátí úspěch? K tomuhle slouží ZIL, ZFS Intent Log. Funguje trochu jako žurnál, tedy asynchronní zápisy se uloží do RAM, synchronní zápisy putují do ZILu a jsou ihned zapsány na disk, a když má ZFS čas, zapíše je na disk a smaže ze ZILu. Pokud by náhodou (například) vypadl proud a ZFS je nemohlo normálně zapsat, přehraje ZIL při příštím importu poolu a splní tak, co slíbilo. ZIL se normálně nachází na discích poolu, ale mohu ho umístit na jiné zařízení, třeba SSD nebo nějakou NVRAM, pokud bych chtěl zrychlit synchronní zápisy.Začneme snapshoty. Vytvořit souborový systém je snadné, vytvořit snapshot také.
jakub@ferda:/tank# zfs create tank/testy jakub@ferda:/tank# zfs snapshot tank/testy@testovaci-snapshot jakub@ferda:/tank# zfs list -r -t all tank NAME USED AVAIL REFER MOUNTPOINT tank 130K 1.95G 19K /tank tank/testy 18K 1.95G 18K /tank/testy tank/testy@testovaci-snapshot 0 - 18K -
Snapshoty jsou jen ke čtení a standardně se vytvoří jen pro jmenovaný souborový systém, ne pro jeho podsystémy, můžeme ale požádat o rekurzivní snapshot přídáním "-r". Nezabírají teméř žádné místo, dokud původní data nezmění, a potom zabírají jen tolik místa kolik zabírají změny. Ze snapshotu mohu vytvořit klon, tedy snapshot, do kterého je možné zapisovat. Ke snapshotu se lze vrátit pomocí zfs rollback a k jejich likvidaci (stejně jako k likvidaci nepohodlných souborových systémů) poslouží zfs destroy.
Souborové systému maji spoustu vlastností, které se dědí. Dostat se k nim dá pomocí zfs get all pool/fs. Je jich spousta a manuálová stránka zfs obsahuje jejich vysvětlení, ale pár jich za zmínku stojí.
Všechny tyhle vlastnosti se aplikují jen na nové nebo změněné soubory, je to znát hlavně u komprese a recordsize, nastavení vlastnosti magicky "nepřechroustá" všechna data.
Sliboval jsem NFS a CIFS, že? U NFS je to jednoduché, zfs set sharenfs=on pool/fs nebo častěji zfs set sharenfs=rw se postará o všechno, co potřebujete (tedy mimo zabezpečení). Systém sám nastartuje služby potřebné pro NFS server, pokud neběží (pokud souborový systém odsdílíte, nevypne je, ale při příštím restartu se nezapnou pokud nebudou potřeba). U CIFS je to trochu složitější, protože je potřeba nastavit pracovní skupinu a přenastavit PAM, aby generoval hesla použitelná pro CIFS, protože CIFS server integrovaný v jádře OpenSolarisu neumí anonymní režim jako Samba, ale zfs set sharesmb=on je vaším přítelem. Jestli se všechno vyexportovalo, jak mělo, vám napoví utilita sharemgr. Mezi vlastnostmi lze najít i shareiscsi, ale tím se tu nebudu zabývat, protože je na cestě přepracovaný systém pro exportování svazků a v příští verzi (tedy za měsíc) už tahle možnost pravděpodobně nebude existovat.
Kdyz jsem ukazoval rpool, byl tam vidět také swap a dump prostor (prostor pro crashdumpy). Neměly mountpoint a pravděpodobně to nejsou souborové systémy, jak to? Je to tak, jsou to virtuální svazky, které lze pomocí ZFS tvořit. Konkrétně zfs create -V velikost cesta, svazek se pak objeví v /dev/zvol/dsk/cesta. Krom toho, že je můžeme exportovat, dělat snapshoty, klony, nakonfigurovat je, aby byly komprimované, a vůbec s nimi provádět psí kusy (tedy všechno, co jde se souborovými systémy), jde pomocí parametru -s vytvořit i "sparse volume", tedy vytvoří se svazek, ale místo pro něj se nerezervuje. Ve storage terminologii se tomu říká thin provisioning a je to užitečná funkce (můžete ze dvou 500GB disků rozdistribuovat klientům několik TB), ale říkáte si o hrozivé problémy, pokud vám dojde místo (SCSI write chyby a tak).
Předposlední vychytávka. ZFS poměrně agresivně cachuje data. Ale každá RAM je malá, disky jsou velké a dat je hodně. ZFS umí přidat k poolu cachovací zařízení. Funguje to tak, že když ZFS dochází paměť v RAM a potřebuje z ní vyhodit nacachovanou stránku a přesto má pocit, že by mohla být v budoucnu potřeba, přesune ji do cache druhé úrovně (neplést s L2 cache procesoru). Dobrým HW pro tyhle účely jsou SSD, jsou o hodně rychlejší než klasické disky, a přitom často nemají kapacitu na to, aby se jimi daly klasické disky nahradit, a o 128 GB cache člověk jen tak nezavadí.
A úplně nakonec, říkal jsem, že o místa, kam se připojuje ZFS, se nestará fstab a mount. Jak se tedy zbavit poolu, jinak než ho zničit nebo vypnout počítač? Co když budu potřebovat odpojit pool s daty a přenést ho jinam? To samozřejmě jde i za chodu (pokud to tedy není rpool) příkazem zpool export. Opakem je pak zpool import, který prohledá všechny disky a poohlédne se po poolech. Je možné mu napovědět, na kterých discích hledat, nebo stanovit alternativní název (dva rpooly by nedělaly dobrotu) nebo kořenový adresář pro imporovaný pool.
To je pro dnešek vše. Přístě budou sítě, služby a balíčkovací systém.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.