Difference between revisions of "Překrytí systémového disku - overlay filesystem"

From DCEwiki
Jump to: navigation, search
m (Skripty)
m (Spouštěcí skripty a operace v systému bezdiskového stroje)
 
Line 233: Line 233:
 
</syntaxhighlight>}}
 
</syntaxhighlight>}}
  
=== Spouštěcí skripty a operace v systému bezdiskového stroje ===
+
== Spouštěcí skripty a operace v systému bezdiskového stroje ==
  
 
==== Init skript pro spouštění dalších operací ====
 
==== Init skript pro spouštění dalších operací ====

Latest revision as of 15:26, 25 September 2019

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 r. 2006.

Původně se používal 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. S přechodem na jádro řady 2.6 však začal vývoj unionfs zaostávat, proto byl upřednostěn progresivnější aufs, který podporoval i novější jádra řady 3.x a měl – stejně jako linuxový kernel – zdrojový kód udržovaný v git repozitáři a verzovaný vůči aktuálním verzím jádra.

Bohužel, klíčový problém aufs byl (a je), že není součástí hlavní vývojové větve linuxového jádra, přes to, že se o začlenění jeho vývojář Junjiro R. Okajima řadu let snažil. Vývojářům kernelu se nelíbilo, že aufs sjednocení adresářů neprovádí v rámci VFS (virtuálního souborového systému), ale mimo něj – stejně jako původní unionfs. Proto nakonec upřednostnili overlay, který provádí sjednocení adresářů na úrovni VFS. [1]

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[2].
overlay 
Původně vyvíjený jaderný modul s názvem overlayfs, se stal součástí hlavní vývojové větve jádra od verze 3.18-rc2 pod názvem overlay[3].
unionfs-fuse 
Overlay lze také řešit přesunion-fuse. Ten soubory honí v uživatelském prostoru, což představuje zhruba 20% ztrátu výpočetního výkonu procesoru. Což je pro účely disklessu akceptovatelné.
mcachefs 
Umožňuje použít lokální blokové zařízení jako keš nad připojeným NFS adresáře. V podstatě se to chová také jako overlay, ovšem s tím rozdílem, že vytahuje při čtení soubory z podkladové vrstvy nahoru, což overlay nedělá. S výhodou lze toho využít u dynamického ramdisku


Linuxový systém nad NFS[edit]

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[edit]

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[edit]

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[edit]

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
Poznámka
#!/bin/sh
### BEGIN INIT INFO
# Provides:          findswap
# Required-Start:    mountall
# Required-Stop: 
# Should-Start:
# Should-Stop:
# Default-Start:     S
# Default-Stop:
# Short-Description: Find all unused swap partitions to enable swapping on them
# Description:
### END INIT INFO

do_start() {
  SWAPCANDIDATES="$(cat /proc/partitions | sed -n -e 's/^.* \([hs]d[a-z][0-9]\)$/\1/p' -e 's/^.* \(xvd[a-z][0-9]\)$/\1/p')"
  for i in $SWAPCANDIDATES ; do
    if [ "$( blkid -s TYPE /dev/$i -o value )" = "swap" ] ; then
      grep -q "/dev/$i" /proc/swaps
      if [ $? -ne 0 ] ; then
        echo "Adding swap device /dev/$i."
        swapon "/dev/$i"
      fi
    fi
  done
}

case "$1" in
  start|"")
	do_start
	;;
  restart|reload|force-reload)
	echo "Error: argument '$1' not supported" >&2
	exit 3
	;;
  stop)
	# No-op
	;;
  *)
	echo "Usage: $0 [start|stop]" >&2
	exit 3
	;;
esac

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

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!
Poznámka
#!/bin/sh

PREREQ=""
prereqs()
{
     echo "$PREREQ"
}

case $1 in
prereqs)
     prereqs
     exit 0
     ;;
esac

# Kód pro vypnutí překrytí předáním volby overlay=off jádru
[ "${overlay}" == "off" ] && exit 0 || [ -e /off ] && exit 0

# Kód, co se stará o zavedení modulu, který umožní překrytí souborového systému...
insmodule()
{
    if ! grep -q $1 /proc/filesystems ; then
        modprobe $1 >/dev/null 2>/dev/null
        if ! grep -q $1 /proc/filesystems ; then
            if [ -d "${rootmnt}/lib/modules/$(uname -r)/extra/$1" ] ; then
                if [ ! "$(insmod ${rootmnt}/lib/modules/$(uname -r)/extra/$1/$1.ko)" ] ; then
                    echo $1
                fi
            fi
        else
            echo $1
        fi
    else
        echo $1
    fi
}

for i in overlayfs aufs unionfs
do
    OVERLAY=$(insmodule $i)
    [ "$OVERLAY" == "$i" ] && break
done

# Kód, který připraví přípojný bod a namountuje virtuální disk, kterým se překryje systémový  disk
# namountovaný přes NFS...
mkdir /tmp/unirw
mount -n -t tmpfs none /tmp/unirw

case "$OVERLAY" in
    overlayfs) echo "Remounting root as overlayfs ..."
        mount -n -t overlayfs -o upperdir=/tmp/unirw,lowerdir=${rootmnt} overlayfs ${rootmnt}
        ;;
    aufs) echo "Remounting root as aufs ..."
        mount -n -t aufs -o dirs=/tmp/unirw=rw:${rootmnt}=nfsro unionfs ${rootmnt}
        ;;
    unionfs) echo "Remounting root as unionfs ..."
        mount -n -t unionfs -o dirs=/tmp/unirw=rw:${rootmnt}=ro unionfs ${rootmnt}
        ;;
    *) panic "Actual initrd.img has not a module for overlay filesystem"
        ;;
esac

# Mají-li být data co se ukládají na virtuální disk - kterým je systémový disk překrytý - dostupná,
# pak je třeba provést přesun namountovaného virtuálního disku do adresářové struktury sjednoceného
# souborového systému. V opačném případě lze tento kód vynechat.
mkdir -p ${rootmnt}/overlay/unirw
mount -n -o move /tmp/unirw ${rootmnt}/overlay/unirw
chmod 755 ${rootmnt} # Disable rw access for non-root users

# Vytvoření adresářů, na které se mountují další virtuální souborové systémy.
mkdir -p ${rootmnt}/dev
mkdir -p ${rootmnt}/proc
mkdir -p ${rootmnt}/sys
mkdir -p ${rootmnt}/tmp
mkdir -p ${rootmnt}/run
mkdir -p ${rootmnt}/var/lock

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

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

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[edit]
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ářů[edit]

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ů[edit]

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

Použití[edit]

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ů[edit]

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í[edit]

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[edit]

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[edit]

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. 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
  2. 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 jádro, aby obsahovalo modul aufs.
  3. Dlouho se zdálo, že se po začlenění overlayfs situace změní k lepšímu, protože nebude nutné pro jiné distribuce, než Debian patchovat jádro. Jenže začlenění se neustále odsouvalo. Původně bylo ohlášeno již pro jádra řady 3.10, ale nakonec k tomu došlo až u jader řady 3.18 Po začlenění byl název jaderného modulu byl z původního overlayfs změněn na overlay, ovšem mnohem závažnější problém nastal v tom, že změny v jeho kódu znemožnily použít jako podkladový souborový systém adresář sdílený přes NFS. Tento nedostatek byl odstraněn až od verze …
  4. K vytvoření dynamického ramdisku vedl fakt, že mne nebavilo při ladění skriptů pro overlay opakovaně sestavovat ramdisk.