Preboot eXecution Environment

Aus wiki.archlinux.de

Dieser Artikel wurde als veraltet markiert, und sollte kontrolliert, und gegebenfalls korrigiert bzw. aktualisiert werden.


Als Preeboot eXecution Environment (kurz "PXE") wird eine Technik bezeichnet, die es ermöglicht, über das Netzwerk, direkt nachdem das BIOS die Hardware initialisiert hat, beliebigen ausführbaren Code nebst Nutzdaten zu verteilen. Dies kann zum Beispiel genutzt werden, um:

  • Ein Notfallsystem auszuliefern
  • Ein Installationsmedium auszuliefern
  • Eine komplette Systemumgebung über das Netzwerk auszuliefern

Da Syslinux als Bootloader verwandt wird, ist es kein Problem, mehrere Möglichkeiten, auch mehrfach, zu kombinieren. Die Konfigurationen können Netzwerkweit, aber auch nur für bestimmte Clients konfiguriert werden. Dieser Artikel beschäftigt sich im Folgenden mit der Einrichtung eines Serversystems und der Erstellung von Clientsystemen unter ArchLinux.

Hinweis: Zur Zeit gibt es keine Möglichkeit, PXE via WLAN zu betreiben.

Funktionsweise

Wie ein Linux-System über das Netzwerk startet

Nachdem das BIOS die Hardware erfolgreich initialisiert hat, wird, sofern es aktiviert und als Bootziel eingestellt wurde, das PXE-Boot-Rom angesprungen und ausgeführt. Dieses initialisiert einen einfachen TCP/IP-Stack. Anschließend wird auf der zum Bootrom gehörenden Netzwerkkarte via DHCP nach einer IP-Adresse erfragt. DHCP muss allerdings nicht nur IP-Adressen ausliefern, sondern kann auch noch, mithilfe sogenannter Options, weitere Konfigurationseinstellungen vermitteln. Dazu gehören Hostname, Gateway-Adresse, DNS-Server, aber eben auch eine Option namens "Next Server". Eben dieser nächste Server ist der nächste Server, der in der Bootreihenfolge angesprungen wird - der TFTP-Server. TFTP ist ein stark vereinfachtes Datei-Übertragungs-Protokoll, welches jedoch keinerlei Sicherungsmechanismen besitzt. Auch wird vom DHCP-Server übermittelt, welche Binärdatei von dem TFTP-Server abgeholt und ausgeführt werden soll. In unserem Fall ist dies der im SysLinux-Paket enthaltene Bootloader pxelinux. Dieser holt sofort seine Konfigurationsdaten, ebenfalls via TFTP, und interpretiert diese. Angenommen, die Mac-Adresse des Systems lautet AA:BB:CC:DD:EE:FF, und die IP-Adresse 192.168.10.100, so wird er folgende Reihenfolge durchführen:

  • /pxelinux.cfg/aa-bb-cc-dd-ee-ff
  • /pxelinux.cfg/c0a80a64
  • /pxelinux.cfg/c0a80a
  • /pxelinux.cfg/c0a8
  • /pxelinux.cfg/c0
  • /pxelinux.cfg/default

Sobald eine dieser Dateien gefunden wurde, wird sie ausgelesen und Interpretiert. Sollte eine Datei nicht vorhanden sein, so wird die nächste probiert. Die Punkte 2-5 entsprechen dabei der hexadezimalen Darstellung der IP-Adresse, Punkt 1 dagegen stellt die MAC-Adrese dar. Nachdem schließlich die Wahl des zu bootenden Systems gefallen ist (so denn ein Prompt konfiguriert wurde), so wird auch dieses via TFTP nachgeladen. In unserem Falle werden dies eher der Linux-Kernel sowie das Init-Ram-Drive sein. Schließlich wird der Kernel gestartet, der die Module initialisiert, und das Rootdateisystem einhängt und schließlich init starten will. Damit dies geht, wird in den Kernelparametern angegeben, dass das Rootdateisystem via nfs, also dem SUN Netzwerkdateisystem, ausgeliefert wird. Also wird der Kernel die Netzwerkkarte reinitialisieren, eine Verbindung zum NFS-Server aufnehmen, das Rootdateisystem mounten, und den Bootvorgang fortsetzen. Nachdem auch dies gemeistert ist, wird das System "normal" gebootet (kleinere Modifikationen sind dennoch vonnöten) und steht ohne Einschränkungen zur Verfügung.

Einrichtung eines PXE-Serversystems

Voraussetzungen

Folgende Software wird benötigt:

Die jeweiligen Installationsanweisungen können den jeweiligen Artikeln entnommen werden. Gegebenenfalls bereits vorhandene DHCP-Server sind zu deaktivieren (Router, Server, NAS-Systeme, (teure) Switches, etc pp beinhalten solche zum Beispiel)

