Překrytí systémového disku - overlay filesystem

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání
Koncept transparentního překrytí systémového disku virtuálním diskem vytvořeným v lokální paměti, využíváme u bezdiskového linuxu od roku 2006. S tímto nápadem tenkrát přišel Pavel Píša[1], a při realizaci použil unionfs, jehož vývoj započal r. 2004. Byla to vůbec první linuxová implementace této technologie, která se dala reálně používat.
unionfs
S přechodem na linuxové jádro řady 2.6 začal vývoj unionfs zaostávat, proto ho nahradil aufs, který podporoval i novější jádra řady 3.x Jeho kód sice nebyl součástí kódu jádra, ale byl také udržován v gitu a verzován vůči aktuálním verzím jádra.[2]
aufs
Modul aufs sice nebyl součástí hlavní vývojové větve jádra, ale až k jádru verze 3.16 byl standardní součástí distribučního jádra Debianu[3] Jeho kód nebyl do linuxového jádra integrován, přestože o to jeho vývojář Junjiro R. Okajima řadu let usiloval, protože nedělal sjednocení adresářů v rámci VFS (virtuálního souborového systému), ale mimo něj – stejně jako původní unionfs. A to byl i důvod, proč byl nakonec upřednostněn modul overlay, který provádí sjednocení adresářů na úrovni VFS, s jehož vývojem začal Miklos Szeredi v roce 2010.
overlay
Pozorně jsme sledovali Szerediho práci na modulu s názvem overlayfs od samého počátku, protože jsme doufali, že se po začlenění jeho modulu do jádra situace změní k lepšímu a nebude nutné pro každou novou verzí jádra znovu patchovat kód a kompilovat vlastní jádro. Jenže se to neustále odsouvalo. Původně bylo ohlášeno, že k tomu dojde již u jádra řady 3.10, ale nakonec byl zařazen do hlavní vývojové větve jádra až od verze 3.18-rc2 a přejmenován na overlay.
Smutné ovšem bylo to, že zařazený kód obsahoval změny, které znemožnily použít jako podkladový souborový systém adresář sdílený přes NFS – tento nedostatek byl odstraněn až od jádra verze 4.8. Nicméně ho bylo možné obejít aplikací unionfs-fuse
unionfs-fuse
Přes union-fuse lze také „vyrobit” overlay, ale výkonově slabší, protože soubory nehoní na úrovni jádra, ale v uživatelského prostoru a to obnáší zhruba 20% ztrátu výpočetního výkonu procesoru. Ovšem pro účely disklessu to bylo stále ještě přijatelné.
mcachefs
Jsme použili z jiného důvodu, i když se v podstatě chová podobně jak overlay. Liší se od něj tím, že vytahuje soubory z podkladové vrstvy nahoru již při pouhém čtení, což overlay nedělá. A pokud je v horní vrstvě lokální souborový systém a pod ním adresář připojený přes NFS, může fungovat jako keš. Bohužel, v reálném nasazení této utility se projevilo několik zásadních nedostatků v jejím návrhu:
  1. Neměla podporu pro atomické změny, což bylo řešitelné jen opakovanými restarty, dokud se do keše nenatáhly všechny potřebné systémové soubory …
  2. … a co bylo horší, neuměla aktualizovat symlinky. Pokud se na straně NFS změnil cíl symlinku, zůstal v keši viset neplatný symlink, což přinášelo komplikace při použití systemd. Proto bylo nutné do ramdisku implementovat funkci, která z lokální keše, před nasazením overlaye, všechny symlinky zrušila.


Linuxový systém nad NFS

Poznámka Linuxový systém nad NFS lze provozovat pouze za předpokladu, že jeho jádro obsahuje modul aufs. U Debianu byl tento modul donedávna součástí distribučního jádra, ale od jádra verze 3.19 se patchování jádra nevyhnete. Jak vytvořit vlastní jádro s podporou aufs viz výše.

Princip je následující:

  1. Nejprve se spustí linuxové jádro, které si do paměti rozbalí ramdisk
  2. V ramdisku musí být k dispozici modul aufs a utility pro připojení adresáře sdíleného přes NFS
  3. V paměti se vytvoří další tmpfs prostor, připojený na přípojný bod, kterým se pak překryje namountovaný adresář se systémem, sdíleným přes NFS
  4. Další zavádění již probíhá jako obvykle. S tím, že veškeré změny se zapisují do onoho vyhrazeného prostoru v paměti

Součástí ramdisku tak musí být skripty, které tyto operace zrealizují ještě před spuštěním init procesu.

Dynamický ramdisk

