Workshop: Diskless Linux mit PXE

29.03.2004 von MAX PRATZ 
Über Intels Preboot Excution Environment PXE lassen sich Arbeitsplatzrechner als festplattenlose Clients betreiben, die ihr Betriebssystem aus zentraler Quelle beziehen. Unser Workshop zeigt, wie PXE mit Linux funktioniert.

Mit dem Pre-boot Execution Environment PXE stellt Intel im Rahmen seiner Wired-for-Management-Architektur eine standardisierte und auf vielen Boards und Netzwerk-Adaptern implementierte Methode zum Remote Boot von Systemen bereit. Dabei umfasst PXE einen definierten Satz von Firmware-Routinen, über dessen APIs mit Hilfe eines Protokolls zur Adresszuweisung und der Lokalisierung von Netzwerkressourcen das BIOS ein so genanntes Network Bootstrap Program (NBP) bei einem Server anfordern und über dieses weitere Software nachladen kann.

Diese Methode lässt neben einer automatischen Installation des Betriebssystems auch die komplette Anforderung eines vorkonfektionierten, lauffähigen OS-Images beim Server zu. Damit eröffnet PXE die Möglichkeit, Arbeitsplatzrechner nicht als "fette" PCs mit Harddisk-basierter Betriebssysteminstallation zu betreiben, sondern als festplattenlose Clients, die ihr OS aus zentraler Quelle beziehen. Die Vorteile einer solchen Lösung vor allem hinsichtlich Administration, Maintenance und Support liegen auf der Hand.

Angenehmer Nebeneffekt: Der Diskless Client sorgt nebenbei für angenehme Ruhe am Arbeitsplatz. Und so ist die Idee zum Diskless Linux via PXE ursprünglich auch entstanden. Bei Experimenten mit einem heimischen Video-Streaming-Client erwiesen sich die angepeilten Lösungen zwar als technisch zufrieden stellend, jedoch in Sachen Lautstärke als eindeutig nicht "Wohnzimmer-kompatibel". Da liegt der Versuch mit einem plattenlosen Gerät, das über PXE bootet, nahe. Wie sich bei entsprechenden Versuchen zeigte, lässt sich das Prinzip jedoch relativ problemlos auch für Client-Installationen in Firmen-Umgebungen umsetzen.

Die dabei gemachten Erfahrungen sowie die wichtigsten Rahmenbedingungen und Arbeiten zur Implementierung von Diskless Clients unter Linux fasst der vorliegende Artikel zusammen. Anhand dieser Informationen sollten Sie relativ problemlos in der Lage sein, eine entsprechende Lösung für eigene Zwecke aufzusetzen. Alle im Folgenden beschriebenen Scripts sowie ein fertiges Boot-Image stehen auch zum Download bereit. Es handelt sich dabei ausnahmslos um freie Software gemäß der GPL, so dass eigenen Modifikationen und Experimenten nichts im Wege steht.

Vorbedingungen

Für die ersten Versuche benötigen Sie zunächst einmal einen Diskless Client mit Remote-Boot-Fähigkeit. Die meisten On-board-Netzwerk-Controller bringen auch gleich einen passenden PXE-Client im BIOS mit. Höherwertige Netzwerkadapter kommen in der Regel ebenfalls schon mit einem eigenen PXE-BIOS. Unter Umständen müssen sie dieses aber erst einmal aktivieren. Auf den vom Autor verwendeten Karten des Typs Intel EEPro/100+ wurde dazu beispielsweise das Intel-Tool IBAUtil eingesetzt.

Des Weiteren benötigen Sie eine CD der Linux-Distribution, die auf dem plattenlosen System laufen soll. Für den vorliegenden Artikel wurde zu diesem Zweck ein Fedora Core 1 verwendet. Auf Server-Seite müssen ein DHCP- und ein TFTP-Server sowie ein NFS-Server parat stehen. Dazu lassen sich die mit den allermeisten Distributionen ausgelieferten Varianten einsetzen. Es spricht auch nichts dagegen, die drei Server-Dienste zusammen auf einer Maschine zu betreiben.

