BTRFS v praxi po 5 letech

Letos tomu bude 5 let, co jsem začal trvale používat systém souborů BTRFS. Po článcích z roku 2011 BTRFS Teorie a BTRFS Praxe, bych chtěl dnes shrnout některé vlastnosti, které ve své praxi považuji za nejužitečnější a které běžně používám. Některé věci se budou opakovat ze dřívějších článků, tam jsem se snažil přidat další pohled po létech.

Snapshoty

Tuhle vymoženost BTRFS snad nelze přechválit :-). Používám ji takřka denně.

Snapshot je atomické zachycení stavu subvolume v čase. Velkou výhodou je, že snapshot subvolume v BTRFS je také subvolume. Nic nám tedy nebrání dělat snapshot „snapshotu“. Na rozdíl od některých jiných systémů je snapshot nezávislý. Můžeme tedy bez problémů smazat subvolume, ze které snapshot vznikl. A především, z hlediska userspace není subvolume (a tedy i snapshot) nic jiného než adresář (či přesněji řečeno něco jako mountpoint).

Např:

btrfs sub snap tomas tomas.snap
 Create a snapshot of 'tomas' in './tomas.snap'

Během zlomku sekundy mám k disposici snapshot svého domovského adresáře. Mohu vyzkoušet nějakou nebezpečnou činnost. Kdykoliv se můžu vrátit.

Stejně jako subvolume tedy můžeme libovolný snapshot připojit kamkoliv do systému (budeme potřeboval jeho subvolid, to získáme z výpisu btrfs subvolume list /mnt/btrfs_pool):

mount /dev/disk /mnt/pripojnybod -o subvolid=objectid

Pokud bych si tedy ve výše uvedeném příkladě svůj home poškodil, mohu na jeho místo připojit onen snapshot.

Snapshoty používám hned pro několik účelů. Jednak pro zálohování, o čemž ještě bude řeč. Dále jako stroj času. Mám snapshoty staré několik měsíců (teď, když jsem konečně vyřešil diskovou otázku, mám v plánu je tam nechat do „nekonečna“). Kdykoliv se tedy můžu podívat na stav včera, minulý týden, před měsícem.

Dále je používám jako pracovní nástroj. Podobně jako se vývojář neobejde bez systému správy verzí, tak já si pořizuji snímek dat kdykoliv s nimi pracuji. Dát do Gitu 250GB dat není zrovna nejrychlejší (a následné odstraňování z nejpohodlnějších). V případě BTRFS si jednoduše pořídím snapshot a vím, že se kdykoliv mohu vrátit. A mohu pracovat v několika větvích. Pokud se libovolný směr ukáže jako slepá ulička, tak to jednoduše smažu. Takto mám v průběhu práce klidně několik desítek snapshotů.

Dynamické přidávání disků

Do systému souborů můžeme kdykoliv přidat, ale také z něj kdykoliv odebrat (s ohledem na velikost volného místa a typu raidu) další disk. Na rozdíl od ostatních systémů souborů, kde lze jen za běhu fs jen místo zvětšovat, u BTRFS lze online i zmenšovat.

Zmenšit velký používaný oddíl například na ext4 znamená několika hodinový výpadek, u některých systémů souborů (například aktuálně prosazované XFS) nelze zmenšit vůbec.

Díky btrfs lze dynamicky přidělovat místo například pro virtuální servery bez výpadků:

btrfs device add /dev/disk /mnt/btrfs_pool
btrfs device delete /dev/disk /mnt/btrfs_pool

A to všechno za běhu serveru. Provozujeme-li například virtuální server, kde je potřeba přidat místo na disku, můžeme jednoduše ve virtualizátoru přidat další disk a ve virtuálce jej přiřadit k existujícímu BTRFS.

Pokud naopak virtuální server místo nepotřebuje, např. se z něj odstranil větší projekt, můžeme opět za běhu disk z btrfs odstranit a ve virtualizátoru jej odebrat. Vyzkoušejte si to třeba v KVM (virsh attach-disk, virsh detach-disk) nebo ve vmware (jistě bude třeba mít v provozu virtio resp. toolsy). Funguje to fantasticky.