S rozšířením disklessu na TurtleBoty jsem od září 2019 implementoval novinku – dynamický ramdisk[4]. Ten umožňuje modifikovat zavádění disklessového systému bez toho, že by bylo nutné v PXE menu psát na příkazové řádce jádra další potřebné parametry.

Dynamický ramdisk je založen na myšlence, že ramdisk obsahuje pouze výchozí skripty, nezbytné pro nahození sítě a stažení konfiguračního souboru podle identifikačních údajů (jména skupiny, IP adresy, hostname či výchozí brány) z DHCP. Ten obsahuje další potřebné informace k sestavení sendviče a spuštění disklessového systému.


Dynamický ramdisk vyžaduje upravený skript nfs a dva klíčové skripty: enable_wireless a nfsroot

nfs
Originální verze tohoto skriptu je součástí instalačního balíku initramfs-tools-core. Instaluje se do adresáře /usr/share/initramfs-tools/scripts/ – odkud se bere, když update-initramfs sestavuje ramdisk. Při zavádění se použije, pokud je jádru předán parametr boot=nfs. Tahle verze skriptu není pro dynamický ramdisk použitelná, protože očekává parametr nfsroot ve kterém je IP adresa NFS serveru a cesta ke sdílenému adresáři, kde je uložen kořenový adresář zaváděného systému + další parametry připojení.
Ten, pokud se nepředá jádru rovnou při zavádění, lze dodat z DHCP. Ovšem pokud ho DHCP nedodá, zůstane zavádění viset v nekonečné smyčce. Jenže u dynamického ramdisku se pracuje s konfigurací, která se stahuje až poté, co se přes DHCP nastaví síť. Proto je nutné kus kódu vykuchat a vykuchanou verzi skriptu nfs umístit do adresáře /etc/initramfs-tools/scripts/, aby měla při sestavení jádra vyšší prioritu.
enable_wireless
Klíčový skript, v adresáři /etc/initramfs-tools/scripts/nfs-top, který se stará o nahození sítě. Logika věci je taková, že…
  1. Pokud systém najel drátem přes PXE, tak není co řešit, protože v adresáři /run již existuje soubor s konfigurací sítě
  2. Pokud systém doposud nemá funkční síťové připojení, postupně nahodí všechna síťová rozhraní co má k dispozici do stavu UP a pokud mezi nimi bude síťová karta do níž bude zapíchnutý "živý" drát, bude použita pro nahození sítě.
  3. Pokud nikam "živý" drát zapíchnutý nebude, ale bude k dispozici zařízení typu WLAN, tak se pokusí připojit na Wi-Fi.
nfsroot
Je druhý klíčový skript v adresáři /etc/initramfs-tools/scripts/nfs-top, závislý na skriptu enable_wireless. Tento skript se stará o stažení konfigurace a případně i dalších skriptů, co se postarají o sestavení cílového sendviče.
Poznámka Ostatní skripty nejsou v ramdisku nezbytně nutné, protože je nfsroot může na základě konfiguračního souboru stáhnout a umístit do adresářů nfs-premount, nfs-bottom, aj. dodatečně. S tím, že pokud tam již jsou, tak jejich stávající verze stejně převalí.

Skripty

Nejjednodušším způsobem jak dostat tento skript do ramdisku je:

  1. Nainstalovat balíček initramfs-tools,
  2. Nakopírovat tento skript do adresáře /etc/initramfs-tools/scripts/nfs-bottom
  3. A následně aktualizovat ramdisk - viz odstavec Práce v prostředí ramdisku#Korektní sestavení ramdisku u Debianu v předchozí kapitole
Upozornění V případě že je systém zaváděný z ramdisku který je mimo virtuální stroj, je třeba nově sestaveným ramdiskem nahradit ten ramdisk který se při zavádění skutečně používá.
Upozornění Aby se skripty skutečně spustily, musí být v ramdisku nastaveny jako spustitelné! Pokud tomu tak není, tak se disk nepřekryje a systém najede jako zapisovatelný!

Připojení lokálního swapovacího oddílu – findswap

Původně šlo o skript, který vyhledával swapovací oddíl, aby ho připojil, až během zavádění hlavního disklessového systému. Do ramdisku jsem ho přesunul až v září 2016, poté co mne napadlo využít swapu pro navýšení RAM.


Skript pro překrytí systémového disku – overlay

Skutečný Full-Diskless, který se obejde bez jakékoliv lokální instalace umožnila technologie překrytí systémového adresáře připojeného z NFS serveru adresářem vytvořeným přes TMPFS z části RAM[5] v kombinaci se zaváděním přes PXE.[6]