Installieren der Distribution

Eine betriebsfertige Distribution lagert normalerweise auf der Festplatte des Rechners. Nun soll ja im Client keine Festplatte verwendet werden, sondern er muss das Betriebssystem via NFS vom Server beziehen. Dies erfordert, die Distribution statt auf der nicht vorhandenen lokalen Platte in einem Verzeichnisbaum auf dem Server zu lagern. Sie lässt sich auf zwei Wegen dorthin befördern.

Zum einen können Sie die Distribution ganz normal auf der lokalen Festplatte eines Rechners installieren. Von dort kopieren Sie dann alle Dateien in ein Verzeichnis auf dem Server. Alternativ ist es möglich, die Software direkt auf dem Server zu installieren. Diese Aufgabe lässt sich bequem über ein kleines Script erledigen, das die benötigten Binaries von der CD-ROM in das Zielverzeichnis befördert und noch einige notwendige Dateien erzeugt.

Die für das vorliegende Beispiel verwendete Variante finden Sie als mkfedora.sh zum Download. Nach dem Aufruf über ./mkfedora.sh [ZIEL] [DIST-CD] installiert es die im Script selbst angegebene Minimal-Paketausstattung von der Distributions-CD in das als ZIEL angegebene Verzeichnis auf dem Server. Daneben legt es im Ziel-Verzeichnisbaum noch /etc/fstab sowie /etc/sysconfig/authconfig an und generiert gleich einen SSH-Hostkey.

Anpassungen für das Remote-Booten

Im nächsten Schritt gilt es, die Distribution für das Booten aus einer entfernten Quelle zu präparieren. Dies erfordert eine Reihe von Anpassungen im Verzeichnisbaum auf dem Server (im Folgenden als SYSROOT bezeichnet). Bei unserem Fedora fallen folgende Arbeiten an:

Diese Arbeiten lassen sich zwar grundsätzlich von Hand ausführen. Komfortabler erledigt sie aber das Script mkbootready. Aufgerufen wird es mit ./mkbootready [SYSROOT], wobei Sie für SYSROOT das Basisverzeichnis der auf dem Server lagernden Installation angeben.

NFS konfigurieren

Nun richten Sie NFS für den Zugriff der plattenlosen Clients ein, die ihr Betriebssystem aus dem in den vorigen Schritten erzeugten Distributionsverzeichnis aus dem Server beziehen sollen. Dazu müssen Sie das Verzeichnis exportieren. Für ein Distributionsverzeichnis namens /netboot/pxeclient fügen Sie beispielsweise folgende Zeile in die /etc/exports des NFS-Servers ein:

/netboot/pxeclient 192.168.1.0/24(ro,no_root_squash)

Da für das Booten der Diskless Clients die Option no_root_squash benötigt wird, sollten Sie aus Sicherheitsgründen keinesfalls ein Einhängen im Lese/Schreib-Modus erlauben. Andernfalls würden die root-Benutzer der Clients auch root-Zugriff auf dem Server erhalten. Stellen Sie sicher, dass Ihr NFS-Server läuft. Vergessen Sie außerdem nicht, nach dem Eintragen des Exports die Konfiguration neu zu laden. Haben Sie damit Probleme, hilft ein Blick in das NFS-HOW-TO weiter. Sie finden es beim Linux Documentation Project.

Vorbereiten des initrd-Image

Die Erstellung des Boot-Image selbst erfordert einigen Arbeitsaufwand. So muss beispielsweise busybox kompiliert werden, das alle wichtigen Systembefehle kompakt in einem Programm bereitstellt. Für lspci wird ein Patch von Diego Torres Milano benötigt, der über die Option -k den Netzwerkadapter automatisch erkennt und gleich den passenden Modulnamen ausspuckt. Auch sind eine ganze Reihe Initialisierungs-Scripts zu erstellen beziehungsweise anzupassen.