RAID 1 nad libovolných počtem různě velkých disků

Kromě výše uvedeného je třeba zdůraznit, že přidat další disk lze bez ohledu na jeho velikost a celkový počet disků i do existujícího BTRFS s módem raid 1. Zatímco pro raid1 běžně platí, že disky musejí být stejné velikosti (v případě různých velikostí se uvažuje velikost nejmenšího z nich a další místo je ztraceno), tak v případě BTRFS můžeme mít klidně lichý počet různě velkých disků. BTRFS bude data ukládat vždy na dva z nich.

Ukázkový výpis btrfs fi show z jednoho z mých serverů ukazuje různou velikost disků v módu raid1:

Label: none uuid: 83f38077-90b4-49cd-9fac-8cc1204098ce
 Total devices 4 FS bytes used 833.19GiB
 devid 3 size 882.58GiB used 246.00GiB path /dev/sda3
 devid 4 size 2.73TiB used 835.03GiB path /dev/sdb
 devid 5 size 931.51GiB used 295.00GiB path /dev/sdh
 devid 6 size 931.51GiB used 294.03GiB path /dev/sdg

Mód je k nalezení v výpisu btrfs fi df:

Data, RAID1: total=830.00GiB, used=829.76GiB
System, RAID1: total=32.00MiB, used=144.00KiB
Metadata, RAID1: total=5.00GiB, used=3.44GiB
GlobalReserve, single: total=512.00MiB, used=0.00B

Vidíme 3 různé velikosti disků (882GiB, 2.73TiB, 931GiB) a také to, že dvě zařízení (devid 1 a 2) byla v minulosti odebrána.

Změna módu raidu

Pokud vytvoříme systém souborů nad jedním diskem, vytvoří se v módu data single, metadata dup. Tedy data budou na disku pouze jednou, metadata budou duplikována. Pokud přidáme do BTRFS další disk, data stále zůstanou uložena pouze jednou (metadata zůstanou duplikována, takže se mohou, ale také nemusí dostat na oba disky).

Toto nám přirozeně nemusí vyhovovat. BTRFS nám dává nástroje jak (opět za běhu) změnit mód raidu:

btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt/btrfs_pool

Můžeme zvolit jiný typ raidu pro metada i data, můžeme také experimentovat s raid5 nebo 6, což bych zatím pro produkční data nedoporučoval.

Změna módu funguje oběma směry. Nejen od méně bezpečných (například výchozí single) k bezpečnějším, ale také naopak. Pokud usoudíme, že pro redundantní data netřeba mirror a vystačíme si například s raid0 (kde získáme i rychlostní výhody), můžeme tuto změnu provést kdykoliv (opět je podmínkou pouze místo na disku a počet zařízení) za plného běhu serveru.

Zálohování

Známý to už před lety pojemnoval „heronův způsob zálohování“. Je primitivní (stejně jako Heron :-D), v podstatě jde o kombinaci snapshotů a rsyncu:

  1. Snapshot zálohovaného oddílu
  2. Rsync na zálohovací systém
  3. Snapshot zálohovacího systému
  4. (Možné odstranění snapshotu zálohovaného systému). Pokud si jej chceme ponechat jako timemachine, tak netřeba mazat.
  5. (Případné odstranění starších snapshotů na zálohovacím systému, dle retence.)

Díky snapshotu je záloha konzistentní, díky rsync se po síti přenáší jen minimum dat. Na zálohovacím stroji se mohou snapshoty záloh ponechávat tak dlouho, jak dlouho je nutné zálohy držet. Navíc díky nezávislosti snapshotů je můžeme libovolně promazávat. Například nové snímky záloh můžeme mít klidně po hodině, potom uchovávat jen denní, potom třeba jen měsíční. Po x měsících či letech není většinou nutné data vytáhnout přesně k dané hodině, stačí libovolná nejbližší.