Konfiguration

  • Als erstes konfigurierst du den gewählten DHCP-Server so, dass die gewünschten Computer zum Boot aufgefordert werden.
  • Nun legst du die Verzeichnisstruktur an. Es empfiehlt sich, als Basis /srv/nfs anzulegen. Viele ziehen es vor, das Boot-System in /var/lib/tftpboot anzulegen, und unter /srv/nfs anschließend die Dateisysteme der Ziel-Rechner anzulegen, allerdings hat dies den Nachteil, das vom Clientsystem aus anschließend kein Kernelupdate durchgeführt werden kann. Der Vorteil ist eine erhöhte Sicherheit, da man via TFTP auf sämtliche Unterverzeichnisse Zugriff hat! Dies ist abzuwägen anhand der eigenen Paranoia. Sollten in einem Netz viele Fremde unterwegs sein, ist es im Interesse der Sicherheit anzuraten, nicht "/srv/nfs" auch für den Bootloader zu verwenden!
    • Unterhalb dieses Verzeichnisses legst du nun das Verzeichnis pxelinux.cfg an.
    • In dem Verzeichnis erstellst du die Datei default
  • Nun wird im NFS-Server der Stamm, in dem später die Root-Verzeichnisse der Zielsysteme liegen, freigeben (/srv/nfs z.B.). Wie das geht, erfährst du im Artikel Network File System
  • Der TFTP-Server muss wissen, in welchem Verzeichnis der Bootloader und die Konfiguration (pxelinux.cfg/default) zu finden sind. Konfiguriere ihn daher ebenfalls.
  • Nun kopierst du /usr/lib/syslinux/pxelinux.0 in das Zielverzeichnis (/srv/nfs im Beispiel)
  • Zu guter Letzt werden nur noch die Daemons gestartet → Fertig.

Konfiguration des Bootloaders

Der Bootloader pxelinux wird ähnlich konfiguriert, wie zum Beispiel "richtige" Bootloader wie GRUB oder eben syslinux. Hier sei zum Beispiel eine minimal funktionstüchtige Konfiguration aufgelistet:

default linux100

label linux100
kernel /pc100/boot/vmlinuz26
append initrd=/pc100/boot/kernel26.img rootfstype=nfs nfsroot=192.168.2.10:/srv/nfs/pc100/,v3,rsize=16384,wsize=16384 ip=dhcp quiet vga=773

Parameter "default"

Dieser spezifiziert das Standard-Label, das gebootet wird. Dieser Parameter sollte nur einmal in der Datei auftauchen.

Parameter "prompt"

Auf diesen folgt, nach einem Leerzeichen, "0" oder "1", und er bestimmt, ob eine Eingabe (z.B. zur Systemauswahl) ermöglicht wird, oder nicht. Dieser Parameter sollte nur einmal in der Datei auftauchen.

Parameter "display"

Hiermit kann eine Textdatei vor dem Prompt aufgelistet werden. Diese kann z.B. dem Benutzer aufzeigen, welche Optionen sich ihm anbieten. Sie sollte maximal 80x24 Zeichen "groß" sein. Dieser Parameter sollte nur einmal in der Datei auftauchen.

Parameter "f1" bis f10

Hiermit kann eine Textdatei aufgelistet werden, wenn die entsprechende Funktionstaste betätigt wird.. Diese kann z.B. dem Benutzer aufzeigen, welche Optionen sich ihm anbieten. Sie sollte maximal 80x24 Zeichen "groß" sein. Dieser Parameter sollte nur einmal in der Datei auftauchen.

Parameter "timeout"

Nach diesem folgt, ebenfalls nach einem Leerzeichen, eine Anzahl von Sekunden, nach wie vielen, sofern ein Prompt vorhanden ist, automatisch das default-label gebootet wird. Dieser Parameter sollte nur einmal in der Datei auftauchen.

Parameter "label"

Dieser Parameter erstellt ein neues Label. Nach einem Leerzeichen folgt der Name dieses Labels. Er sollte eindeutig sein. Nach der Labeldeklaration folgende Details werden automatisch mit ihm verknüpft, bis ein neues Label erstellt wird.

Parameter "kernel"

Dieser Parameter spezifiziert die Lage des Kernels, relativ zur Wurzel des TFTP-Servers. Er ist für ein Label Pflicht.

Parameter "append"

Dieser für Labels optionale Parameter gibt an, welche Parameter dem Kernel übergeben werden.

Einrichtung eines PXE-Clientsystems

Komplette Systemumgebung

Im folgenden wird beschrieben, wie in die vorhandene Serverinstallation ein komplettes Linux-System integriert wird. Befolge diese Schritte pro PC-System.

Voraussetzungen

