Překrytí systémového disku, nasdíleného přes NFS, transparentní vrstvou která ukládá změny do ramdisku v lokální paměti, využíváme u bezdiskového linuxu od r. 2006.
Zpočátku jsme využívali UnionFS. Vývoj UnionFS započatý r. 2004 ale začal s přechodem na jádro 2.6 zaostávat a proto jsme dali přednost progresivnějšímu aufs, které podporuje jádra řady 3.x a zdrojový kód udržuje (stejně jako zdrojáky kernelu) v gitu.
Přesto že je modul aufs součástí distribučního jádra v Debianu, nejde o standardní součást vanilla jádra. Vývojářům kernelu se totiž nelíbila ani jedna ze zmíněných implementací. Především z toho důvodu, že slučování provádějí mimo rámec VFS.
Dlouho žádná jiná použitelná alternativa neexistovala, ale jak se zdá od jádra řady 3.10 se konečně stane součástí hlavní vývojové větve jádra [overlayfs], který umožňuje realizovat sloučení obsahu dvou adresářů do jednoho na úrovni VFS.
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
Kompilace jádra s podporou 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
...
|
Lokální swap
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ě.
Překrytí systémového disku
Překrytí systémového disku zajišťují dva skripty, umístěné v ramdisku.
Vyžadují instalaci nástrojů v initramfs-tools
- root_overlay
- Překryje systémový disk připojený přes NFS pomocí aufs
- nfsrootsetup
- Vygeneruje nový obsah souboru
/etc/hosts
, ve kterém použije doménové jméno nfsroot pro aktuální NFS server
root_overlay
|
#!/bin/sh
# Remounting root as overlay filesystem
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
|
Kód, který provede detekci a případně zavedení modulu, který umožní provést překrytí systémového adresáře...
|
insmodule()
{
if ! grep -q $1 /proc/filesystems ; then
modprobe $1 >/dev/null 2>/dev/null
if ! grep -q $1 /proc/filesystems ; then
if [[ ! "$(insmod ${rootmnt}/lib/modules/$(uname -r)/extra/$i/$i.ko)" ]] ; then
echo $1
fi
else
echo $1
fi
else
echo $1
fi
}
for i in overlayfs aufs unionfs
do
OVERLAY=$(insmodule $i)
[ "$OVERLAY" != "no" ] && break
done
|
Kód, který připraví přípojný bod a namountuje virtuální disk, kterým se překryje namountovaný systémový disk...
|
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
|
A vytvoření adresářů, nezbytných pro běh systému.
|
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
|
nfsrootsetup
|
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.
|
|
#!/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
|
Doplňkové operace...
- 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í swapu - 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ů