Koncept transparentního překrytí systémového disku nasdíleného přes NFS virtuálním diskem vytvořeným v lokální paměti, využíváme u bezdiskového linuxu od r. 2006.
Původně jsme k tomu využívali unionfs, jehož vývoj započal r. 2004. Byla to vůbec první linuxová implementace této technologie, která se začala reálně používat. S přechodem na jádro řady 2.6 však začal jeho vývoj zaostávat, proto jsme dali přednost progresivnějšímu aufs, které podporuje i nejnovější jádra řady 3.x a má zdrojový kód udržován (stejně jako kernel) v gitu.
Linuxové jádro s podporou sjednocení souborového systému
I když je modul aufs součástí distribučního jádra Debianu, není jeho zdrojový kód součástí hlavní vývojové větve jádra. Jak přidat kód pro aufs do vanilla kódu je uvedeno níže.
Do hlavní vývojové větve nebyl aufs, stejně jako unionfs přijat proto, že se vývojářům kernelu nelíbilo, že se sjednocení adresářů neprovádí v rámci VFS (virtuálního souborového systému), ale mimo něj.
Jiná použitelná alternativa nebyla dlouho k dispozici, proto vývojáři distribucí používají ke kompilaci jádra
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
aufs
|
root@nfsserver :~/git# git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git
root@nfsserver :~/git# cd aufs3-standalone.git
root@nfsserver :~/git# git checkout origin/aufs3.0
|
Zdrojáky z http://www.kernel.org
|
root@nfsserver :~/git# cd /usr/src
root@nfsserver :/usr/src# wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.8.1.tar.bz2
...
root@nfsserver :/usr/src# tar -xjf linux-3.8.1.tar.bz2
|
|
root@nfsserver :/usr/src/linux-3.8.1# cd /root/git/aufs3-standalone/
root@nfsserver :~/git/aufs3-standalone# cp -rvn ./{Documentation,fs,include} /usr/src/linux-3.8.1
...
root@nfsserver :~/git/aufs3-standalone# cd /usr/src/linux-3.8.1
root@nfsserver :/usr/src/linux-3.8.1#
|
- aufs3-kbuild.patch
- aufs3-base.patch
- aufs3-proc_map.patch
- aufs3-standalone.patch
|
root@nfsserver :/usr/src/linux-3.8.1# patch -p1 < /root/git/aufs3-standalone/aufs3-kbuild.patch
...
root@nfsserver :/usr/src/linux-3.8.1# patch -p1 < /root/git/aufs3-standalone/aufs3-base.patch
...
root@nfsserver :/usr/src/linux-3.8.1# patch -p1 < /root/git/aufs3-standalone/aufs3-proc_map.patch
...
root@nfsserver :/usr/src/linux-3.8.1# patch -p1 < /root/git/aufs3-standalone/aufs3-standalone.patch
...
root@nfsserver :/usr/src/linux-3.8.1# cd ..
root@nfsserver :/usr/src# tar -cjf linux-3.8.1-aufs.tar.bz2 linux-3.8.1
|
...
Hunk #2 succeeded at 1432 (offset 7 lines).
...
|
root@diskless :/usr/src# ln -s linux-3.8.1 linux
root@diskless :/usr/src# cd linux
root@diskless :/usr/src/linux# gunzip -c /proc/config.gz > .config
root@diskless :/usr/src/linux# make oldconfig
...
|
|
root@diskless :/usr/src/linux# make menuconfig
|
|
root@diskless :/usr/src/linux# make
...
root@diskless :/usr/src/linux# make deb-pkg
...
|
overlayfs
Jak se zdá, v brzké době se však situace změní k lepšímu a od jádra řady 3.10 by se konečně mohl stát součástí hlavní vývojové větve jádra overlayfs, který realizuje sloučení obsahu dvou adresářů do jednoho na úrovni VFS. Tedy z pohledu vývojářů správně.
V současné době má overlayfs (pokud vím) implementováno ve svém distribučním jádře Ubuntu a OpenWrt.
Skripty v ramdisku
Součástí ramdisku jsou skripty, které realizují operace, co musí proběhnout ještě před spuštěním init procesu bezdiskového systému.
Skript pro překrytí systémového disku
O překrytí systémového disku se stará univerzální skript root_overlay, který musí být - stejně jako modul pro sjednocení souborového systému - součástí ramdisku. Skript tento modul zavede a připojí virtuální disk, umístěný v paměti, který překryje systémový disk připojený přes NFS.
Protože se může spustit až poté, co je systémový disk sdílený přes NFS připojen, je uložen v podadresáři /scripts/nfs-bottom
.
root_overlay
|
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# 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
|
Skript po nastavení hostname
Tento skript je určen především pro naše bezdiskové stroje v laboratořích.
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.
|
Obsah následujícího skriptu je specifický pro potřeby sítě naší katedry. Pokud jej hodláte využít, musíte upravit část ve které se nastavuje obsah proměnné HOSTNAME na základě IPv4 adresy, kterou přiřazuje DHCP server.
|
nfsrootsetup
|
#!/bin/sh
# Setup hostnames according to IP address and create /etc/hosts
PREREQ="root_overlay"
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
echo "Setting hostname..."
# Bring in the main config
. /conf/initramfs.conf
# source relevant ipconfig output
. /tmp/net-*.conf
if [ -z "${HOSTNAME}" ]; then # No hostname sent by DHCP
case "${IPV4ADDR}" in
147.32.86.*) HOSTNAME="dcezam-${IPV4ADDR##*.}";;
147.32.87.*) HOSTNAME="dcestud-${IPV4ADDR##*.}";;
192.168.136.*) HOSTNAME="k09-${IPV4ADDR##*.}";;
192.168.202.*) HOSTNAME="k2-${IPV4ADDR##*.}";;
*) HOSTNAME="dcelinux-${IPV4ADDR}";;
esac
fi
[ -z "${DNSDOMAIN}" ] && DNSDOMAIN=local
rm -f ${rootmnt}/etc/hostname
echo ${HOSTNAME} > ${rootmnt}/etc/hostname
# Create /etc/hosts with correct IP for the server
rm -f ${rootmnt}/etc/hosts
cat <<EOF > ${rootmnt}/etc/hosts
127.0.0.1 localhost
${IPV4ADDR} ${HOSTNAME}.${DNSDOMAIN} ${HOSTNAME}
${nfsroot%%:*} nfsroot
EOF
exit 0
|
Spouštěcí skripty v systému bezdiskového stroje
- k335linux
- Skript, který symlinkuje adresář /opt
- findswap
- Skript, který se snaží najít a aktivovat lokální swap
k335linux
|
#! /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í lokálního swapovacího oddílu
Pokud je systémový adresář připojený přes NFS překrytý tak, aby ukládal data na virtuální disk v paměti, pak by měla mít klientská pracovní stanice (nebo virtuál) k dispozici swapovací diskový oddíl, který jí umožní - v případě že dojde místo v paměti - odsypat data z docházející fyzické paměti na fyzický disk.
Není-li swapovací oddíl k dispozici, tak se systém sice nezhroutí, ale začne se chovat jako když dojde místo na disku - podivně.
findswap
|
#!/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
|
Mount uživatelských adresářů
Využívá souboru /etc/hosts, který vygeneroval skript v ramdisku
Využití překrytí při přípravě binárních distribučních balíků