Um die Anzahl der Schritte zu minimieren, wird archbootstrap-eeAUR zurückgegriffen. Dieses installiert selbstständig in ein Zielverzeichnis eine komplette ArchLinux-Installation. Alternativ kann man auch selbst mithilfe von pacman ein solches System installieren, was allerdings umständlicher ist. Folgende Schritte finden in einer Konsole statt!

  • Nachdem sichergestellt wurde, dass archbootstrap-ee installiert ist, wird man mithilfe von su zunächst zum Benutze root.
  • Anschließend ruft man
 archbootstrap-ee --target=/srv/nfs/pc100 --arch=i686 --mirror=ftp://ftp.hosteurope.de/mirror/ftp.archlinux.org/\$repo/os/i686

auf, wobei /srv/nfs/pc100 das Zielverzeichnis in diesem Beispiel ist, i686 die Plattform und der hintere Parameter den gewünschten ArchLinux Spiegelserver (Mirror) angibt.

  • Nachdem dieser Vorgang bestätigt wurde, und ArchLinux in das Verzeichnis installiert wurde, wechselt man mithilfe von chroot in dieses Verzeichnis.
  • Dort sollte man mithilfe von nano die Datei /etc/mkinitcpio.conf bearbeiten.
    • In dieser trägt man in der Zeile MODULES=() das Modul "nfs" ein, und in der Zeile HOOKS=() werden die Bereiche base, udev, net und filesystems ein, sodass die Zeilen wie folgt aussehen:
MODULES=(nfs)
HOOKS=(base udev net filesystems)
    • Auf Autodetect sollte (noch) verzichtet werden, solange das Zielsystem nicht die selbe Hardware wie der Server / der Rechner, auf dem das Image generiert wird hat.
    • Weitere Angaben nach Bedarf hinzufügen.
    • Mithilfe von mkinitcpio -g /boot/kernel26.img wird nun das Init-Ram-Drive neu erstellt
  • Wie bei einer regulären Installation ist nun mithilfe von nano die Datei /etc/rc.conf anzupassen.
  • Auch die Datei /etc/hosts will nicht vernachlässigt werden.
  • Hat man vor, pacman zu nutzen, so empfiehlt es sich in den meisten Fällen auch, in der Datei /etc/pacman.d/mirrorlist die gewünschten Spiegelserver (Mirrors) auszukommentieren.
  • Damit im Boot-Prozess nicht der Netzwerk-Stack neu initialisiert wird, dadurch die NFS-Verbindungen getrennt werden, und der Kernel sauber Suizid begeht, empfiehlt es sich, eine separate Netzwerk-Initialisierung einzubauen. Wir legen diese daher als /etc/rc.d/network-nfsroot an, und fügen folgenden Text ein:
#!/bin/bash
. /etc/rc.conf
. /etc/rc.d/functions

case "$1" in
        start)
                if ! ck_daemon network-nfsroot; then
                        echo "Network is already running.  Try 'network restart'"
                        exit
                fi

                stat_busy "Starting Network"

                if dhcpcd -p -s $(ifconfig eth0 | grep -o '[0-9]*\.[0-9\.]*' | head -n1) eth0; then
                        add_daemon network-nfsroot
                        stat_done
                else
                        stat_fail
                fi
                ;;
        stop)
                stat_busy "Stopping Network"

                if [ -f /var/run/dhcpcd-eth0.pid ]; then
                        /bin/kill $(cat /var/run/dhcpcd-eth0.pid)
                        rm_daemon network-nfsroot
                        stat_done
                else
                        stat_fail
                fi
                ;;
        restart)
                $0 stop
                /bin/sleep 2
                $0 start
                ;;
        *)
                echo "usage: $0 {start|stop|restart}"  
esac

# vim: set ts=2 noet:
    • Nicht zu vergessen sei, diese Datei auch ausführbar zu machen, und in der /etc/rc.conf den Daemon "network" durch "network-nfsroot" zu ersetzen.
  • Als eine der letzten Tätigkeiten sei in /etc/locale.gen die gewünschte Locale auszukommentieren, und locale-gen aufzurufen.
  • Final wird nun noch /etc/fstab bearbeitet. Die meisten Einträge dort sollten bereits richtig sein, es empfiehlt sich allerdings noch ein none / none am Ende hinzuzufügen. Es ist auch darauf zu achten, am Ende eine Leerzeile zu lassen, sonst meckert mount herum.
  • Nun wird das System noch wie oben angegeben in den Bootloader eingetragen - fertig, man kann sich nun am Zielsystem wie in einer frischen Installation anmelden. Es ist aber nicht zu vergessen, ein Root-Kennwort zu vergeben, und erst recht nicht zu vergessen, im BIOS auch zu aktivieren, den Netzwerkboot zuzulassen.