Diese Arbeiten müssen Sie jedoch nicht alle selbst erledigen: Sie finden ein funktionsfähiges initrd-Image auch in gepackter Form zum Download. Anfassen müssen Sie es nur noch dann, wenn Ihr Kernel nicht alle notwendigen Funktionen fest einkompiliert mitbringt, sondern einige Funktionen in Module ausgelagert hat. In diesem Fall ist das Image entsprechend anzupassen. Das ist auch bei dem als Exempel verwendeten Fedora der Fall, bei dem vor allem NFS lediglich als Modul vorhanden ist.

Zunächst entpacken Sie das Boot-Image und hängen es ein:

gunzip pxeboot.img.gz
mkdir __pxeboot-tmp__
mount -o loop pxeboot.img __pxeboot-tmp__

Anschließend legen Sie Verzeichnisse für die nötigen Module an. Dabei geben Sie für ${KERNELVER} die genaue Version des verwendeten Kernel an. Bei dem Fedora Core 1 wäre das beispielsweise 2.4.22-1.2115.nptl.

mkdir -p __pxeboot-tmp__/lib/modules/${KERNELVER}/net
mkdir -p __pxeboot-tmp__/lib/modules/${KERNELVER}/nfs

Nun kopieren Sie nfs.o und die von ihm benötigten Dateien (in der Regel sunrpc.o und lockd.o) in das eben angelegte Unterverzeichnis .../nfs. Sinngemäß verfahren Sie mit den erforderlichen Netzwerktreiber-Modulen und deren Dependencies (meist ist das mii.o), die in das Verzeichnis .../net gehören. Falls Sie für verschiedene Clients unterschiedliche Netzwerktreiber brauchen, können Sie sie hier alle ablegen. Der Lader pickt sich später das Passende heraus.

Jetzt berechnen Sie die Dependencies neu. Hier geben Sie für $SYSTEMMAP die System.map-Datei des verwendeten Kernel an, für $KERNELVER wiederum die genaue Kernel-Version:

/sbin/depmod -a -F $SYSTEMMAP -b __pxeboot-tmp__ -C /dev/null $KERNELVER

Zu guter Letzt hängen Sie das Image wieder aus und komprimieren es erneut:

umount __pxeboot-tmp__
gzip -9 pxeboot.img
rmdir __pxeboot-tmp__

Image per Script

Sie ahnen es wahrscheinlich schon: Auch für die Arbeiten zum Erstellen des initrd-Images gibt es bereits ein vorbereitetes Script, das Sie als mkbootimage.sh herunterladen können. Aufgerufen wird es mit:

./mkbootimage.sh [SYSROOT] [SYSTEMMAP] [KERNELVER]

Dabei übergeben Sie als SYSROOT das Wurzelverzeichnis des Systems, dessen Kernel-Module Sie verwenden wollen. Dabei handelt es sich üblicherweise um das Verzeichnis auf dem Server, in das Sie die Distribution installiert haben - in unserem Fedora-Beispiel also /netboot/pxeclient. Dort muss unter [SYSROOT]/lib/modules/[KERNELVER] eine gültige modules.dep zu finden sein.

Bei KERNELVER handelt es sich, wie bereits erwähnt, um die genaue Version des verwendeten Kernel (für Fedora Core 1 also 2.4.22-1.2115.nptl). Als SYSTEMMAP ist, wie ebenfalls schon angesprochen, die System.map-Datei desselben Kernel anzugeben. Das wäre also üblicherweise so etwas wie /netboot/pxeclient/boot/System.map-[KERNELVER].

DHCP-Einstellungen anpassen

