Aus Linux-Magazin 07/2006

Netzwerkblockgeräte in neuen Missionen (Seite 5)

Auch dieser Ansatz hat aber Nachteile: Hoher Aufwand beim Erstellen der Initial RAM-Disk, Overhead durch Blockdevice und Filesystem sowie der schwierige Übergang aus dem kleinen Root-Filesystem der Initial RAM-Disk auf das neu eingehängte Root-Filesystem des Clients. Den Übergang organisiert »pivot_root«, »freeramdisk« gibt am Ende den Speicher der RAM-Disk wieder frei.

Abbildung 5: Die im Artikel vorgestellten Techniken lassen sich durchaus kombinieren. Blockgeräte tragen meist blockbasierte Dateisysteme. Sonderfälle sind Cowloop oder Union-FS, die - basierend auf Blockgeräten oder Dateisystemen - eine neue beschreibbare Schicht bilden.

Abbildung 5: Die im Artikel vorgestellten Techniken lassen sich durchaus kombinieren. Blockgeräte tragen meist blockbasierte Dateisysteme. Sonderfälle sind Cowloop oder Union-FS, die – basierend auf Blockgeräten oder Dateisystemen – eine neue beschreibbare Schicht bilden.

Early Userspace

Die jüngste Entwicklung namens Early Userspace wird mittelfristig sowohl Kernel-Root auf NFS als auch die Initial RAM-Disk ablösen. Es handelt sich um spezielle Kernelstrukturen (Initram-FS), die ein einheitliches Root-Filesystem abbilden. Es lässt sich beispielsweise als Temp-FS direkt in den Kernel einkompilieren oder (ähnlich wie die Initial RAM-Disk) als CPIO-Archiv auch separat halten und laden.

Für den Übergang zum einzubindenden Root-Filesystem sorgt seit Kernel 2.6.15 nicht mehr »pivot_root«. Es genügt nun, den Mountpoint nach »/« zu verschieben. Die Inhalte, die vorher an dieser Stelle lagen, löscht das kleine Programm »run-init« (zu finden in der Klibc).

Bordmittel allein genügen nicht, um NBD zu verwenden, das spätere Root-Filesystem aus mehreren Teilen zusammenzusetzen und alles mittels Union-FS zu verbinden. Die einzelnen Mount-Vorgänge und das Laden der entsprechenden Module fasst am besten ein Shellskript zusammen (gekürzte Fassung in Listing 3), das den Namen »init« erhält und im Initram-FS steht.

Listing 3:
Init-Skript