V průběhu času se do BTRFS dostal také nástroj send a receive. (Trochu jsem se o tomto zmínil i v dalším článku věnovanému zálohování.) Pododdíl kdykoliv můžeme uložit do jednoho souboru a na stejném nebo jiném systému souborů jej zase vytáhnout do podoby subvolume. Toto lze dělat i inkrementálně. Tímto způsobem můžeme libovolně často dělat inkrementální zálohy systému a pokud je obnovujeme na vzdáleném serveru, tak v podstatě ten původní systém skoro v reálném čase replikovat.

Nevím, jak moc se send / receive uchytí, ani pro ZFS (kde je mnohem déle) jsem nezachytil nějaké větší použití. Co se týče replikací, tak existují mnohem vhodnější způsoby. Ale v každém případě je dobré o tom vědět.

systemd-nspawn a jiné kontejnery

Pokud používáte BTRFS na rootovském oddílu a současně systemd, můžete si kdykoliv pořídit snímek svého systému a nabootovat do něj díky nspawn:

btrfs subvolume snapshot / /.tmp
systemd-nspawn --private-network -D /.tmp -b

Během 10s (BTRFS snapshot 1s, boot když hodně tak 9s – mám virtuálku, kde user-space nabíhá 400ms) jste v clonu svého vlastního systému!!! Můžete si tam opět vyzkoušet, tentokráte na celosystémové úrovni) nějakou nebezpečnou činnost. Jakmile nspawn kontejner ukončíte, můžete snapshot .tmp klidně smazat.

Tak jak systemd obecně nemám rád, tak tato vlastnost může být přesně ta, pro kterou jej budu používat. Velmi snadno si totiž můžete do oddělených kontejnerů (nspawn je mnohem lepší chroot) schovat libovolnou aplikaci, kterou nechcete provozovat na „hlavním“ systému. Nebo klidně oddělit všechny. Logy z jednotlivých strojů můžete posílat do hlavního journald a mít tak vše pod jednou střechou.

V manu nspawnu naleznete další šťavnaté příklady.

PostgreSQL

Vlastně analogie výše uvedeného. Pokud provozujete postgresql nad jedním pododdílem (zde je opravdu důležité, aby bylo vše na jednom subvolume, transakční logy i všechny tablespace), kdykoliv si můžete pořídit snímek toho oddílu.

A na tom snímku kdykoliv spustit samostatný server:

pg_ctl start -D /mnt/pg_snap_00258

V tomto případě není vše tak automatické jako v případě nspawnu (ale tam ve složitějším nastavení také ne), zde je nutné změnit číslo TCP portu a cestu k UNIX socketu. Ale pro ukázku co všechno lze dělat je to snad dostatečně efektní.

Jen poznámku: Snímek databáze pochopitelně není ve stavu jako po korektním vypnutí db serveru. To ale ničemu nevadí, je atomický a mezi dvěma fsync. DB server spuštěný nad snímkem udělá standardní recovery z transakčního logu, stejně jako v případě výpadku napájení apod. Toto je zcela korektní postup a v případě slušného databázového systému ta db bude ve stavu poslední potvrzené transakce. V případě neslušného db systému alespoň víte, co nemáte používat ;-).

Chování při výpadku disku

Aby to tady nebylo všechno tak krásné a růžové, je potřeba si přiznat také nevýhody. Zatím nejzásadnější a nejméně pochopitelnou vlastností btrfs, na kterou jsem v praxi narazil, je chování při výpadku disku.

Pokud používáme BTRFS přímo na zařízení a máme v něm přímo disková zařízení (což je přesně to, jak to chceme mít), tak při výpadku disku máme problém. Pokud používáme raid1 o data se nemusíme bát. Od toho tam je.

Ovšem pokud budeme chtít vadný disk odstranit a nahradit novým, musíme btrfs odpojit (umount), následně připojit v degradovaném režimu a až tady odstranit chybějící zařízení. Potom opět odpojit a připojit normálně. A klidně někdy později přidat nový disk.

umount /mnt/btrfs_pool # a vsechny ostatni mountpointy tohoto btrfs
mount /dev/disk /mnt/btrfs_pool -o degraded

btrfs device delete missing /mnt/btrfs_pool

umount /mnt/btrfs_pool
mount /dev/disk /mnt/btrfs_pool # a vsechny dalsi mountpointy