Wahrscheinlich betreiben Sie bereits einen DHCP-Server. Falls nicht, ist es jetzt höchste Zeit, einen solchen einzurichten. Auch dazu finden Sie gegebenenfalls ein passendes HOW-TO beim Linux Documentation Project. Für den Diskless Client fügen Sie eine Sektion wie die folgende in /etc/dhcpd.conf ein:

host pxeclient {
hardware ethernet AA:BB:CC:DD:EE:FF;
fixed-address 192.168.111.222;
option host-name "pxeclient";

filename "/pxelinux.0";
next-server tftpserver;
option root-path "nfsserver:/netboot/pxeclient";
}

Als "filename" ist hier der Name des PXE-Boot-Image auf dem TFTP-Server anzugeben, in unserem Fall immer "/pxelinux.0". Unter "next-server" tragen Sie den Host-Namen beziehungsweise die IP-Adresse des TFTP-Servers ein. Mit "root-path" ist der NFS-Pfad zum Wurzelverzeichnis für den Client gemeint.

Falls NFS- und TFTP-Server auf derselben Maschine laufen, ist die explizite Angabe des Server-Namens überflüssig. Bei Bedarf können Sie auch NFS-Optionen anhängen:

nfsserver:/netboot/pxeclient/,retry=1,rsize=8192,wsize=8192

Näheres dazu finden Sie in der Manpage zu mount(8). Vergessen Sie im Anschluss an die Änderungen nicht, den DHCP-Daemon neu zu starten, damit die Optionen auch übernommen werden.

TFTP konfigurieren

Installieren Sie, falls nicht schon geschehen, das Paket tftp-server. Falls die von Ihnen verwendete Distribution den xinetd nutzt, müssen Sie meist nur in /etc/xinetd/tftp die Option disable=no setzen und xinetd neu starten. Alternativ können Sie auch tftpd manuell mit Angabe der Option -s /tftpboot starten. Die herunterladbaren Dateien sind üblicherweise im Verzeichnis /tftpboot zu lagern.

Sobald Sie den TFTP-Server am Laufen haben, besorgen Sie sich bei Kernel.org die aktuellste Version von syslinux. Darin findet sich eine Datei namens pxelinux.0, die Sie in das Verzeichnis /tftpboot des Servers kopieren. Nun wechseln Sie in dieses Verzeichnis und legen ein Subdirectory namens pxelinux.cfg an. In dieses legen Sie wiederum eine Datei "default" ab, die folgenden Inhalt haben sollte:

LABEL linux
KERNEL vmlinuz-2.4.22-1.2115.nptl
APPEND initrd=pxeboot.img.gz ramdisk_size=8192

Der Name des Kernel-Image kann bei Ihnen abweichen, das Beispiel gilt für das verwendete Fedora. Zum Abschluss kopieren Sie jetzt noch den Kernel und das initrd-Image aus den vorigen Schritten in das Verzeichnis /tftboot.

Booten

Damit sind alle Vorbereitungen abgeschlossen. Sie können jetzt Ihren Diskless Client einschalten, sich gemütlich zurücklehnen und ihm beim Booten zuschauen. Vergessen Sie jedoch nicht, dass Sie lediglich ein Read-only-Image haben. Der Client kann also nur nach /var und /tmp schreiben, aber praktisch in kein anderes Verzeichnis.

Der einfachste Weg, etwas zu ändern, ist dies in einer chroot auf dem NFS-Server zu tun. Führen Sie also zum Beispiel chroot /netboot/pxeclient aus, um eine Shell über chroot zu starten. Nehmen Sie hier uname(1) zu Hilfe, falls Sie auf Server und Client mit verschiedenen Kernel oder Prozessoren arbeiten.

Mit etwas Nacharbeit lässt sich der Bootvorgang übrigens in vielen Fällen noch beschleunigen. Zum einen sollten Sie sich unbedingt einen angepassten Kernel maßschneidern. Entfernen Sie alles, was Sie nicht wirklich benötigen.