01 #!/bin/sh
02 
03 # IP-, NFS- und (D)NBD-Parameter aus der Kernel-Kommandozeile lesen
04 for opts in ${KCMDLINE} ; do
05   case ${KCMDLINE} in
06     ip=*)
07       # IP-Konfiguration: client-ip:server-ip:gateway:netmask
08       IPINFO=${opts#ip=};;
09     nfsroot=*)
10       # NFS-Server und Pfad
11       NFSROOT=${opts#nfsroot=};;
12     nbdroot=*)
13       # NBD-Konfiguration: server:port
14       NBD=nbd # name of kernel module
15       NBDOPT=${opts#nbdroot=};;
16     dnbdroot=*)
17       # DNBD-Konfiguration: server:port
18       NBD=dnbd # name of kernel module
19       NBDOPT=${opts#dnbdroot=};;
20     dcsize=*)
21       # RAM-Cache-Größe für DNBD
22       DNBDCACHESIZE=${opts#dcsize=};;
23   esac
24 done
25 RWDIR=/dev/shm
26 
27 # Root-Filesystem via NBD/DNBD importieren
28 if [ -n "${NBD}" ] ; then
29   nbdhost=${NBDOPT%:*}
30   nbdopt=${NBDOPT#*:}
31   nbdport=${nbdopt%,*}
32   nbdfs=${nbdopt#$nbdport*}
33   if [ -z "$nbdfs" ]; then
34     RFST=ext2;
35   else
36     RFST=${nbdfs#*,};
37   fi
38   echo "Diskless client using ${NBD} on $nbdhost:$nbdport with $RFST"
39   modprobe ${RFST}
40   case "${NBD}" in
41     nbd)
42       # Network Block Device des Standardkernels
43       sleep 2
44       nbd-client $nbdhost $nbdport /dev/nbd0
45       RDEV=/dev/nbd0;;
46     dnbd)
47       # DNBD (Distributed Network Block Device)
48       if [ -z $nodnbdcache ] ; then  # variable not really used yet
49         mkdir /dnbd
50         mount -n -o 'size=$dcsize' -t tmpfs tmpfs ${RWDIR}
51         cat /dev/zero > ${RWDIR}/cache 2>/dev/null
52         clientopt="-c ${RWDIR}/cache"
53       fi
54       sleep 2
55       while ! dnbd-client -b $nbdhost -d /dev/dnbd0 $clientopt ; do
56         sleep 1
57       done
58       RDEV=/dev/dnbd0;;
59   esac
60   RWRO="ro"
61   if [ -n "${COWLOOP}" -a -x /bin/cowdev ] ; then
62     modprobe cowloop
63     echo "Using Copy-on-Write block device for rw access"
64     mount -n -t tmpfs -o size=50% ramfs ${RWDIR}
65     mkdir /dev/cow && cp -a /tmp/ctl /dev/cow
66     ln -s /dev/cowloop0 /dev/cow/0
67     cowdev -a ${RDEV} ${RWDIR}/nbd.cow
68     usleep 10
69     RWRO="rw"
70     RDEV=/dev/cow/0
71   fi
72   sleep 2
73   mount -n -t $RFST -o $RWRO $RDEV /mnt
74 
75 # Root-Filesystem via NFS importieren
76 elif [ -n NFS ]
77   modprobe nfs
78   portmap
79   NFSRO=nfs
80   mount -t nfs [...]
81 fi
82 
83 # Union-FS aktivieren
84 echo "Using UnionFS for rw access"
85 RWDIR=/dev/shm
86 mkdir -p ${RWDIR}/union ${RWDIR}/uniontmp
87 mount -n -t tmpfs none ${RWDIR}/uniontmp
88 mount -n --move /mnt /root
89 mount -n -t unionfs -o dirs=${RWDIR}/uniontmp=rw:/root=${NFSRO}ro none /mnt
90 mkdir -p /mnt/uniontmp
91 mount -n --move ${RWDIR}/uniontmp /mnt/uniontmp
92 mount -n --move /root /mnt/mnt
93 
94 # Pivoting nach neuer Art
95 exec run-init -c dev/console /mnt /sbin/init

NFS und NBD/DNBD im Initram-FS

Das Skript muss einige wichtige Konfigurationsdaten erhalten. Wer diese Parameter nicht in einer Datei im Initram-FS speichern möchte, weil er dann für jede bootende Maschine ein eigenes Filesystem-Image braucht, übergibt die Werte am Bootprompt an den Kernel. Hier kann er beliebige Strings hineinschreiben, die der Kernel zwar nicht versteht, die aber das Init-Skript anschließend auswertet. Diese Taktik verwendet beispielsweise auch Knoppix, um Konfigurationsoptionen von der Benutzerauswahl im Bootmenü in das später laufende Linux-System zu transportieren.

Die Zeilen 4 bis 24 von Listing 3 werten die Kommandozeile aus und schreiben die Parameter in Variablen. Der Kernelstring für NFS (»nfsroot= Server:Pfad«) dient als Vorbild für das Format von Root on NBD/DNBD. Bei NBD ist die Angabe der Portnummer Pflicht, die Option ist »nbdroot= Server:Port,Filesystem«. Bei DNBD heißt das Schlüsselwort »dnbdroot=…«. Die Portnummer dahinter darf entfallen, das Komma muss aber bleiben. Zeile 22 liest die erlaubte Größe für das DNBD-Cachefile. Es lassen sich noch weitere Parameter übergeben, etwa für das Diff-File von Cowloop.

Theoretisch könnte auch ein DHCP-Server die Konfigurationsdaten verteilen [11]. Dazu wäre jedoch ein DHCP-Client wie »dhclient« nötig, der benutzerdefinierte Variablen kennt. Bei der IP-Konfiguration im Initram-FS kommt aber meist ein recht simpler Client aus dem Klibc-Paket [15] zum Einsatz.

Ziel-Root

Die Zeilen 28 bis 59 von Listing 3 holen das Root-Filesystem vom Server per NBD oder DNBD. Bei NBD genügt der Aufruf in Zeile 44; DNBD verlangt etwas mehr Arbeit. Der Block in den Zeilen 61 bis 71 verwendet auf Wunsch Cowloop, um das Blockdevice beschreibbar zu machen. Diese Tatsache vermerkt Zeile 69 in der Variablen »RWRO«.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Comments
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben