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

Z DCEwiki
Skočit na navigaci Skočit na vyhledávání

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.

Linuxové jádro s podporou sjednocení souborového systému

Zpočátku jsme využívali pro sjednocení souborového systému unionfs. Jeho vývoj započal r. 2004. Byla to vůbec první dostupná 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 jádra řady 3.x a zdrojový kód je udržován (stejně jako zdrojáky kernelu) v gitu.

I když je modul aufs součástí distribučního jádra Debianu, nejde o standardní modul vanilla jádra. Proto následující část demonstruje jak přidat aufs do vanilla kódu.

Součástí není proto, že se vývojářům kernelu nelíbila ani jedna z dosud zmíněných implementací. Především se jim nelíbilo, že sjednocení adresářů neprovádějí v rámci VFS (virtuálního souborového systému), ale mimo něj. Žádná jiná použitelná alternativa dlouho 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ý provádí sloučení obsahu dvou adresářů do jednoho na úrovni VFS.

V současné době má overlayfs (pokud vím) implementováno pouze distribuční jádro Ubuntu.

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

Poznámka
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

Poznámka
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


Poznámka
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
Poznámka
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).
...
Poznámka
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
...
Poznámka
root@diskless :/usr/src/linux# make menuconfig
Poznámka
root@diskless :/usr/src/linux# make
...
root@diskless :/usr/src/linux# make deb-pkg
...

overlayfs

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

Poznámka
#!/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 [[ ! "$(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 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.

Upozornění 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

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

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í 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

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

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ů