Der IDE-Support beispielsweise vertrödelt eine erkleckliche Zeitspanne, nur um herauszufinden, dass gar keine Platten angeschlossen sind. Was Sie wirklich brauchen, lässt sich quasi an fünf Fingern abzählen: Support für Netzwerkkarte, initrd-Image, NFS, ext2 und tmpfs.

Feilen Sie auch kräftig an der /etc/rc.d/rc.sysinit. Hier finden sich viele für ein Read-only-Image völlig überflüssige Aufrufe, wie etwa von fsck oder depmod. Werfen Sie auch hier alles heraus, was Sie nicht wirklich brauchen.

Einschränkungen

Zwar booten die Systeme nicht so schnell wie von Festplatte, aber doch so zügig, dass man sich das sprichwörtliche Kaffeekochen nach dem Einschalten sparen kann. Einige kleinere Einschränkungen der vorgestellten Lösung sollen aber nicht verschwiegen werden.

So funktioniert etwa der Shutdown der Systeme nicht sauber. Das liegt daran, dass der Client versucht, sein NFS-Root noch auszuhängen. Dem Autor ist bis jetzt keine distributionsunabhängige Methode eingefallen, um das zu umgehen. Falls Sie es versuchen wollen: Stellen Sie sicher, dass das Aushängen des NFS-Root unterbleibt und auch der Portmapper (so er denn läuft) nicht terminiert wird. Lösungsvorschläge können Sie gerne an gve@intra2net.com senden.

Vielleicht ist Ihnen aufgefallen, dass trotz Verwendung eines DHCP-Servers der Client mit einer festen IP-Adresse konfiguriert wird. Das liegt daran, dass kein DHCP-Client läuft, der ein Lease erneuern könnte. Die vorgeschlagene Lösung verwendet den Daemon aus der initrd nicht weiter, weil das Image sonst gemountet bleiben müsste und somit 8 MByte Hauptspeicher quasi verschwendet wären. Einen neuen dhclient aus dem Distributionsfundus zu starten, ist zwar prinzipiell möglich. Allerdings müssen Sie dazu in den meisten Fällen das dhclient-script anpassen, damit es nicht etwa das Netzwerk-Device abschaltet oder während der Discovery-Phase die IP-Adresse ändert.

Ausblick

Noch ein Tipp zum Schluss: Spendieren Sie Ihren Diskless Clients genügend Hauptspeicher - 512 MByte RAM oder auch etwas mehr dürfen es ruhig sein. Da die Systeme keinen Swapspace zur Verfügung haben, legen sie bei zu geringer Speicherausstattung ansonsten gelegentlich mal eine kleinere Verschnaufpause ein, um den Speicher neu zu organisieren.

Vielen Unternehmen setzen auf SuSE Linux als Standard-Distribution. Dort ergeben sich bei der Umsetzung der vorgestellten Lösung einige kleine Änderungen . So bringt beispielsweise der SuSE-Kernel NFS bereits einkompiliert mit, andererseits benötigt er für DHCP das af_packet-Modul. Insgesamt fallen etliche Änderungen im mkbootimage-Script an. Auch die Datei linuxrc - Sie finden diese in pxeboot.img.gz - ist entsprechend anzupassen.

Falls auch Sie mit SuSE Linux arbeiten, schauen Sie sich doch gelegentlich einmal das (allerdings englischsprachige) Diskless Linux with PXE HOW-TO auf der Intra2net-Website. Dort werden die für SuSE Linux notwendigen Änderungen bei nächster Gelegenheit eingearbeitet. (jlu)

Zum Autor: Gerd von Egidy leitet als Entwicklungschef bei der Tübinger Intra2net AG die Entwicklung des preisgekrönten Kommunikations-Servers Intranator. Daneben zeichnet er auch für die Support-Koordination und die Qualitätskontrolle des süddeutschen Appliance- und Software-Herstellers verantwortlich. Last not least studiert er noch Betriebswirtschaftslehre mit Schwerpunkt Wirtschaftsinformatik.