Portál AbcLinuxu, 26. dubna 2024 08:41

OpenSolaris - 3 (ZFS)

17. 3. 2009 | Jakub Jirků
Články - OpenSolaris - 3 (ZFS)  

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.

Co je ZFS?

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.

Rampant Layering Violation?

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í.

Trochu o vnitřnostech

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.

Filesystém jako adresář?

Dlužím vám vysvětlení ohledně toho, že jsou souborové systémy jako adresáře. Tomu, že si všechny berou místo ze společného poolu, jsme se už věnovali, takže teď je jen stačí hierarchicky uspořádat a máme to. Souborový systém v podání ZFS je tedy chytřejší adresář, se kterým se dají dělat kejkle. Krom toho, že na první pohled vidíme, kolik místa zabírá. Souborových systémů můžeme teoreticky vytvořit, kolik chceme (tedy přesněji 2^48, což je skoro totéž), ale není dobré to přehánět, spousta algoritmů v systému pracuje v O(počet souborových systému), takže stroj s desítkami tisíc souborových systémů nebude startovat zrovna rychle (ale je přislíbeno něco s tím udělat na další verzi). Když vytvořím pool, standardně se mi vytvoří první souborový systém, který se jmenuje stejně jako pool, a připojí se do /jméno_poolu.

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.

Drobnosti na závěr

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.

Příště

To je pro dnešek vše. Přístě budou sítě, služby a balíčkovací systém.

Seriál OpenSolaris (dílů: 4)

První díl: OpenSolaris - 1 (historie, představení), poslední díl: OpenSolaris - 4 (síť, služby, balíčky).
Předchozí díl: OpenSolaris - 2 (základy)
Následující díl: OpenSolaris - 4 (síť, služby, balíčky)

Související články

Tvorba balíčků pro Solaris
Solaris patchování - opravy nainstalovaných balíčků
Solaris 10 a zóny
Co je na tom Solarisu 10 tak úžasného!?
OpenBoot Prompt
Java pod GPL
Rich Green, viceprezident Sunu o open source

Odkazy a zdroje

opensolaris.org

Další články z této rubriky

Týden na ITBiz: Svět IT a burzy, umělá inteligence, Nvidia a outsourcing
Linuxové foto novinky: pozvolná evoluce
PCLinuxOS 2017.2 MATE - tak trochu zvláštní linuxová distribuce
Krátký pohled na Fedoru 25, Wayland a GNOME 3.22
Naprosto ničím nezajímavé Lubuntu 16.10

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.