ZFS SNAPSHOT
ZFS snapshot (snímka) je read-only kópia filesystému v danom čase kedy bol vytvorený. Snapshot môže byť vytvorený takmer okamžite, v počiatku nespotrebováva dodatočný priestor v poole, avšak ak sa dáta v datasete zmenia (niečo sa vymaže, zmení…), prvý snapshot stále odkazuje na dáta prvého a v poradí druhý snapshot obsahuje rozdiel prvého snapshotu. Dá sa povedať, že každý snapshot je rozdiel predchádzajúceho.
Príklad:
Ak pridáme na disk 2GB súbor a spravíme snapshot, tak bude mať skoro nulovú veľkosť. To je spôsobené tým, že snapshot iba odkazuje na dáta vo filesystéme. Pokiaľ však tento súbor vymažeme, pridáme iný napr. 3GB a spravíme opäť snapshot, tak kvôli prvému snapshotu bude dodatočný priestor na disku +2GB (dáta prvého súboru), až pokým samozrejme nevymažeme počiatočný snapshot.
Ako sa dostaneme k snapshotom?
Snapshoty sú dostupné v skrytom priečinku „.zfs“ v každom datasete v tejto forme:
[cesta k namapovanému datasetu]/.zfs/snapshot/[názov_snapshotu]/...
Príklad:
Vytvoríme dataset pool/test/skuska1
, ktorý je namapovaný v /test/skuska1
, pridáme súbory do umiestnenia /test/skuska1
a spravíme snapshot pool/test/skuska1@piatok
, tak k dátam v snapshote sa dostanete v umiestnení /test/skuska1/.zfs/snapshot/piatok
.
# ls -la /test/skuska1/.zfs/snapshot/ pondelok utorok streda stvrtok piatok
ZFS CLONE
ZFS clone je read/write kópia filesystému vytvorená zo snapshotu. Klon sa vždy vytvára zo snapshotu!
Príklad:
Ukážeme si, ako vytvoriť klon zo snapshotu s názvom pool/test@mysql_zaloha
a to tak, že vytvoríme dataset (namapovaný do /test), následne nakopírujeme do neho mysql dump, spravíme snapshot ( pool/test@mysql_zaloha
) a nakoniec spravíme zo snapshotu klon a namapujeme ho do /clone
:
# zfs create -o mountpoint=/test pool/test # cp mysql_dump.sql /test # zfs snapshot pool/test@mysql_zaloha # zfs clone -o mountpoint=/clone pool/test@mysql_zaloha pool/test/clone_mysql
Teraz vieme do klonu aj zapisovať. Klon sa nachádza v /clone
.
ZFS CREATE
Jednoduchým príkazom ZFS create vieme vytvoriť dataset, ktorý môže a nemusí obsahovať ďalšie poddatasety.
# zfs create pool/test # zfs set mountpoint=/test pool/test # zfs set compression=on pool/test # zfs list NAME USED AVAIL REFER MOUNTPOINT pool 21.7G 13.0G 18K none pool/root 6.72G 13.0G 4.99G / pool/test 20K 13.0G 20K /test
Týmto príkazom sme vytvorili nový pool s názvom pool/test, ktorý sme namapovali do /test. Ekvivalent týchto troch príkazov by bol:
# zfs create -o mountpoint=/test -o compression=on pool/test pool/test
Dedenie (Inherit)
Použijem jednoduchú ukážku, ako zdedia poddatasety všetky vlastnosti ich hlavného datasetu. Vytvorím hlavný (parent) dataset pool/share
a jeho poddatasety pool/share/peto
a pool/share/jano
, vytvorím priečinok /share
a namapujem pool dataset pool/share
do /share
:
# zfs create pool/share # zfs create pool/share/peto # zfs create pool/share/jano # mkdir /share # zfs set mountpoint=/share pool/share # zfs list NAME USED AVAIL REFER MOUNTPOINT pool/share 57K 13.0G 19K /share pool/share/jano 19K 13.0G 19K /share/jano pool/share/peto 19K 13.0G 19K /share/peto
Všimnite si, že namapovaním poolu pool/share
si automaticky preberú všetky vlastnosti jeho „deti“ poddatasety pool/share/peto
a pool/share/jano
.
ZFS LIST
Ak sme už vytvorili nejaké pooly, bolo by dobré si ich vypísať. To spravíme príkazom ZFS list:
# zfs list NAME USED AVAIL REFER MOUNTPOINT pool 21.7G 13.0G 18K none pool/root 6.72G 13.0G 4.99G / pool/root/tmp 165M 13.0G 165M /tmp pool/root/var 192M 13.0G 192M /var pool/samba 10.0G 10.0G 21.5K /samba ....
Bez ďalších prepínačov sme dostali kompletný výpis datasetov, ktorý obsahuje náš systém. Môžeme však chcieť vypísať informácie iba o určitom poole:
# zfs list pool/test NAME USED AVAIL REFER MOUNTPOINT pool/test 57K 8.58G 19K /test
Alebo vypísať iba snapshoty v systéme:
# zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT pool/test@zaloha 169M - 2.72G /test pool/test@20101213 140M - 2.79G /test ....
Dá sa vypísať aj všetko, t.j. všetky datasety, snapshoty, clony atď. To docielime, ak zadáme za prepínačom -t parameter all:
# zfs list -t all NAME USED AVAIL REFER pool 26.1G 8.58G 18K none pool/root 6.11G 8.58G 5.08G / pool/test@zaloha 169M - ....
Niekedy je potrebné zistiť, aké snapshoty sa viažu na dataset prepínačom -r [názov datasetu]:
# zfs list -r pool/test NAME USED AVAIL REFER MOUNTPOINT pool/test 277K 16.5G 277K /test pool/test@zaloha 0 - 277K - pool/test@zaloha2 0 - 5GK - ....
Pri skriptoch sa hodí vypísať sformátovaný výstup príkazu zfs list. Na to nám slúži prepínač -o a za ním meno stĺpca oddelený čiarkami:
# zfs list -o name,used,avail,refer NAME USED AVAIL REFER pool 7.81G 3.45M 19K pool/clone 0 3.45M 19K pool/root 7.79G 3.45M 4.37G pool/root/tmp 5.09M 3.45M 5.09M pool/root/var 305M 3.45M 281M pool/skuska 84K 3.45M 3.65G ....
ZFS DESTROY
Príkazom zfs destroy zmažeme daný snapshot alebo dataset.
# zfs destroy pool/test@snapshot1 <-- snapshot # zfs destroy pool/test <-- dataset
Ak by obsahoval dataset pool/test
20 snapshotov, museli by sme ich ručne vymazať, alebo použiť prepínač „-R“, ktorý vymaže všetky poddatasety a jeho snasphoty:
# zfs destroy -R pool/test
ZFS QUOTA
ZFS quota je definícia diskového priestoru pre dataset a jeho poddatasety, t.j. nastavujeme, koľko môže maximálne „spotrebovať“ dát bez ohľadu na celkovú veľkosť priestoru na disku.
V ZFS vieme teda veľmi jednoducho definovať systémové kvóty jediným príkazom, a to zfs set quota=[k,M,G] názov_poolu
.
# zfs set quota=5G pool/test/samba
Môžeme nastaviť kvótu aj pre jednotlivého užívateľa alebo skupinu použitím zfs userquota
a zfs groupquota
:
# zfs create pool/ftpusers # zfs set userquota@uzivatel1=10G pool/ftpusers # zfs create pool/manazment # zfs set groupquota@riaditel=20GB pool/manazment
Zobrazíme si ešte aktuálny stav user
a group
kvót:
# zfs get userquota@student1 pool/ftpusers NAME PROPERTY VALUE SOURCE pool/ftpusers userquota@uzivatel1 10G local # zfs get groupquota@manazment pool/manazment NAME PROPERTY VALUE SOURCE students/labstaff groupquota@riaditel 20G local
ZFS RESERVATION
ZFS reservation je definícia minimálneho garantovaného objemu dát pre dataset a jeho poddatasety. Vieme teda garantovať (narozdiel od zfs quota) určitú veľkosť kvóty pre dataset, ktorá bude dodržaná.
# zfs set reservation=5G pool/test/samba
ZFS RENAME
Niekedy sa môže hodiť premenovať datasety. To sa robí príkazom rename.
# zfs rename pool/test/A pool/test/B
ZFS COMPRESSION
Datasetu vieme prideliť aj kompresiu príkazom zfs compression. Možné kompresie sú on, off, lzjb, gzip, gzip-[1-9]
.
Príklad:
Chceme nastaviť najmenšiu(9) kompresiu gzip pre pool pool/test
a zistiť zmeny príkazom get.
# zfs set compression=gzip-9 pool/test # zfs get -r compression pool/test NAME PROPERTY VALUE SOURCE pool/test compression gzip-9 local
Ak sme vytvorili pool s názvom pool/test
a pridelili mu kompresiu gzip-9, tak ak neskôr vytvoríme pool/test/test1
a pool/test/test2
, všimnite si, že kompresné hodnoty zdedia od svojho „rodiča“ (parentu) pool/test:
# zfs get -r compression pool/test NAME PROPERTY VALUE SOURCE pool/test compression gzip-9 local pool/test/A1 compression gzip-9 inherited from pool/test pool/test/A2 compression gzip-9 inherited from pool/test
ZFS SEND A RECEIVE
Príkaz zfs send vytvorí zo snapshotu dátový tok a zfs receive premení dátový tok opäť na snapshot.
Posielanie snapshotu lokálne
# zfs send pool/samba@20101212 | zfs receive pool/samba_dir
Posielame snapshot pool/samba@20101212
, ktorý následne prijmeme do pool/samba_dir
.
Posielanie snapshotu na vzdialený server
1.
(serverA)# zfs send pool/samba@20110110 | ssh server2 zfs recv pool/samba_dir
V tomto prípade sme poslali snapshot pool/samba@20110110
na server server2
, kde sme ho následne prijali a namapovali do pool/samba_dir
.
2.
(serverB)# ssh server2 zfs send pool/test@test | zfs recv -vF -d pool receiving full stream of pool/test@test into pool/test@test received 249KB stream in 1 seconds (249KB/sec)
Cez ssh sme povedali, aby server server2
poslal snapshot s názvom pool/test@test
, ktorý sme následne prijali na lokálnom serveri serverB
.
Tento príkaz môžeme použiť aj na zálohu napr. celého operačného systému, ktorý je v jaily. Jail mal 850MB a po komprimácii iba 353MB:
# zfs send pool/virtual_server@jail | gzip -9 > jail_virtual.gz
Inkrementálna záloha
Inkrementálna, teda prírastková záloha je zálohovací model, pri ktorom sa zálohujú iba zmenené údaje v dátach, t.j. obsahuje informácie o zmenách voči predchádzajúcej zálohe. Prenášajú sa teda iba zmeny v predchádzajúcom snapshote.
Príklad:
Vytvoríme prvý snapshot pool/test@transfer
, nakopírujeme nejaké dáta a neskôr vytvoríme snapshot pool/test@2
, prenesieme prvý snapshot pool/test@transfer
na iný systém.
# zfs send pool/test@transfer | ssh server2 zfs recv -vF tank/test receiving full stream of pool/test@transfer into tank/test received 327MB stream in 54 seconds (6.06MB/sec)
Keďže po prvom snapshote ( pool/test@transfer
) som nakopíroval do datasetu nejaké dáta (±200kb), druhý snapshot pool/test@2
bude už obsahovať aj tento prírastok. Teraz môžeme vykonať inkrementálnu zálohu na iný systém, kde sa budú prenášať iba rozdiely predchádzajúceho snapshotu.
# zfs send -i pool/test@transfer pool/test@2 | zfs recv -vF tank/test receiving incremental stream of pool/test@transfer into pool/test@2 received 372KB stream in 1 seconds (372KB/sec)
ZFS ROLLBACK
Príkaz zfs rollback slúži na vrátenie predošlého stavu datasetu k danému času kedy bol vytvorený teda obnoví sa dátová štruktúra súborov, do daného okamihu kedy bol vytvorený snapshot. Pozor, staršie zfs snapshoty ako rollback snapshot budú po aplikácii zfs rollback vymazané!
Príklad:Vytvoríme si tri súbory a pri každom spravíme snapshot:
# touch snapshot1 # zfs snapshot pool/test@snapshot1 # touch snapshot2 # zfs snapshot pool/test@snapshot2 # touch zly_snapshot # zfs snapshot pool/test@snapshot3 # zfs list -t all NAME USED AVAIL REFER MOUNTPOINT pool 3.37G 4.44G 19K none pool/root 3.37G 4.44G 3.28G / pool/root/tmp 31K 4.44G 31K /tmp pool/root/var 95.7M 4.44G 95.7M /var pool/test 54K 4.44G 20K /test pool/test@snapshot1 0K - 20K /test pool/test@snapshot2 2M - 20K /test pool/test@snapshot3 0 - 20K /test
Vidíme, že v priečinku test sa vytvorili tri súbory:
# ls -la total 3 -rw-r--r-- 1 root wheel 850B Dec 20 11:45 snapshot1 -rw-r--r-- 1 root wheel 70B Dec 20 11:45 snapshot2 -rw-r--r-- 1 root wheel 3B Nov 25 11:46 zly_subor
Teraz chceme napríklad vrátiť pôvodný stav do doby kedy sa vytvoril snapshot2, pretože sa tam objavil súbor zly_subor, ktorý tam nechceme:
# zfs rollback pool/test@snapshot2 cannot rollback to 'pool/test@snapshot2': more recent snapshots exist use '-r' to force deletion of the following snapshots: pool/test@snapshot3
Budeme musieť pridať prepínač -r, pretože existuje novší snapshot (snapshot3):
# zfs rollback -r pool/test@snapshot2 # ls -la total 1 -rw-r--r-- 1 root wheel 850B Dec 20 11:45 snapshot1 -rw-r--r-- 1 root wheel 70B Dec 20 11:45 snapshot2
Ako vidíme, dostal som priečinok test do pôvodného stavu, kedy bol vytvorený snapshot2 a odstránil nežiadaný stav (zly_subor) s tým, že všetky snapshoty po snapshote2 sa automaticky odstránili.
ZFS HOLD
Niekedy sa nám môže stať, že stratíme prehľad pri veľkom počte snapshotov a nejaký si omylom vymažeme. V ZFS si vieme povedať, ktorý snapshot si chceme ponechať teda označiť ho ako nevyzmazateľný. Docielime to príkazom zfs hold keep snapshot, ktorý nám ho zabráni odstrániť:
# zfs hold keep pool/root@prva_instalacia # zfs destroy pool/root@prva_instalacia cannot destroy ’pool/root@prva_instalacia’: dataset is busy
Môžeme sa však neskôr rozhodnúť takýto „nevymazateľný“ snapshot aj tak vymazať. Musíme použiť prepínač -d:
# zfs destroy -d pool/root@prva_instalacia
Alebo zbaviť snapshot tagu „hold“:
# zfs release pool/root@prva_instalacia
Ďalej môžeme potrebovať zistiť informáciu, kedy sme označili snapshot ako neodstrániteľný:
# zfs holds pool/root@OK NAME TAG TIMESTAMP pool/root@OK keep Thu Jan 15 11:25:39 2010
ZFS ALLOW A UNALLOW
V ZFS vieme nastavovať práva pre pooly príkazom zfs allow. Opačným krokom je práva odobrať, a to príkazom zfs unallow.
Príklad:Chceme, aby užívateľ testuser mohol robiť s poolom pool/testuser
úkony: create
, destroy
, mount
a snapshot
. Následne pridelíme vytvorené práva pre daný pool príkazom allow
.
# zfs allow testuser create,destroy,mount,snapshot pool/testuser # zfs allow pool/testuser ------------------------------------------------------------- Local+Descendent permissions on (pool/testuser) user testuser create,destroy,mount,snapshot -------------------------------------------------------------
Pre odstránenie týchto práv použijeme príkaz unallow, odoberieme už vytvorené práva pre užívateľa testuser a následne aplikujeme vykonané zmeny pre pool príkazom allow.
# zfs unallow testuser pool/testuser # zfs allow pool/testuser
ZFS SET
Príkazom zfs set nastavujeme vlastnosti pre snapshoty (quota, reservation atď…).
ZFS GET
Príkaz zfs get nám slúži na zobrazenie informácií napr. o compress ratiu pre dataset:
# zfs get compressratio pool/root NAME PROPERTY VALUE SOURCE pool/root compressratio 1.00x -
Záver
Dostali sme sa až na záver seriálu. Je toho veľmi veľa čo ZFS dokáže a určite som nespomenul veľa vecí, pretože som sa zameral iba na základy. Verím, že moja séria článkov niekomu pomohla a zorientoval sa v tomto veľmi užitočnom súborovom systéme.
Zdroje:
MAN ZFS
MAN ZPOOL
FreeBSD ZFS wiki
ZFS tunning 32bit system
Oracle Solaris ZFS Administration Guide