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

Technologie dynamického ramdisku, zavedená v září 2019 posunula disklessovou infrastrukturu na zcela jinou úroveň, protože umožnila zjednodušit konfiguraci zavaděče[4] a soustředit konfiguraci veškeré disklessové infrastruktury[5] do jednoho adresáře verzovaného přes git.


S rozšířením disklessu na TurtleBoty jsem od září 2019 implementoval novinku – dynamický ramdisk[6]. 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

Pokud je systémový adresář připojený přes NFS překrytý virtuálním diskem vytvořeným v paměti, je žádoucí aby klientská pracovní stanice (nebo virtuál) měla na lokálním blokovém zařízení k dispozici swapovací oddíl, který umožní - v případě že začne místo v paměti docházet - odsypat data z fyzické paměti na fyzický disk.

Není-li swapovací oddíl k dispozici, tak to sice nevede ke zhroucení systému, ale ten se pak začne chovat stejně jako když dojde místo na disku - podivně. Init skript findswap se při svém spuštění pokusí tento swapovací oddíl vyhledat a připojit.

Poznámka Od jádra ... nabízí NFS server také možnost swapování přes NFS


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

Skript postupně namountuje adresáře vrstev nasdílených přes NFS na přípojné body v ramdiskovém adresáři /tmp, pak zavede jaderný modul overlay a sestaví sendvič, který obsah vrstev připojených přes NFS překryje virtuálním tmpfs diskem vytvořeným v rámci dostupné RAM.

Na základě přidělené IPv4 adresy nastavuje aktuální hostname bezdiskového stroje a generuje soubor /etc/hosts, ve kterém ukazuje záznam nfsroot na aktuální NFS server.

Skript v ramdisku najdete v podadresáři /scripts/nfs-bottom/.

Pokud bude všechno v pořádku a linuxovému jádru nebude předána volba overlay=off najede stroj s překrytým souborovým systémem.

Zda-li overlay je či není aplikovaný lze zjistit kupř. z výpisu příkazu mount. Pokud systémový disk není překrytý, tak ho normálně vidíme namountovaný na kořen / souborového systému. V opačném případě se v tomto výpisu neobjeví.

Kam je připojený ale můžeme vidět, když si necháme vypsat obsah souboru /proc/mounts. Z něm by se měl objevit systémový disk připojený na /root.

A v adresáři /overlay/unirw by také měly být vidět veškeré nově vytvořené a změněné soubory.

Chceme-li překrytí vypnout, tak buď můžeme rovnou předat volbu overlay=off

vmlinuz ... overlay=off ...

Druhou variantou je operativní vypnutí překrytí, máme-li zaváděcí proces přerušený parametrem break. V takovém případě stačí v kořeni ramdisku vytvořit soubor s názvem off a příkazem exit pak pokračovat v zavádění.

vmlinuz ... break ...
...
(initramfs) touch off
(initramfs) exit
...
Upozornění Pokud přepínáme mezi překrytím a RW přístupem, je třeba aby byl pro RW přístup vyexportován také adresář virtuálního stroje na vzdáleném NFS serveru!


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

Ověření a přihlášení uživatele

Tohle téma řeší samostatný manuál - Ověření uživatele u 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. Více v kapitole Zavádění bezdiskových strojů.
  5. Viz – Přehled vývoje infrastruktury pro diskless Debian na katedře DCE.
  6. K vytvoření dynamického ramdisku vedl fakt, že mne nebavilo při ladění skriptů pro overlay opakovaně sestavovat ramdisk.