Každý operační systém potřebuje datový prostor, kam může za běhu zapisovat změny – logy, databáze, konfigurační změny, atp. Rozdíl je pouze v tom, že se diskless nezdržuje čekáním na to, až se data zapíšou na lokální blokové zařízení – spoléhá že to za něj udělá NFS server kterému je posílá ať si je někam uloží přes ethernet.<ref> Je to velice výhodný přístup! Až do nástupu SSD a NVME disků, byly IO operace úzkým hrdlem každého počítačového systému. Aby mohl zapsat datový blok z rychlé RAM na pomalý rotační disk, musel vyčkat se zápisem až se roztočí, teprve poté co mu driver oznámil, že jsou data zapsaná mohl čekající proces pokračovat dál. Diskless nic takového nezdržuje, protože NFS server, který obdržel data po síti, ihned odpoví, že jsou data přijata a diskless už se nestará o to, kdy, kam a jak si ty data uloží. <ref> NFS server, který obsluhuje více takových strojů, má vždy lepší ekonomiku provozu než pracovní stanice.

  • Je vybaven větším množstním RAM než pracovní stanice, takže se nezdržuje se neustálým roztáčením disků. Drží data v RAM, dokud ji nepotřebuje uvolnit. Nemá důvod se opakovaně zdržovat roztáčením pomalých rotačních disků aby mohl uložit.
  • Má také obvykle i větší počet disků, což umožňuje paralelní zápis i čtení, což ve výsledku zkracuje dobu čekání na dokončení I/O operace, protože nemusí čekat na potvrzení o zápisu jako Non-Diskless stroje, které obvykle na to mají pouze jeden systémový disk. Server si rozdělí data na víc částí a každou z nich zapíše ve stejnou chvíli na jiný disk. A totéž platí i pro čtení.
  • Server má navíc sdílenou RAM, takže se nezdržuje pokud chce více strojů najednou jeden a ten samý blok dat, který už jednou načetl do RAM, a rovnou jim ho odešle.
  • Datový prostor na serveru je drahý. Hodně disků, hodně RAM, hodně počítání a také má poměrně velkou spotřebu elektrické energie. Ale čím víc obsluhuje klientů, tím se to víc vyplatí.

Diskless, který nemá overlay, neukládá změny do RAM. Musí tedy mít na NFS serveru vyhrazen svůj datový prostor, přístupný v režimu read-write, kam si může svoje změny zapsat. Nemůže zapisovat do stejného adresáře jako jiný stroj, poněvadž by to mohlo vést ke kolizím. Takže čím víc takových strojů NFS server obsluhuje, tím víc datového prostoru mu to zabere.

U strojů co mají overlay to není nutné, protože si změny zapisují do RAM a vůbec nevadí, že se při restartu zahodí. Naopak. Je výhodné, když se po restartu ocitne vše ve výchozím stavu, protože nezůstanou žádné soubory, ve kterých by číhal na svou oběť vir, či nějaký ransomware. A na NFS serveru tím pádem stačí pro všechny stroje jeden adresář, který může být klidně exportován read-only, takže nehrozí, že by jeho obsah v nestřeženou chvíli nějaký škodič zakryptoval. A protože je systém všude stejný, jsou i data, která si uživatel zapisuje přes NFSv4 do svého adresáře připojeného v režimu read-write, použitelná i jinde.

ramdisk tmpfs.svg


Spouštěcí skripty a operace v systému bezdiskového stroje

Init skript pro spouštění dalších operací

Protože v našem prostředí bezdiskového linuxu využíváme i software, který není součástí distribuce a vyžaduje určitá specifická nastavení, je v adresáři /etc/init.d umístěn skript,k335linux, který v okamžiku kdy je namountováno NFS spustí obsah skriptu v /etc/default/k335linux.

Upozornění Obsah následujícího skriptu je specifický pro naši konfiguraci. Pokud jej hodláte využít, musíte jeho obsah upravit.
k335linux
Poznámka
#! /bin/sh
### BEGIN INIT INFO
# Provides:          k335linux
# Required-Start:    $remote_fs
# Required-Stop: 
# Should-Start:
# Should-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Creates symlink in /opt
# Description:
### END INIT INFO

#
# k335linux	K335 diskless linux setup helpers.
#
#		Base on skeleton by Miquel van Smoorenburg <miquels@cistron.nl>.
#		Modified for Debian 
#		by Ian Murdock <imurdock@gnu.ai.mit.edu>.
#
# Version:	@(#)k335linux 1.0  12-Jan-2011  pisa@cmp.felk.cvut.cz
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=k335linux
DESC="station configuration"

# Include k335linux defaults if available
if [ -f /etc/default/k335linux ] ; then
	. /etc/default/k335linux
fi

set -e

case "$1" in
  start)
	echo -n "Starting $DESC: "
        #echo -n "xconf"
        #/usr/local/bin/xconf > /dev/null
	echo "."
	;;
  stop)
# 	echo -n "Stopping $DESC: "
# 	echo "."
	;;
  force-reload)
	$0 restart \
	|| exit 0
	;;
  restart)
    echo -n "Restarting $DESC: "
	start-stop-daemon --stop --quiet --pidfile \
		/var/run/$NAME.pid --exec $DAEMON
	sleep 1
	start-stop-daemon --start --quiet --pidfile \
		/var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
	;;
  *)
	N=/etc/init.d/$NAME
	echo "Usage: $N {start|stop|restart|force-reload}" >&2
	exit 1
	;;
esac

exit 0

Připojení uživatelských adresářů

Záznam v souboru /etc/fstab, který využívá pro připojení vzdálených adresářů souboru /etc/hosts, vygenerovaného skriptem v ramdisku

ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no nfshomecreator@nfsserver testuser 1234 100 /nfs/diskless-home

Autorizace uživatelů

Toto téma řeší samostatný manuál - Autorizace uživatelů v linuxu

Použití

V rámci linuxového bezdiskového stroje nad NFS lze provádět veškeré operace jako kdyby šlo o stroj s normálním blokový, zařízení. Překrytí systémového disku však má z hlediska použití v laboratořích a učebnách jednu obrovskou výhodu - veškeré změny jsou uloženy pouze v rámci virtuálního disku, kterým je překrytý výchozí systém a po restartu se zahodí - s výjimkou souborů uložených v uživatelských adresářích.

Pokud je při zavádění přemountován přípojný bod /overlay/unirw z prostředí ramdisku do systému, je jeho obsah dostupný v rámci sjednoceného souborového systému. Z něj pak lze vytáhnout změny a soubory vytvořené v rámci disklessového systému.

Využití překrytí systémového disku při přípravě binárních distribučních balíků

Chceme-li využívat překrytí při testovacích instalacích a tvorbě binárních balíčků, nemusíme patchovat a kompilovat vlastní linuxový kernel, ale můžeme použít rovnou modul overlay který je dnes již standardní součástí distribučního jádra.

mount -t overlay overlay -o lowerdir=/nejnizsi_vrstva,upperdir=/vrstva_kam_se_zapisuje,workdir=/work /sloucene_vrstvy
lowerdir
Adresář, který se má překrýt transparentní vrstvou.
upperdir
Adresář, do kterého se zapisuje obsah transparentní vrstvy která je zcela nahoře. Proto musí být do něj možné zapisovat.
workdir
Prázdný adresář, který se však musí vyskytovat v rámci stejného souborového systému, jako upperdir

Posledním parametrem příkazu je přípojný bod do kterého se sloučené vrstvy připojí.

  • Součástí podkladové vrstvy lowerdir může být i několik transparentních vrstev nad sebou. Adresáře jsou od sebe odděleny dvojtečkou a postupně se na sebe vrství zleva doprava. Tj. adresář první v pořadí je nejníž položený.
  • Adresáře upperdir a workdir lze vynechat, ovšem v takovém případě se sloučené vrstvy připojí na přípojný bod pouze v režimu pro čtení

Praktický příklad použití

Dejme tomu, že chcete vyzkoušet jaké změny v systému nastanou, pokud budete chtít nainstalovat aplikaci kompilovanou ze zdrojových kódů.

Příprava a kompilace

Kompilace si může vynutit instalaci nových balíčků, které ovšem jinak vůbec nepotřebujete. Proto si nejprve připravíte adresář /root/pivot pro chroot, ve kterém budete moci provést konfiguraci a instalaci dalších potřebných balíčků, aniž by tím došlo k nabourání stávajícího systému.

Poznámka
root@stroj:~# mount -t overlay overlay -o lowerdir=/,upperdir=/root/prepare,workdir=/root/work /root/pivot
root@stroj:~# mount /dev /root/pivot/dev -o bind
root@stroj:~# mount /proc /root/pivot/proc -o bind
root@stroj:~# mount /sys /root/pivot/sys -o bind
root@stroj:~# chroot /root/pivot

Posledním příkazem chroot jste se přepnuli do systému, kde lze provádět konfiguraci zdrojového kódu a instalaci potřebných balíčků. Ve stejném prostředí můžete (ale nemusíte) zdrojové kódy také zkompilovat.