Upřímně, tohle mě fakt zarazilo. BTRFS v případě havárie disku ví, že nějaké device je missing a pracuje normálně dál (data jsou dostupná, nic se neděje). Jen ho prostě nemůže odstranit. To až v degraded. Takže je nutný výpadek služeb. I když jen na pár minut. Proč, nevím. Přitom v normálním stavu si můžeme disky přidávat a odebírat jak je ctěná libost.

Jak toto obejít je asi jasné, můžu mít disky v hw nebo software raidu1 a potom mít v btrfs raid0. Btrfs nikdy výpadek disku neuvidí, o to se postarají nižší vrstvy. Ale tím se poněkud ztrácí hlavní výhoda BTRFS což je implementace raidu a hlavně znalost, kde co a kolik tam toho je.

Rychlost

O BTRFS se říká, že je pomalé. Já jej považuji za nejrychlejší FS současnosti. Ono totiž záleží na úhlu pohledu. Pokud někam nasadíme BTRFS jako normální FS a vůbec nevyužijeme jeho vlastností, ano rychlost není nic moc. Zejména rychlost fsync.

I toto se časem mění. Když jsem dřív, před 3-4 lety zkoušel provoz db nad BTRFS, rychle jsem utekl zpět. Dneska už PostgreSQL provozuju nad BTRFS zcela bez problémů. Rychlost BTRFS se časem znatelně zlepšuje.

Jenže, pokud jej používáme chytře, tak je to jeden z nejrychlejších FS současnosti. Za jak dlouho zkopírujete 2TB soubor? Na BTRFS do 1s. (cp --reflink – nevím, jak to nakonec dopadlo, ale některé distribuce uvažovali, že reflink bude dokonce výchozí mód příkazu cp). Za jak dlouho naklonujete a spustíte systém? Já do 2s. Takto by se dalo pokračovat.

Jak jde čas, tak i notoricky pomalé systémy (například apt-get, který v klasickém případě volá doslova stovky fsynců – protože je dobré, když se během update systému nic nerozbije), tak pokud se před samotnou operací udělá snapshot (návod) lze potom update provést bez pomalých synců. V případě problému s to prostě celé vrátí zpět. Tohle na „normálním“ fs neuděláte. A takových případů je víc, často lze skutečně hromadu synchronizačních volání vhodně nahradit snapshoty.

Takže pokud někdo uvažuje o BTRFS, měl by asi nejprve zauvažovat nad tím, jak využije jeho vlastnosti. Pokud je neplánuje použít vůbec, je lepší zůstat u tradičních FS.

Shrnutí:

BTRFS nám poskytuje výhody v mnoha různých oblastech:

  • Lepší zacházení s volným místech, disky lze libovolně přidávat i odebírat. Což lze s výhodou použit například pro přidělování diskového prostoru virtuálním serverům.
  • Snapshoty kdykoliv a jakéhokoliv pododdílu. Pro atomické zálohování, jednoduchou implementaci timemachine apod.
  • Snímky celého systému můžeme kdykoliv spustit jako kontejner. Aplikační data můžeme kdykoliv spustit jako clon původní aplikace (např. db server).
  • Můžeme libovolně měnit mód raidu podle potřeby ochrany dat, a využití místa na zařízení.
  • Když se věci dělají chytře, mohou být mnohem rychlejší. :-)
Příspěvek byl publikován v rubrice BTRFS, Databáze, GIT, Linux, PostgreSQL, RAID, Systémy souborů. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

4 komentáře: BTRFS v praxi po 5 letech

  1. lzap napsal:

    Sali me zrak? :-)

    • Heron napsal:

      :-D

      Mohl jsem tam dát LXC, ale potom jsem si řekl, že nspawn bude pro hodně lidí okamžitě použitelný, takže je tam ten správný wow efekt. A taky jsem ti chtěl udělat radost :-D

  2. Robo napsal:

    Na niektoré veci používam ZFS ale znovu sa pozriem na BTRFS, dúfam že nesklame…

  3. Pingback: BTRFS – úklidové práce | Heronovo

Komentáře nejsou povoleny.