Selbst betagte Rechner kommen als Diskless-Clients unter Linux dank transluzenter Dateisysteme und anderer Zutaten zu neuen Ehren – ersparen sie ihren Admins doch jede Menge Arbeit.
Wo Software auf eine so große Anzahl Clients zu verteilen ist, dass der Rundgang mit der Installations-CD von vornherein ausscheidet, bieten sich einige Alternativen an. Häufig fällt die Wahl auf eine Administrationssoftware, die Betriebssystem, Anwendungen und Updates aus einem zentralen Repository via Netzwerk und gegebenenfalls mittels Wake-on-LAN auf die Clients verbreitet. Dieses an sich recht übersichtliche Verfahren kann in der Praxis jedoch schnell zu einem Alptraum ausarten. Denn gerade dann, wenn sich die Konfiguration der Zielmaschinen sehr rasch ändert, stößt diese Herangehensweise bald an ihre Grenzen.
Doch Abhilfe ist möglich. In der Unix-Welt sind Diskless-Clients weit verbreitet, die ihren Kernel und auch das Wurzeldateisystem übers Netzwerk beziehen. Damit entfällt die Softwareverteilung, weil alle Programme auf einem zentralen Server bleiben. Hat der Client genügend eigene Rechenpower, kann er als so genannter Rich-Client lokal Applikationen ausführen. Bei Thin-Clients findet andernfalls auch die Datenverarbeitung komplett auf dem Server statt.
PXE ist Standard
Die Zeiten, in denen man für den Systemstart via Netzwerk Boot-ROMs für exotische Netzwerkkarten brennen oder zumindest eine Bootdiskette dabei haben musste, sind so gut wie vorbei: Intels PXE-Industriestandard steckt in fast jedem PC, der damit in der Lage ist, ohne ein lokales Bootmedium sein Betriebssystem zu starten.
Wenn die Voraussetzungen erfüllt sind, kann man das Bios so umkonfigurieren, dass der PC immer via Netzwerk bootet. Dazu bedarf es lediglich eines DHCP-Servers für die Vergabe der IP-Adresse und der Bootloader-Definition sowie eines TFTP-Servers, der den Client erst mit dem Bootloader und danach mit dem Linux-Kern versorgt (Abbildung 1). Oftmals ist mit dem DHCP-Server auch noch ein dynamischer DNS-Server (DDNS) verbunden, der den Namen des gerade gestarteten Clients nach einer erfolgreichen DHCP-Adressenvergabe in den DNS-Dienst einträgt [1].
Hat der Linux-Kern auf der Clientmaschine seinen Dienst aufgenommen, verlangt er die Wurzel eines Dateisystems, um den Urprozess, meist »init«, starten zu können. Im Fall des Diskless-Clients ist dies natürlich ein Netzwerk-Dateisystem, genauer gesagt NFS, denn etwas anderes wird vom Linux-Kern an dieser Stelle nicht unterstützt. Zusätzlich müssen einige Kerneloptionen korrekt eingestellt sein [2].
Komplexität begrenzen
Beruht das Konzept einer derartigen Systemlandschaft auf plattenlosen Clients, ist eine der Randbedingungen, dass die Komplexität nicht beliebig steigen darf. Stattdessen sollen Standardlösungen den Administratoren das Leben erleichtern. Das hier vorgestellte Beispiel verwendet aus diesem Grund eine unmodifizierte Linux-Distribution, komplizierte Anpassungen entfallen. Ein Update der eingesetzten Software zieht also nicht die Anpassung einer Unzahl von Skripten nach sich. Zusätzlich gestaltet sich auch die Installation von Diskfull- und Diskless- Clients gleich.
Als Distribution für Server und Clients kommt Gentoo zum Einsatz. Die Installation eines Diskfull-Systems geschieht dort über eine »chroot()«-Umgebung, was auch beim Diskless-Client passt. Änderungen an den Start-Stop-Skripten können unterbleiben, damit geht der Admin möglichen Problemen bei einem Upgrade von vornherein aus dem Weg. Anzupassen sind nur Skripte, die zu Applikationen gehören, die der Anwender außerhalb der Gentoo-Paketverwaltung Portage installiert hat.
In einem Gentoo-Server sind die erforderlichen Dienste mit wenigen Kommandos schnell aufgesetzt:
emerge net-misc/dhcp emerge net-ftp/tftp-hpa emerge net-fs/nfs-utils
Die Konfiguration des DHCP-Servers ist in [3] nachzulesen. Listing 1 enthält ein entsprechendes Beispiel, die »subnet«-Blöcke sind jeweils den lokalen Gegebenheiten anzupassen. Die entscheidenden Optionen heißen »next-server« und »filename«. Die Option »next-server« bezeichnet den TFTP-Server. Im Beispiel ist dies derselbe Server, was aber nicht so sein muss.
|
Listing 1: |
|---|
01 allow unknown-clients;
02 default-lease-time 1800; # 30 minutes
03 max-lease-time 7200; # 2 hours
04
05 subnet 192.168.39.0 netmask 255.255.255.0 {
06 range 192.168.39.128 192.168.39.254;
07 option broadcast-address 192.168.39.255;
08 option domain-name-servers 192.168.39.1;
09 option domain-name "localdomain";
10 next-server 192.168.39.10;
11 filename "gentoo_A/boot/pxelinux.0";
12 }
|
Netzwerk-Boot vorbereiten
Als Wert für die Option »filename« trägt der Admin den Pfad des Bootloaders relativ zur Wurzel des TFTP-Servers ein. Ob er hierfür die Grub-Variante »pxegrub« [4] oder aber »pxelinux« aus dem Projekt Syslinux [5] einsetzt, ist Geschmackssache. Doch ist die Unterstützung für neuere Netzwerkkarten bei »pxelinux« besser, dafür entfällt im Vergleich mit »pxegrub« das grafische Bootmenü.
Die Konfiguration des TFTP-Servers beschränkt sich im Wesentlichen auf die Wahl der Wurzel des bereitgestellten Dateisystembaums. Die folgenden Zeilen in »/etc/conf.d/in.tftpd« wählen hierfür »/tftproot«:
INTFTPD_PATH="/tftproot"
INTFTPD_OPTS="-u nobody -l -s -v ${INTFTPD_PATH}"
Auch die Konfiguration des NFS-Servers birgt keine Geheimnisse. Die folgenden Zeilen in »/etc/exports«
/tftproot/gentoo_A 192.168.39.*(ro,sync,no_root_squash) /sync 192.168.39.*(ro,sync,no_root_squash) /home 192.168.39.*(rw,sync,root_squash)
exportieren die Verzeichnisse »/tftproot/gento_A« und »/sync« lesend und außerdem das Verzeichnis »/home« lesend und schreibend für die Clients. Die Verwendung des Verzeichnisses »/sync« wird später klar.
Installation des Clients
Bevor ein Client erfolgreich starten kann, muss das zukünftige Wurzeldateisystem des Clients unterhalb von »/tftproot/gentoo_A« gefüllt sein. Dies gelingt bei Gentoo ohne Besonderheiten, da hier ja die Installation ab einer bestimmten Stufe immer in einer »chroot()«-Umgebung stattfindet. Und genau an dieser Stelle kreuzt der Weg die ganz normale Installation [7]:
chroot /tftproot/gentoo_A /bin/bash mount -t proc none /proc env-update . /etc/profile
Die folgenden Schritte beziehen sich – wie bei Gentoo üblich – auf diese »chroot()«-Umgebung. Für den Client ist ein Kernel erforderlich, der die Option »Networking | Networking Options | IP: Kernel Level Autoconfiguration« gesetzt hat, damit er in der Lage ist, die erste IP-Konfiguration selbst via DHCP vorzunehmen. Zusätzlich sollten die benötigten Netzwerk-Kartentreiber einkompiliert und die Option »NFS-Root« gesetzt sein (Listing 2).
|
Listing 2: |
|---|
01 <*> NFS file system support 02 [*] Provide NFSv3 client support 03 [ ] Provide client support for the NFSv3 ACL protocol extension 04 [ ] Provide NFSv4 client support (EXPERIMENTAL) 05 [ ] Allow direct I/O on NFS files (EXPERIMENTAL) 06 < > NFS server support 07 [*] Root file system on NFS |
Dies und die Kompilation des Kernels erledigt effektiv »genkernel« mit »emerge genkernel; genkernel –menuconfig all«. Am Ende finden sich dann unter »/boot« wie gewohnt der Kern und die initiale RAM-Disk, die man verwenden kann, aber nicht muss.
Der Admin sollte auch an »/etc/conf.d/keymaps« denken und in »/etc/fstab« das via NFS zu montierende Wurzeldateisystem mit folgender Zeile eintragen: »192.168.39.10:/tftproot/gentoo_A / nfs defaults,ro 0 0«. Die sonstigen Systemtools kann er wie üblich und nach Geschmack installieren.
Hat der Kern dann im späteren Betrieb das primäre Netzwerk-Interface konfiguriert, so dürfen die Bootskripte nicht noch einmal eine IP-Adresse anfordern. Andernfalls würde der Client plötzlich ohne sein Wurzeldateisystem dastehen. Diesen Fehler verhindert der folgende Eintrag in »/etc/conf.d/net«: »config_eth0 = ( “noop” )«.
Booten übers Netz
Die Konfiguration von »pxelinux« aus Listing 3 erlaubt es, den Client immer noch über eine eventuell vorhandene Festplatte oder eben weiterhin über das Netzwerk zu starten. Daher sind hier unterschiedliche Einträge vorgesehen. Die Netzwerk-Bootvorgänge unterscheiden sich nur durch die Parameter für den Kernel, die später den Bootvorgang dynamisch steuern. Damit kann der Admin alle Clients generell auf PXE-Boot umstellen. Sie bieten ein einheitliches Bootmenü an.
|
Listing 3: |
|---|
01 default L 02 timeout 100 03 prompt 1 04 display msg.txt 05 06 label L 07 LOCALBOOT 0 08 09 label l 10 LOCALBOOT 0 11 12 label R 13 kernel /gentoo_A/boot/EbzImage 14 append ip=dhcp root=/dev/nfsnfsroot=192.168.39.10:/tftproot/gentoo_A,hard,intr,ro udev init=/stateless.sh stateless=unionfs xauto=auto 15 16 label r 17 kernel /gentoo_A/boot/EbzImage 18 append ip=dhcp root=/dev/nfsnfsroot=192.168.39.10:/tftproot/gentoo_A,hard,intr,ro udev init=/stateless.sh stateless=unionfs xauto=auto |
Da »syslinux« auf dem Client noch nicht vorhanden ist, installiert der Admin es kurzerhand nach: »emerge sys-boot/syslinux«. Die grundsätzliche Einrichtung eines Diskless-Clients ist damit abgeschlossen. Ein Test verliefe aber noch nicht erfolgreich, weil ja das Wurzeldateisystem nur read-only exportiert ist. Daher könnte der Client weder unter »/var« seine Logfiles schreiben noch eine »/etc/mtab« anlegen.
Durchscheinende Dateien
Abhilfe schafft ein transluzentes Dateisystem. Es erreicht außerdem, dass gegebenüber einer einfachen Installation [7] nicht für jeden Diskless-Client ein eigenes Wurzelverzeichnis bereitgestellt werden muss. Obwohl das transluzente Dateisystem Union-FS [8] in Gentoo noch maskiert, also nicht ohne weiteres installierbar ist, reicht seine Stabilität für den vorliegenden Zweck bereits aus. Der Administrator kann deshalb die Maskierung unbesorgt aufheben und die aktuelle Version mit »ACCEPT_KEYWORDS=”~x86″ emerge unionfs« aufspielen.
Union-FS erlaubt es, das vom Server exportierte Wurzelverzeichnis zunächst unverändert und schreibgeschützt zu übernehmen. Es wird dann zusammen mit einem beschreibbaren Dateisystem zu einem Union-Mount vereinigt. Änderungen landen in dem beschreibbaren Zweig der Vereinigung.
Damit Gentoos Portage-System bei späteren Upgrades des Clients reibungslos funktioniert, weist der Admin den Kernel über seine Parameter (Listing 3) dazu an, statt »init« das Shellskript »stateless.sh« (Listing 4) zu starten. Es sorgt für die notwendigen Overlay-Mounts für »/etc« und »/var« (Abbildung 2). Das darunter liegende Read-Write-Dateisystem benutzt das RAM-Disk-Dateisystem Temp-FS. Das passiert vor dem Gentoo-Startvorgang und wird auch außerhalb des Systems, im Bootloader konfiguriert.
|
Listing 4: |
|---|
01 #!/bin/bash
02
03 MODPROBE=/sbin/modprobe
04 IFCONFIG=/sbin/ifconfig
05
06 ahostname(){
07 MYHOST="$1_`$IFCONFIG eth0 | awk '/HWaddr/ {print $5}' | tr -d ':'`"
08 echo "STATELESS: Setting Hostname to $MYHOST"
09 echo "HOSTNAME="$MYHOST"" > /etc/conf.d/hostname
10 /bin/hostname "$MYHOST"
11 }
12
13 getparams() {
14 local cmdline=$(dmesg | grep '^Kernel command line' | sed 's/^Kernel command
15 line://g')
16 for pp in $cmdline; do
17 echo $pp | grep '^stateless=' >/dev/null 2>&1
18 if [ $? -eq 0 ]; then
19 echo $pp | sed 's/stateless=//g'
20 return 0
21 fi
22 done
23 echo ""
24 return 1
25 }
26
27 isset() {
28 for p in $(getparams | tr ',' ' '); do
29 if [ "$p" == "$1" ]; then
30 return 0
31 fi
32 done
33 return 1
34 }
35
36 aunionfs() {
37 isset unionfs
38 if [ $? -eq 0 ]; then
39 echo "STATELESS: Loading module unionfs ..."
40 $MODPROBE unionfs
41 while [ "$1" != "" ]; do
42 echo "STATELESS: Mounting tmpfs $1 ..."
43 mount -n -t tmpfs -o defaults none /mnt/unionfs/$1
44 echo "STATELESS: Mounting $1 unionfs ..."
45 mount -n -t unionfs -o dirs=/mnt/unionfs/$1=rw:/$1=ro none /$1
46 shift
47 done
48 else
49 echo "STATELESS: Not using unionfs as requested ..."
50 fi
51 }
52
53 aunionfs etc var
54 ahostname stateless
55 exec /sbin/init
|

Abbildung 2: Dieser Ausschnitt aus dem Dateisystem des Clients zeigt die Overlay-Mounts für die Verzeichnisse »/etc« und »/var«.
Eigenes Init
Das Skript sorgt auch für die Vergabe eines unverwechselbaren Hostnamens auf Basis der MAC-Adresse. Danach überlagert es sich mit »init« – und alles geht normal weiter, der Client bootet wie üblich. Die Änderungen in »/etc« und »/var« gelangen in die RAM-Disk und sind nach dem Herunterfahren verloren. Aus diesem Grunde spricht man auch von einem Stateless-Rich-Client.
Für das Skript »stateless.sh« steht unter [10] auch ein Portage-Ebuild bereit. Da dies eine Abweichung vom offiziellen Portage-Tree ist, sollte der Admin für diese Zwecke unter »/usr/local/portage« einen lokalen Portage-Zweig einrichten. Dies geschieht durch die Option »PORTDIR_OVERLAY=”/usr/local/portage”« in der Datei »/etc/make.conf«. Anschließend kopiert er einfach »sys-apps/stateless-0.1_pre.ebuild« nach »/usr/local/portage/sys-apps/stateless« und installiert mit »emerge stateless«.
Zu guter Letzt ist noch die Konfigurationsdatei des Bootloaders anzupassen. Die Kerneloption »stateless=unionfs« schaltet den zustandslosen Rich-Client für das nächste Booten scharf. An dieser Stelle sollte auch gleich ein »depmod -a« ausgeführt werden, denn bei einem späteren Start des Clients ist dies durch das Read-only-Wurzeldateisystem nicht mehr möglich.
Das grundsätzliche Konzept lässt sich in einigen Punkten noch weiter verfeinern. Da alle Logging-Informationen bei einem Neustart verloren gehen, schickt der Client diese Daten besser über Syslog-NG [16] an einen zentralen Logging-Server. Je nach Bedarf und Vorliebe kann der Administrator auf dem Logging-Server für jeden Client wieder getrennte Logdateien vorsehen. Listing 5 zeigt die Syslog-Konfiguration für den Client und Listing 6 die für den Server.
|
Listing 5: |
|---|
01 options {
02 long_hostnames(off);
03 sync(0);
04 stats(43200);
05 };
06 source src { unix-stream("/dev/log"); internal(); pipe("/proc/kmsg"); };
07 destination server { udp("192.168.39.10",port(514)); };
08 log { source(src); destination(server); };
|
|
Listing 6: |
|---|
01 options {
02 chain_hostnames(off);
03 keep_hostname(yes);
04 sync(0);
05 stats(43200);
06 };
07 source src { unix-stream("/dev/log"); internal(); pipe("/proc/kmsg"); };
08 source remote {
09 udp (
10 ip("0.0.0.0")
11 port(514)
12 );
13 };
14 destination messages { file("/var/log/messages"); };
15 destination hosts {
16 file("/var/log/hosts/$FULLHOST"
17 create_dirs(yes));
18 };
19 log {source(src); destination(messages); };
20 log {source(remote); destination(hosts); };
|
LDAP einbinden
Die Benutzerdatenbank »/etc/passwd« und »/etc/shadow« stehen zwar allen Clients zum Lesen zur Verfügung, doch ist es in einer größeren Umgebung selbstverständlich, eine zentrale Benutzerdatenbank zu verwenden. In einer reinen Unix/Linux-Welt kommt dafür wohl in den meisten Fällen ein OpenLDAP-Server zum Einsatz, in Mischumgebungen zusammen mit Windows ist die bessere Wahl allerdings ein Microsoft Active Directory Server (ADS). Hierfür benötigt der Client sowohl »nss_ldap« als auch »pam_ldap«. Mit dem Portage-System ist das schnell erledigt: »emerge nss_ldap pam_ldap«.
Für den Active Directory Server ist noch die Schema-Erweiterung Microsoft Services for Unix (MSSFU) notwendig. Auch braucht »/etc/ldap.conf« (Listing 7) noch ein Attribute-Mapping, um der anderen Namensgebung dieses Schemas Rechnung zu tragen. Damit sowohl die Authentifizierung als auch die Attributezuordnung zu den Benutzern über LDAP laufen, sind sowohl der Nameservice-Switch (NSS) als auch der PAM-Stack anzupassen. Der Artikel in [11] beschreibt diesen Vorgang ausführlich.
|
Listing 7: |
|---|
01 base dc=ds,dc=fh-kl,dc=de 02 uri ldaps://dc1.ds.fh-kl.de ldaps://dc2.ds.fh-kl.de 03 ldap_version 3 04 05 binddn cn=buser,cn=users,dc=ds,dc=fh-kl,dc=de 06 bindpw buserpw 07 08 # Services for UNIX 3.5 mappings 09 nss_map_objectclass posixAccount User 10 nss_map_objectclass shadowAccount User 11 nss_map_attribute uid sAMAccountName 12 nss_map_attribute uidNumber msSFU30UidNumber 13 nss_map_attribute gidNumber msSFU30GidNumber 14 nss_map_attribute uniqueMember member 15 nss_map_attribute homeDirectory msSFU30HomeDirectory 16 nss_map_attribute loginShell msSFU30LoginShell 17 nss_map_objectclass posixGroup Group 18 pam_filter objectclass=User 19 pam_password ad 20 pam_login_attribute sAMAccountName 21 22 ssl on 23 tls_checkpeer no 24 referrals no |
Zentrale Ablage
Die Benutzer benötigen ein zentrales Dateisystem für ihre Daten. In einer reinen Unix/Linux-Umgebung eignet sich dafür wohl wieder NFS am besten. In einer Linux/Windows-Mischumgebung reicht NFS nicht aus. Für die Windows-Welt ist ein CIFS-Fileserver notwendig. Bei der Entscheidung zugunsten eines Windows-Fileservers gibt es allerdings Probleme mit anderen Dateitypen jenseits von regulären Dateien und Verzeichnissen. Damit scheidet ein Windows-Fileserver eigentlich aus.
Mit Samba und den CIFS-Unix-Extensions lassen sich diese Probleme vermeiden. Allen CIFS-Servern bleibt jedoch gemeinsam, dass sie eine benutzer- und sitzungsbezogene Authentifizierung erfordern. Die wiederum ist ein typischer Anwendungsfall für das Sitzungsmanagement im PAM-Stack des Clients.
Der zugehörige Mount-Helper »mount.cifs« stammt aus der Samba-Suite, die Kernelunterstützung für CIFS ist dank »genkernel« schon im Kernel enthalten. Die User-Level-Tools sind wie gewohnt zu installieren: »emerge nfs-utils samba«. Das bereits betagte und in manchen Situationen instabile PAM-Modul Pam_mount [12] wurde bei dieser Gelegenheit durch eine neue, eigene Variante ersetzt: Pam_cifs [13].
Dieses Modul steht auch als Portage-Ebuild zur Verfügung. Es klinkt sich sowohl im Authentisierungs-Stack als auch im Session-Stack von PAM ein. Ein Daemon sorgt für ein zuverlässiges Abmontieren der CIFS-Shares, falls der betreffende Benutzer auf dem System nicht mehr aktiv ist.
In Kombination mit einem Windows-Fileserver verwendet das vorgestellte Beispiel Homeverzeichnisse via NFS und lässt »pam_cifs« den CIFS-Share nach »/var/cifs/User/cifs« montieren und im Homeverzeichnis einen Link von »cifs« auf »/var/cifs/User/cifs« anlegen.
In diesem Konzept findet jeder Nutzer seine zentrale Datenablage unter »/cifs« wieder. Unter Windows wird dies beispielsweise als Netzwerk-Laufwerk »U:« durch das Anmeldeskript verbunden. So sind auch Windowmanager zufrieden, die Sockets und Pipes im Homeverzeichnis des Benutzers anlegen möchten.
Pam_cifs gibt es ebenfalls als Portage-Ebuild, das wie oben unter »/usr/local/portage« zu platzieren ist. Anschließend muss der Admin noch die PAM-Konfiguration entsprechend Listing 8 anpassen und mit Hilfe von »rc-update add cifsumountd default« dafür sorgen, dass der Daemon »cifsumountd« beim Booten automatisch startet. Er ist zuständig für das Abmontieren nicht mehr benötigter CIFS-Shares.
|
Listing 8: |
|---|
01 auth required /lib/security/pam_env.so 02 auth required /lib/security/pam_cups.so debug # stored auth-token 03 auth sufficient /lib/security/pam_unix.so likeauth nullok # get auth-token, local users 04 # don't use pam_cifs 05 auth required /lib/security/pam_cifs.so debug # stored auth-token 06 auth sufficient /lib/security/pam_ldap.so use_first_pass debug 07 auth required /lib/security/pam_deny.so 08 09 account sufficient /lib/security/pam_ldap.so debug 10 account required /lib/security/pam_unix.so 11 12 password required /lib/security/pam_cracklib.so retry=3 13 password sufficient /lib/security/pam_ldap.so debug 14 password sufficient /lib/security/pam_unix.so nullok md5 shadow use_authtok 15 password required /lib/security/pam_deny.so 16 17 session required /lib/security/pam_limits.so 18 session required /lib/security/pam_mkhomedir.so umask=077 skel=/etc/skel 19 session sufficient /lib/security/pam_ldap.so debug 20 session required /lib/security/pam_unix.so 21 session optional /lib/security/pam_cups.so use_first_pass debug min_uid=1000 22 session optional /lib/security/pam_cifs.so use_first_pass debug min_uid=1100 make_mount_point linkname=cifs prefix=/var suffix=/cif |
Drucken in einer reinen Linux-Umgebung über Cups ist ebenfalls problemlos möglich – sowohl über die LDP/IPP-Protokolle als auch über das Smbspool-Backend auf Windows-Drucker. Verlangen die Windows-Drucker jedoch nach einer Authentifizierung, weil beispielsweise eine Druckkostenabrechnung durchgeführt wird, beginnt die Suche nach anderen Lösungen. Eine Möglichkeit besteht in einem Client-seitigen Password-Cache (siehe Pam-cups [12], [13]).
Diese nicht besonders elegante Lösung lässt sich zwar durch Umstellung des Gesamtkonzepts auf Kerberos umgehen. Doch steht eine Anpassung von »smbspool« für die Verwendung des Kerberos-Credential-Cache des druckenden Benutzers noch aus.
Virtuelle Clients
Natürlich kann man auch VMware-Workstation oder VMware-Player [15] in den Clientsystemen installieren. Liegen die virtuellen Festplatten-Images jedoch auf einem NFS-Server, kommt bei der Arbeit mit VMware keine Freude auf. Dann ist es besser, von dem strengen Konzept eines zustandslosen Clients abzuweichen und ein Caching der VMware-Images auf der lokalen Festplatte einzurichten. Dies lässt sich durch ein einfaches »rsync«-Skript bewerkstelligen – [10] stellt dazu ein Portage-Ebuild zur Verfügung.
Voraussetzung dafür ist, dass es auf der lokalen Platte eine Partition mit dem Label »DISKLESS« gibt. Achtung: Die Partition wird gegebenenfalls formatiert und »rsync« mit dem exportierten »/sync«-Verzeichnis des Servers angestoßen. Das Verzeichnis »/sync« des Servers wird zunächst nach »/remote« des Clients montiert. Das »rsync«-Skript synchronisiert »/sync/local« des Servers nach »/cache« des Clients. Auf dem Client ist »/remote/local« ein symbolischer Link auf »/cache« und »/remote/remote« wird mit einem Tmp-FS wieder zu einem Union-Mount zusammengefasst.
Damit besteht die Möglichkeit, die VMware-Clones unter »/remote/local« zu halten, während die zugehörigen Master unter »/remote/remote« zu finden sind (siehe Abbildung 3). Wenn außerdem das VMware-Gastsystem zustandslos sein soll, kennzeichnet der Admin die Festplatten in VMware als »independent«.

Abbildung 3: Mit Hilfe von Union-Mounts lassen sich auf dem Server sehr effektiv unterschiedliche, aber ähnliche Client-Dateisysteme abbilden.
Die hier vorgestellte Lösung eignet sich ebenfalls für getrennte Subnetze oder verteilte Standorte, die unterschiedliche Netzwerk-Konfigurationen erforderlich machen. In diesen Fällen differieren die Konfigurationen der Rich-Clients nur minimal.
Server-Varianten
Der TFTP- und NFS-Server benötigt Netzwerk-Interfaces in jedem Subnetz. Notwendige Änderungen bei den Clients betreffen die Bootloader-Konfiguration, gegebenenfalls die DNS-Serverangaben in »/etc/resolv.conf« oder die Lage der Homeverzeichnisse. Dann bietet es sich an, ein Dateisystem aus dem ursprünglichen Wurzeldateisystem »/tftproot/gentoo_A« der Clients und den Änderungen für ein weiteres Subnetz mit Hilfe von »unionfs« zu erzeugen.
Unter [10] liegt ein Patch, das ein Nachschlagen so genannter Whiteouts vermeidet, also jener Verzeichniseinträge, die versehentlich gleichnamige in tiefer liegenden Layern verdecken. Damit wird der Read-only-Zweig »/tftproot/gentoo _A« mit einem Read-Write-Zweig »/tftproot/gentoo_Bdiff« zu »/tftproot/gentoo_B« vereinigt (Abbildung 4):
mount -t unionfs -o dirs=/tftproot/gentoo_Bdiff=rw:/tftproot/gentoo_A=ro none /tftproot/gentoo_B

Abbildung 4: Um möglichst performant mit VMware arbeiten zu können, kopiert »rsync« die Clones der virtuellen Maschinen auf den Client.
Allerdings liefert das Union-FS keine Filesystem-ID. Die muss daher manuell über die Option »fsid« in »/etc/exports« eingetragen werden, wenn der NFS-Server das Subnetz B des Bereichs 192.168.48.0/24 beliefern soll: »/tftproot/gentoo_B 192.168.48.*(fsid=0x1234,ro,sync,no_root_squash)«.
Dann können in »/tftproot/gentoo_B« die erforderlichen Änderungen vorgenommen werden. Damit der Bootloader im Subnetz B auch die richtigen Parameter weitergibt, ist die Konfiguration anzupassen (Listing 9). Zudem muss auch der DHCP-Server den richtigen Pfad auf den Bootloader des Clients mitgeben. Für das Subnetz B des Bereichs 192.168.48.0/24 müsste ein passendes File »/etc/dhcp/dhcpd.conf« beispielsweise enthalten:
next-server 192.168.48.10; filename "gentoo_B/boot/pxelinux.0";
|
Listing 9: |
|---|
01 default L 02 timeout 100 03 prompt 1 04 display msg.txt 05 06 label L 07 LOCALBOOT 0 08 09 label l 10 LOCALBOOT 0 11 12 label R 13 kernel /gentoo_B/boot/EbzImage 14 append ip=dhcp root=/dev/nfs nfsroot=192.168.48.10:/tftproot/gentoo_B, hard,intr,ro udev init=/stateless.sh stateless=unionfs xauto=auto 15 16 label r 17 kernel /gentoo_B/boot/EbzImage 18 append ip=dhcp root=/dev/nfsnfsroot=192.168.48.10:/tftproot/gentoo_B,hard,intr,ro udev init=/stateless.sh stateless=unionfs xauto=auto |
Für die Clients ist dann noch die Datei »/tftproot/gentoo_B/etc/fstab« anzupassen: »192.168.48.10:/tftproot/gentoo_B / nfs defaults,ro 0 0«.
In einem Szenario mit mehreren Standorten und Bootservern ist es unter Umständen sinnvoller, die Wurzeldateisysteme über »rsync« zu replizieren. Der oben erzeugte Dateisystembaum unter »/tftproot/gentoo_B« dient als Quelle für eine Replikation auf einen anderen Server. Die Clients booten von diesem alternativen Server. Die Konfiguration befindet sich aber nach wie vor nur an einer einzigen zentralen Stelle.
Client-Varianten
Das in diesem Beitrag beschriebene Konzept lässt sich den unterschiedlichsten Anforderungen anpassen. Beispielsweise kann man die Konfiguration von KDE so ändern, dass der Benutzer standardmäßig auf einem entfernten Server angemeldet wird. Auf diese Weise ist mit demselben Konzept ein waschechter Thin-Client entstanden. Soll der Thin-Client außerdem noch bezüglich der Serverplattform neutral bleiben, ist es zum Beispiel möglich, NX-Client und -Server von Nomachine [14] einzusetzen oder auch auf RDesktop zurückzugreifen. Ebenso kann der Admin eine Bootoption für einen Kiosk-Modus mit Webbrowser anbieten.
Zum Abschluss sein noch erwähnt, dass sich die zustandslosen Rich- oder Thin-Clients jederzeit und bedenkenlos während des Betriebs ausschalten lassen. Das planmäßige Herunterfahren beschleunigt ein Powerdown-Skript in »/etc/conf.d/local.stop«. (jcb)
|
Die Autoren |
|---|
|
Dipl.-Inf. Jan Dworschak hat an der FH Kaiserslautern Angewandte Informatik studiert und arbeitet derzeit als Software-Entwickler. Markus Müller studiert an der FH Kaiserslautern Angewandte Informatik und beschäftigt sich seit fünf Jahren mit Linux und anderen freien Betriebssystemen. Prof. Dr.-Ing. Wilhelm Meier ist an der FH Kaiserslautern in Zweibrücken als Dozent im Fachbereich Informatik/Mikrosystemtechnik für das Lehrgebiet “Betriebssysteme” tätig. |