Jelikož nevíte co se kam bude instalovat, je lepší před vlastní instalaci vyskočit ven z chrootu (příkazem exit) a sestavit overlay znovu. Ovšem tentokrát již s využitím obsahu adresáře /root/prepare, ve kterém se nalézá vše co bylo nainstalováno v předchozím kroku.

Poznámka
root@stroj:~# exit
root@stroj:~# umount /root/pivot/sys
root@stroj:~# umount /root/pivot/dev
root@stroj:~# umount /root/pivot/proc
root@stroj:~# umount /root/pivot

Instalace

Do parametru lowerdir přidáme nad systémový adresář (/) jako transparentní vrstvu adresář /root/prepare do kterého se ukládaly změny v průběhu přechozího kroku. A pro uložení změn při instalaci vyžijeme nový prázdný adresář /root/binary:

Poznámka
root@stroj:~# mount -t overlay overlay -o lowerdir=/:/root/prepare,upperdir=/root/binary,workdir=/root/work /root/pivot
root@stroj:~# mount /dev /root/pivot/dev -o bind
root@stroj:~# mount /proc /root/pivot/proc -o bind
root@stroj:~# mount /sys /root/pivot/sys -o bind
root@stroj:~# chroot /root/pivot

A můžeme bez obav spustit instalaci. Z obsahu adresáře /root/binary můžeme sestavit binární .deb balíček, a obsah adresáře /root/prepare nám zase pro změnu pomůže při detekci závislostí.

Poznámka Jak sestavit binární .deb balíček je popsáno v manuálu k Pacemakeru
  1. Viz Přehled vývoje infrastruktury pro diskless Debian na katedře DCE
  2. Podrobnější informace o problematice sjednocujících souborových systémů nabízí minisérie přeložených článků na http://www.abclinuxu.cz
  3. Od chvíle, kdy se stal overlayfs součástí hlavní vývojové větve jádra, přestali správci distribučního jádra Debianu aufs integrovat. U bezdiskového linuxu postaveného nad aufs, který běží nad NFS tak nezbývá než patchovat a kompilovat vlastní jádro, aby mělo k dispozici modul aufs.
  4. K vytvoření dynamického ramdisku vedl fakt, že mne nebavilo při ladění skriptů pro overlay opakovaně sestavovat ramdisk.
  5. Překrytí NFS adresáře pomocí unionfs použil Pavel Píša již roku 2005.
  6. V době mého nástupu na DCE (2008) fungovaly laboratorní stroje pouze jako Half-Diskless a já nevěděl o Disklessu nic. Byl jsem přijat coby expert na virtualizaci linuxových strojů, abych zajišťoval za katederního IT nezbytnou spolupráci při realizaci projektu Eusophos, v jehož rámci byl Ondrou Fialou vyvíjen LabLink – virtuální laboratorní systém, který využíval vrstvení virtualizovaných MS Windows pro zajištění software nezbytného k práci s laboratorními modely – ta koncepce se mi líbila a možná, že právě to mne přivedlo později na myšlenku využít sendviče i pro linuxový laboratorní diskless. První rok zabrala většinu mé pracovní doby dokumentace toho, co kde bylo v provozu. IT oddělení DCE tehdy ještě neexistovalo. Pracovní stanice řešil Petr Haba. MS Windows server s katederním webem Michal Komrska a František Vaněk měl pod palcem síť a Novell. Vše ostatní jsem měl řešit já, ale co, to nikdo nevěděl. Lukáš Moc, můj předchůdce mi předal štůsek papírů a zmizel, aniž by mi sdělil alespoň přístupové heslo. Bylo to jak v pohádce o kohoutkovi a slepičce. Abych měl kam sbírat informace, rozjel jsem tuhle wiki, ale nejdřív jsem si do ní musel udělat vlastní rozšíření, abych mohl na jednom místě soustředit veřejné i neveřejné infromace. A tak až po roce jsem se dostal k tomu, abych začal intenzivně spolupracovat s Pavlem Píšou(*1970) na vývoji laboratorního Full-Disklessu na bázi linuxové distribuce. Bohužel moduly linuxového jádra, které jsme potřebovali použít, tehdy ještě nebyly součástí hlavní vývojové větve. Také zavaděč Grub který jsme využívali byl problematický. Původní verze se již nevyvíjela a vývoj nové probíhal pomaleji než bychom si přáli. Takže za rok dosažení cíle lze považovat teprve rok 2011, kdy Pavel Píša odprezentoval náš Full-Diskless systém počítačové laboratoře, zhruba po roce ostrého nasazení, v rámci akce InstallFest (červen 2011).
    Citace z článku Jak jsem se dostal k vývoji disklessové infrastruktury, autor Aleš Kapica (*1969)