Historický exkurs
Protokol NFS je léta starý, jeho počáteční verze byly vyvíjené společností Sun Microsystems. První verze uzřela světlo unixového světa roku 1984, ovšem k plně použitelnému systému měla ještě daleko a několik let sloužila pouze k testování a vývoji v Sun Microsystems. Verze z roku 1989 nesoucí číslo 2 již byla plně použitelná a sám jsem ji ještě před několika lety používal ve své domácí síti. Tato starší verze je stále při kompilaci jádra k dispozici. Má ovšem několik omezení, která ji v současné době výrazně omezují a znevýhodňují její použití.
Jestli vám uvedená omezení nevadí, pak můžete s klidem používat NFS verzi 2 - v pomalejší síti a celkově v méně zatíženém prostředí se používat bez problémů dá. Nicméně volbu NFS verze 2 bych doporučil pouze starším verzím Linuxu, kde byla v jádru možnost NFS verze 3 buď experimentální, nebo nebyla vůbec. Klient pro NFS verzi 3 je k dispozici od nejstarších jader řady 2.4 a server od verze 2.4.19 výše.
Verze 3 je k dispozici od roku 1995 a přináší mnoho vylepšení týkajících se zejména zlepšení výkonu. Také oficiálně přinesla podporu pro přenosy přes TCP. Tato novější verze je v dnešní době perfektně stabilní a má uspokojivé vlastnosti (co se výkonu týče). Na její přednosti oproti verzi 2 se teď ve zkratce podíváme.
Přístup k velkým souborům - NFS verze 3 používá 64bitovou adresaci souborů, takže zvládne i ty největší soubory, které na disku můžeme mít a posouvá tak maximální velikost použitelných souborů na hranici maximální velikosti souborů pro lokální systém souborů na serveru.
Maximální velikost síťové operace ve verzi 3 je 56 kB. To je samo o sobě mnohem více než ve verzi 2 a přispívá tak k plnému využití datagramů UDP. Pro méně spolehlivé sítě (například NFS přes WAN) nabízí možnost přenosu přes TCP, za cenu mírného snížení výkonu (maximální velikost síťové operace je většinou 32 kB).
Dalšími vylepšeními oproti verzi 2 je lepší a rychlejší detekce změn souborů na serveru ze strany klientů a podpora zjištění přístupových práv k souborům na straně serveru - klient se jej zeptá, zda uživatel právo přístupu má, nebo ne, a server zašle odpověď.
Server verze 3 může podle nastavení klienta použít jak asynchronní, tak synchronní operace. Při použití asynchronních operací stačí, že server data přijme a uloží do cache a může klientovi odeslat potvrzení o ukončení operace. Při nastavení klienta pro synchronní komunikaci musí server před odesláním potvrzení uložit všechna data na disk. Klienti mají také možnost požádat o uložení všech dat na disk například při použití příkazu sync.
V současné době se pracuje na verzi 4, ovšem již ne pod taktovkou Sun Microsystems, ale IETF (Internet Engineering Task Force). Tato verze má přinést mnohá další vylepšení a opět tak přiblížit NFS moderním trendům v oblasti síťových systémů souborů. Například již nebude potřeba používat externí lockd k zamykání souborů, ale vše bude součástí protokolu NFS verze 4.
Dost bylo teorie a historie, podívejme se na možnosti a nasazení NFS verze 3 v praxi. Nakonec se zaměříme na pár běžných problémů, se kterými se můžete setkat a také na několik triků.
Současnost a praxe
Soubor /etc/exports s jednoduchou syntaxí je to jediné, co je potřeba upravit. Každý řádek začíná cestou k přípojnému bodu a následuje mezerami oddělený seznam klientů, kteří k němu mohou přistupovat, spolu s nastavením pro daného klienta (nebo skupinu klientů). Klienti jsou většinou identifikováni podle svého hostname (jak z DNS tak ze souboru /etc/hosts) nebo IP adresy. Podporovány jsou také speciální znaky ? a * nahrazující právě jeden a libovolný počet znaků. Případně lze uvést podsíť IP s maskou. To samo o sobě není příliš bezpečné, proto lze použít i jistá omezení. Pro bezpečnější autentizaci si však budeme muset počkat na verzi 4 (v jádrech řady 2.6 již omezená podpora je, ve stavu "experimentální"). Ihned za skupinou klientů je v závorce čárkami oddělený seznam přepínačů ovlivňujících chování serveru.
Hostname je název počítače, reprezentuje počítač v očích uživatele. Stroje na síti mezi sebou komunikují prostřednictvím IP adres. Příkladem hostname může být např. pocitac, stanice09, nbook2 nebo třeba bpusA3m10-2. Hostname svého počítače zjistíte příkazem hostname nebo také uname -a.
Projděme si tedy nejzajímavější možnosti, které lze v tomto souboru nastavit. Co se týče zabezpečení, přímo na straně serveru můžeme určit několik omezení (některá jsou nastavena automaticky). Přepínač ro zakáže všechny operace měnící obsah souborů a adresářů. Toto je implicitní, dá se změnit volbou rw. Vzhledem k povaze NFS a přístupových práv má uživatel s právy roota, který si jako klient připojí systém souborů přes NFS, práva roota i na vzdáleném počítači (co se přístupu k exportovaným souborovým systémům týče). Někdy je to žádoucí, i když to může být značně nebezpečné. Toto chování se dá jednoznačně nastavit volbami root_squash a no_root_squash - při první zmíněné volbě se všechny požadavky uživatele root mapují na anonymní UID/GID. Volbou all_squash se toto chování dá nastavit pro všechny uživatele. Jinak platí, že UID a GID na serveru a klientu by měly být pro daného uživatele stejné, jinak se dočkáme velkého zmatku, uživatelé mohou, kam by neměli, a například do svého domovského adresáře se nedostanou. Parametry anonuid a anongid se pak dá změnit číslo anonymního uživatele a skupiny, na které budou požadavky přemapovány.
UID a GID jsou termíny z oblasti systémových oprávnění. User Identifier a Group Identifier specifikují číslo uživatele v systému a číslo uživatelské skupiny, kam uživatel patří. Superuživatel root má UID 0. Zájemce o další, méně používané možnosti připojení souborových systémů NFS bych odkázal na manuálovou stránku NFS, příkaz man nfs.
Dále máme k dispozici pár voleb umožňujících upravovat poměr spolehlivost/výkon. Volba async zapíná asynchronní přenos (musí jej zapnout také klient), který značně urychluje přenosy dat. Stačí, aby si data server uložil do cache a operace se považuje za úspěšně dokončenou. Z toho samozřejmě plyne možná ztráta nebo porušení dat při výpadku serveru. Při použití verze 3 navíc volba async nepřináší výrazné zvýšení rychlosti, pouze znemožňuje zjištění neúplného uložení dat. Ve verzi 3 proto tuto volbu zapínat nedoporučuji - ve verzi 2 se pro zvýšení výkonu použít dá, za cenu výše zmíněného rizika. Když chceme být paranoidní a prakticky si vynutit podobné chování jako ve verzi 2, můžeme použít volbu no_wdelay, která způsobí, že jednotlivé síťové operace budou ihned zapsány na disk. Tento parametr však značně snižuje výkon.
Velký pozor při editaci tohoto souboru si musíme dávat na mezery. Soubor /etc/exports je na ně poměrně citlivý. Dobrou zásadou je vkládat pouze jednu mezeru mezi exportovaný adresář a pak jednotlivé klienty/skupiny klientů s nastaveními. Mezi definicí klienta nebo skupiny a závorkou s nastavením mezera být nesmí.
Po přizpůsobení tohoto souboru k obrazu svému můžeme standardním způsobem zapnout NFS server: například /etc/init.d/nfs start. U distribucí bez závislostí mezi službami je dobré nejdříve spustit také portmapper: /etc/init.d/portmap start . Službu portmap je vhodné spouštět i na klientských počítačích. NFS sice funguje i bez ní, některé operace jsou pak ale příliš pomalé.
Nastavení klienta spočívá pouze v upravení souboru /etc/fstab, případně v přímém připojení pomocí příkazu mount a všech potřebných parametrů. Jako zařízení uvedeme název či IP adresu serveru, za ní dvojtečku a absolutní cestu k exportovanému přípojnému bodu na serveru.
Projdeme si postupně ty nejdůležitější. Parametry rsize a wsize určují maximální velikost síťových operací. Při použití verze 3 je vhodné je zvětšit na maximální podporovanou velikost pro daný typ spojení - 32768 (32 kB) pro TCP spojení, případně 57344 (56 kB) pro UDP. Velmi důležitý je také parametr nfsvers, protože implicitně se používá verze 2 NFS, verzi 3 je potřeba uvést explicitně. Dále nás bude zajímat parametr async, který zapíná asynchronní přenosy dat. Parametry soft a hard můžeme ovlivnit chování přípojného bodu při odpojení od serveru. Implicitní je parametr hard, který způsobí, že se aplikace přistupující k odpojenému systému souborů "zasekne" a nedá se ani přerušit příkazem kill, pokud nespecifikujeme také volbu intr. Na druhé straně při použití parametru soft po určité době (specifikovatelné parametrem timeo) operace vyprší (timeout) a aplikaci je vrácena chyba čtení/zápisu. Poslední často používanou volbou je nolock, která způsobí, že se při připojení souborového systému nespustí zamykací démon lockd. To je téměř nevyhnutelné, jestliže z nějakého důvodu neběží portmapper. Jinak by se při každém připojení a pokusech o zamčení souboru snažil klient spustit lockd a použít jej, což je bez portmapperu nemožné a musí se čekat na timeout.
Problémy, tipy a triky
Při práci s NFS na serveru, kde jsou soubory uložené na systému souborů FAT, může docházet k nepříjemným překvapením. Například když máme otevřený soubor a jiná aplikace jej změní a přesune, NFS server může mít problém nalézt tento změněný soubor a vrátí aplikaci chybu.
Používání IP adres a názvů v souboru /etc/exports najednou nás může přivést k "záhadným" problémům, kdy se jednou klientovi připojit podaří a podruhé ne. Ideální je používat v /etc/exports pouze jeden druh označování počítačů a sítí.
Taktéž při exportování podadresářů hierarchicky uspořádaných, které jsou umístěné na stejném systému souborů, může docházet k podobným "záhadným" problémům. Například kdybychom se snažili exportovat /var a /var/log najednou - samozřejmě problém by nenastal, kdyby byl adresář /var/log umístěn na vlastním souborovém systému.
Možná by někoho lákalo řešení s "vysokou propustností" - exportování tmpfs. V tomto směru nás NFS zklame, protože tmpfs a ostatní "pseudo" souborové systémy se exportovat nedají. Zaručeně s NFS fungují ext2, ext3, reiserfs, jfs a xfs. S jistými omezeními lze používat přes NFS i iso9660, udf, reiser4, fat a ntfs.
Zkratka tmpfs označuje souborový systém, který je alokován v operační paměti (tedy ne na disku). Na rozdíl od ramdisku (odkládací prostor v paměti) odkládá nepotřebné části paměti na odkládací oddíl (obvykle disk). Volně podle http://en.wikipedia.org/wiki/Tmpfs
Další zvláštní situací, které se lze naštěstí vyhnout rekonfigurací /etc/exports, může být případ otevřeného souboru, který se přičiněním jiné aplikace na serveru přesune mimo exportovaný adresář, i když se jeho inode nezmění. Aplikaci přistupující k souboru přes NFS je vrácena chyba. Když s tímto počítáme a potřebujeme zachovat přístup k jednou otevřeným souborům, i když byly přesunuty, pomůže volba no_subtree_check. Toto má velmi mírný dopad na bezpečnost, ale za normálních okolností je spíše lepší tuto volbu zapnout.
Pojem inode, česky uzel, označuje základní informační jednotku, která na disku uchovává informace o souborech a adresářích. Je součástí struktury souborového systému.
I při použití volby intr při připojování NFS se nám později při výpadku na straně serveru (nebo na síti) může stát, že určitou aplikaci nemůžeme ukončit ani signálem KILL. Jedná se o problém s čekáním na semafor jiného procesu, čekání na semafor se (v současné implementaci semaforů) přerušit nedá. Jestli opravdu potřebujeme souborový systém NFS odpojit i za cenu ztráty dat v aplikacích, můžeme si nechat vypsat všechny procesy přistupující k souborům na odpojeném souborovém systému (například pomocí programu lsof) a všem poslat signál KILL. Nakonec pošleme signál KILL i procesu rpciod. Až se všech těchto procesů zbavíme, můžeme souborový systém odpojit.
Některé špatně napsané aplikace, které se spoléhají na implicitní chování lokálních souborových systémů, mohou mít značné problémy s uchováním konzistence dat při jejich použití přes NFS. Proto než se začneme spoléhat na bezchybnou funkčnost ukládání souborů přes NFS, je dobré si vyzkoušet, zda s NFS pracuje naše aplikace korektně.
Když exportujeme knihovny a spustitelné binární soubory, nastane při jejich přepsání na serveru problém pro všechny klienty, kteří mají právě tyto soubory spuštěné. Téměř jistým výsledkem takovéto operace je velmi "oblíbený" segmentation fault na všech takových klientech. Jedinou možností, jak toto obejít při instalaci nových verzí knihoven a spustitelných binárních souborů, je přejmenování staré verze a následné nainstalování verze nové. Při manuálních instalacích toho lze docílit pomocí přepínače -b programu install.
Chyba segmentation fault je opravdu "velmi oblíbená". Jedná se o lapidární popis stavu, kdy program přistupuje do paměti, kam přistupovat nesmí, protože ta například patří do správy jiného programu. Obvykle tak špatně napsané programy reagují při pokusu o zápis na médium, na které zapisovat nelze. Následek je jasný - pád programu. Podobné situace vyvolávají v systému MS Windows známou "Modrou obrazovku smrti" - BSOD (Blue screen of death) a ani v Linuxu nejsou ničím zvláštním. Volně podle http://en.wikipedia.org/wiki/Segmentation_fault
"Remountování" souborového systému NFS sice dokáže změnit standardní možnosti pro připojování souborových systémů (například sync/async), ale specifické nastavení pro NFS za běhu změnit nedokáže, je potřeba celý systém souborů odpojit a znovu připojit. Nesmíme se také nechat zmást obsahem souboru /etc/mtab (případně výpisem příkazu mount), kde se i při "remountování" nové volby objeví. Pro kontrolu efektivních voleb připojení je mnohem lepší zkontrolovat soubor /proc/mounts přímo.
Když nám "vytuhnou" procesy při výpadku NFS serveru, potřebujeme systém souborů odpojit, a nepoužili jsme volbu intr, není ještě vše ztracené! Můžeme všem procesům poslat signál KILL a pak se pokusit odpojit souborový systém pomocí umount -f. Možná to všechny procesy neukončí a systém souborů se nepodaří odpojit, ale po několika pokusech by se to mělo povést. V krajní nouzi lze použít umount -l, ovšem všechny "vytuhlé" procesy zůstanou v nepřerušitelném stavu, pravděpodobně až do restartu počítače.
Nakonec si ukážeme ještě jeden trik. Jestli jste si kompilovali vlastní jádro, tak jste si možná při nastavení NFS všimli, že vyšší verze jsou jakousi "nadstavbou" nižších. Proto se k našemu serveru verze 3 mohou připojovat i klienti verze 2. Potřebujeme přidat parametry -N 1 -N 2 při spouštění programu rpc.mountd. Záleží na distribuci, jak lze toto provést. Například v Gentoo stačí v /etc/conf.d/nfs tyto parametry přidat do proměnné RPCMOUNTDOPTS. V případě distribucí, které nemají konfigurovatelné spouštěcí skripty, se dá upravit přímo skript /etc/init.d/nfs. Při pokusu o připojení klientem verze 2 k serveru verze 3 bude spojení odmítnuto (connection refused).
Ukázka souboru /etc/exports na serveru: /home/uzivatel ubuntu(no_all_squash,sync,secure,rw) /mnt/hda9 ubuntu(no_all_squash,sync,secure,rw) /mnt/hda8 ubuntu(no_all_squash,sync,secure,rw) /mnt/hda6/hudba ubuntu(no_all_squash,sync,secure,rw) / ubuntu(no_all_squash,sync,insecure,rw) Parametr ubuntu odpovídá záznamu v /etc/hosts: 192.168.1.33 ubuntu ubuntu Ukázka souboru /etc/fstab na klientu: 192.168.1.100:/mnt/hda6/hudba /mnt/hudba nfs defaults 0 0 192.168.1.100:/mnt/hda8 /mnt/hudba2 nfs defaults 0 0 192.168.1.100:/mnt/hda9 /mnt/hudba3 nfs defaults 0 0 192.168.1.100:/home/uzivatel /mnt/server nfs defaults 0 0 192.168.1.100:/ /mnt/server-root nfs defaults 0 0
Verze 2 ve zkratce
Tato verze používá 32bitovou adresaci souborů, proto nedokáže přečíst více než 2 GB z velkého souboru - čím efektivně znemožňuje jejich používání. Obraz plného jednovrstvého DVD má 4,4 GB, a to je v dnešní době standard. Dále omezuje maximální velikost síťové operace čtení nebo zápisu na 8 kB. Při práci s většími soubory to omezuje přenosovou rychlost.
Klienti verze 2 sami ověřují, zda má uživatel právo přístupu k souboru, či nikoliv - kontrola oprávnění je na straně klienta. S tím může být problém například v případě, že server používá pro nastavení práv k souborům ACL a klient nikoliv.
NFS verze 2 vyžaduje, aby server uložil všechna data před tím, než pošle klientovi oznámení o ukončení síťové operace. Toto může být velmi nevýhodné z několika důvodů - od nízkého výkonu a "zablokování" klientské stanice pro operace s připojeným NFS až po fragmentaci souborů na serveru při současném ukládání několika souborů na disk (server musí uložit každých 8 kB ihned na disk).