Im Rahmen meines Studiums bin ich mit MPI in Kontakt gekommen und musste bald feststellen, dass heterogene Umgebungen eine nicht-wirklich unterstuetzte Zielstellung sind. Am besten ist groesstmoegliche Homogenitaet, sprich, ein Cluster. Da diese aber nicht aus dem Nichts wachsen, muss man mit dem leben, was man hat. Und da waere es sehr praktisch, anstelle des installierten Windows ohne Live-CD-Brennereien oder USB-Stick-Misshandlungen "mal eben schnell" eine Kopie des Betriebssystems auf meinem Notebook booten zu koennen. Da bot sich PXE geradezu an. Ich selbst habe noch nie vorher mit PXE gearbeitet, mal davon abgesehen, dass man es bei Knoppix mit einem Mausklick aktivieren konnte -- aber das war vor 5 Jahren. Dennoch ist schliesslich festzustellen, dass es in 3 Schritten zu schaffen ist :) -- zumidest mit meinem aktuellen System. Noch ein Vorwort: In dieser Anleitung soll es nicht um das Installieren eines FBSDs aus dem Netzwerk gehen, sondern darum einen quasi-Klon des Servers zu booten.

Die Ausgangslage

Die Ausgangslage ist mein Notebook mit installiertem System, sowie den aktuellen Sourcen fuer Welt und Kernel. Man bekommt es hoechstwahrscheinlich auch mit Binaerpaketen hin, aber da ich den Quellcode kompiliert vorliegen hatte, bot es sich geradezu an, ihn zu benutzen...
Also, ab in die Details, das ist mein System:

[ad001@glas ~]$ uname -a
FreeBSD glas 8.0-BETA2 FreeBSD 8.0-BETA2 #2: Sun Jul 26 17:49:43 CEST 2009     root@salz:/usr/obj/usr/src/sys/GENERIC  i386
[ad001@glas ~]$ ifconfig em0
em0: flags=8843 metric 0 mtu 1500
        options=19b
        ether 00:16:41:e3:20:4b
        inet 192.158.0.191 netmask 0xffffff00 broadcast 192.158.0.255
        media: Ethernet autoselect (100baseTX )
        status: active
Die Boot-Informationen fuer die netzwerkgebooteten Maschinen sollen auf dem Serversystem unter /tftpboot liegen.
Daneben wird natuerlich noch eine andere Maschine benoetigt, die per PXE booten kann -- das duerfte heute so gut wie jede sein.
Im folgenden werde ich in der Reihenfolge vorgehen, wie das ueber Netzwerk gebootete System mit den einzelnen Komponenten interagiert. Und um Mut zu machen: Es sind nur drei essenzielle Schritte notwendig. Bei mir waren Sie begleitet von viel htttp://frag-onkel-google.de und RTFM und dem garstigstem von allem, dem Lesen irgendwelcher Mailinglisten. Ich verstehe einfach nicht, wieso es Menschen gibt, die Mailinglistdumps im Netz fuer eine tolle Informationsquelle halten... aber nun zur Sache.

Schritt 1: DHCP und Booten

Wenn der Rechner Strom bekommt, dann beginnt das BIOS, das Chaos im Speicher zu ordnen. Nachdem die ungefaehre Konfiguration (Bildschirm - vorhanden. Tastatur - USB, Legacy mode, Festplatten - keine) bekannt ist, werden die BIOS' der einzelnen Komponenten gefragt, ob sie noch etwas Beitragen wollen. Das kann dann die Enumeration der SCSI-Platten oder der SATA-Platten sein oder eben eine Netzwerkkarte, die ankuendigt, dass sie Booten kann. Wenn man sie fragt.
Schliesslich wird gebootet. Dabei wird in der im BIOS vorgegebenen Reihenfolge vorgegangen: Meist angefangen bei Festplatten, dann CD-Rom und schliesslich Netzwerk. Wenn der Rechner alt ist, noch Diskette. Wenn hier nun die Wahl auf Netzwerk faellt, wird das PXE-BIOS wieder aktiviert. Und hier gehts nun los:
Das PXE versucht, sich eine IP-Adresse per DHCP zu holen. Hierzu werden die ueblichen Broadcasts ausgesandt und die Antworten ausgewertet. Hier wird nun auf spezielle Antwortpakete gewartet: Solche, die Boot-Informationen enthalten. Anderweitige DHCP-Antworten werden ignoriert.
Daraus erwaechst die erste Aufgabe fuer das Serversystem: Geeignete DHCP-Antworten geben koennen. Ich habe hierzu den ISC-DHCPD in der Version 3.0 genutzt. Um diesen auf ein System zu bekommen tut es ein cd /usr/ports/net/isc-dhcp30-server/ && make install clean als Nutzer mit ausreichenden Rechten. Danach muss eine entsprechende Konfiguration geschaffen werden, die die erforderlichen Zusatzinformationen enthaelt. Das ganze laesst sich mit folgender dhcpd.conf, die normalerweise in /usr/local/etc/ residiert, erreichen.
Hinweis: Diese Konfiguration liefert ein Boot-Image an jeden Rechner aus. Entsprechend befindet sich hier ein gewisses Sicherheitsrisiko!

[ad001@glas /usr/home/ad001]$ cat /usr/local/etc/dhcpd.conf
ddns-update-style none;
subnet 192.168.0.0 netmask 255.255.255.0 {
  range 192.168.0.30 192.168.0.39;
  option subnet-mask 255.255.0.0;
  option broadcast-address 192.168.0.255;
#  option routers 192.168.0.1;
#  option domain-name-servers 192.168.0.2;
  option domain-name "pxec";
  default-lease-time 3600;
  max-lease-time 3600;
  server-name "192.168.0.191";
  server-identifier 192.168.0.191;
  next-server 192.168.0.191;
  option root-path "192.168.0.191:/tftpboot/clientroot";
  filename "/pxeboot";
}
Eine kurze Erklaerung, was da nun was tut:
Nun kann der DHCPd gestartet werden und wartet auf Anfragen...
[ad001@glas /usr/home/ad001]$ sudo /usr/local/etc/rc.d/isc-dhcpd onestart
Starting dhcpd.
Internet Systems Consortium DHCP Server V3.0.7
Copyright 2004-2008 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/
Wrote 1 leases to leases file.
Listening on BPF/em0/00:16:41:e3:20:4b/192.168.0/24
Sending on   BPF/em0/00:16:41:e3:20:4b/192.168.0/24
Sending on   Socket/fallback/fallback-net
Wird nun versucht, per PXE zu booten, sollte der Client ein DHCP-Paket mit Zusatzinfos bekommen und versuchen, die Datei pxeboot zu laden -- was im Moment noch scheitern sollte, da weder ein TFTPd laeuft noch er die richtige Datei ausliefern kann.

Schritt 2: TFTP und Bootloader

TFTP ist ein selten zum Dateitransfer eingesetztes Protokoll. Dies hat einige einfache Ursachen: Es besitzt keine Sicherheitsmechanismen, baut auf UDP auf (was weitere Schwaechen wie z.B. eine Anfaelligkeit gegen Injections impliziert) und ist, wie der Name "Trivial File Transfer Protocol" schon ankuendigt, eine abgespeckte Variante von FTP.
Um die Sache einfach zu halten, werde ich den von FreeBSD im Grundsystem mitgebrachten tftpd nutzen. Hierzu muss er nur in der /etc/inetd.conf aktiviert und der inetd gestartet werden.

#
# ntalk is required for the 'talk' utility to work correctly
#ntalk  dgram   udp     wait    tty:tty /usr/libexec/ntalkd     ntalkd
tftp    dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot
#tftp   dgram   udp6    wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot
#bootps dgram   udp     wait    root    /usr/libexec/bootpd     bootpd
#

So sieht das bei mir aus. Ich habe die Beispielzeile auskommentiert und dafuer gesorgt, dass das hintenstehende Verzeichnis (hier eben /tftpboot) auch existiert. Sodann kann der inetd mit einem kurzen
[ad001@glas /usr/home/ad001]$ sudo /etc/rc.d/inetd onestart
Starting inetd.
aktiviert werden. Nun muss als naechstes dafuer gesorgt werden, dass auch ein Bootimage, welches PXE beherrscht vorliegt -- so wie es ja in der DHCP-Antwort dem client versprochen wurde. Wenn man (wie ich) regelmaessig seinen Kernel selbst kompiliert und installiert, dann findet sich ein geeignetes Image in /boot. Dieses muss dann nur noch nach /tftpboot kopiert werden.
Bootet man nun den Client, so sollte sich der FreeBSD-Bootloader sehen lassen. Und feststellen, dass er nicht an den Kernel herankommen kann. Es wird Zeit fuer NFS, denn mit dem Eintrag option root-path "192.168.0.191:/tftpboot/clientroot" wird dem Bootloader angekuendigt, dass es auf diesem Wege weitere Daten gibt.

Schritt 3: NFS, Kernel und Userland

Als erstes einmal muss das Verzeichnis /tftpboot/clientroot erzeugt und freigegeben werden. Hierzu ist ein Eintrag in der Datei /etc/exports mit beispielsweise dem folgenden Inhalt notwendig:

/tftpboot/clientroot	-alldirs -maproot=0 -network 192.168.0.0 -mask 255.255.0.0
hiermit wird der entsprechende Pfad mit allen Unterverzeichnissen fuer das angegebene Netzwerk freigegeben und root-Zugriffe auf die UID 0 gemappt (was wiederum Root ist). Anschliessend muss der NFS-Daemon noch zum Laufen gebracht werden:
[ad001@glas ~]$ sudo /etc/rc.d/nfsd onestart
Starting mountd.
Starting nfsd.
[ad001@glas ~]$ sudo /etc/rc.d/rpcbind onestart
Starting rpcbind.

Nun sollte NFS funktionieren. Testen kann man das, wenn eine zweite unixoide Maschine vorhanden ist einfach, indem man versucht, das freigegebene Verzeichnis zu mounten. Hierzu reicht ein mount 192.168.0.191:/tftpboot/clientroot /mnt aus.
Nun muss noch Inhalt fuer die Remote-Maschine hinterlegt werden. Im einfachsten Fall kopiert man /boot einfach in das Verzeichnis, also nach /tftpboot/clientroot/boot. Damit liegt schonmal ein Kernel vor. Jetzt sollte eine per PXE bootende Maschine bereits den Kernel (mit FreeBSD-Bootscreen) laden koennen. Der Spass wird damit enden, dass der Kernel eine Panic mit der Meldung
panic: going nowhere without my init.
von sich gibt. Was der Kernel uns damit sagen moechte? Schlicht und ergreifend, dass der Sprung ins Userland furios gescheitert ist. Dies ist allerdings im Moment auch nicht verwunderlich, denn so etwas wie ein Userland findet sich noch nicht im NFS-Share. Das kann man aber auf drei Wegen aendern: Durch haendisches kopieren des Userlandes von / in das Zielverzeichnis (nicht sehr komfortabel), durch eine Installation aus Binaerpaketen (z.B. von einer FreeBSD-CD), dort waere dann das Paket base relevant, oder aber direkt aus dem kompilierten Quellcode. Das geht dann ebenfalls recht einfach, es reicht ein
[ad001@glas /usr/src]$ sudo make DESTDIR=/tftpboot/clientroot/ installworld
mkdir -p /tmp/install.AhUs44jS
progs=$(for prog in [ awk cap_mkdb cat chf...
...der Prozess dauert ein wenig laenger. Bei einer Installation von Binaerpaketen muss die Umgebungsvariable DESTDIR ebenfalls gesetzt sein -- ansnsten ersetzt man Teile des gerade laufenden Systems (was nur dann ein Problem ist, wenn es eine andere Version ist -- dann aber ein grosses) durch moeglicherweise inkompatible Versionen (schlimmer noch: Dateien mit sinnvollem Inhalt durch leere). Nun liegt auch eine Welt vor. Wenn nun PXE-gebootet wird, dann wird es dennoch eine Fehlermeldung nach der anderen geben: Der Kernel mountet / schreibgeschuetzt, entsprechend wird alles zu Fehlern fuehren. Dies beginnt beim schreiben des DHCP-Leases, setzt sich mit dem DNS-Eintrag fort und... naja, es ist recht unkomfortabel, nicht mal eine temporaere Datei schreiben zu koennen. Also muss eine /etc/fstab eingerichtet werden, die entsprechend auch schreibbare Systeme enthaelt. Zum Beispiel kann / problemlos auch schreibbar sein -- dafuer haben wir es ja nach /tftpboot/clientroot gemountet und nicht nach / auf dem Serversystem. Was man allerdings problemlos tun kann, ist Teile des Originalsystems ueber das Grundsystem zu mounten. So sieht meine /etc/fstab dann schliesslich aus:
[ad001@glas /tftpboot/clientroot]$ cat etc/fstab
# Device               			Mountpoint	FStype		Options		Dump	Pass#
192.168.0.191:/tftpboot/clientroot      /               nfs             rw              0       0
192.168.0.191:/libexec                  /libexec        nfs             ro              0       0
192.168.0.191:/lib                      /lib            nfs             ro              0       0
192.168.0.191:/usr                      /usr            nfs             ro              0       0
192.168.0.191:/home                     /home           nfs             rw              0       0
Natuerlich muss die /etc/exports die analogen Eintraege besitzen (oder einfach eine Freigabe von / -- aber das ist auch nicht unbedingt sicher). Nichtsdestoweniger, nun sollte alles im wesentlichen Funktionieren. Und dank des mountens von /usr/ stehen auch mit /usr/local/bin saemtliche installierte Programme zur Verfuegung.
Was noch fehlt, sind natuerlich die Nutzerlogins. Wenn man das ganze jetzt vorbildlich loesen wollen wuerde (der geneigte Leser erahnt, in welche Richtung es geht...), koennte man Login per LDAP, NIS oder NIS+ aufsetzen. Man kann aber auch einfach die entsprechenden Dateien aus /etc *raeusper* rueberkopieren.... um ganz ehrlich zu sein, ich habe einfach /etc nach /tftpboot/clientroot/etc kopiert und dann dort die abweichenden Anpassungen vorgenommen.
Zu diesem Zeitpunkt soll schliesslich ein funktionierendes, durch das Netzwerk gebootetes FreeBSD zur Verfuegung stehen.

Weiteres


Ein paar Fragen bleiben natuerlich offen...

Resourcen

Hier nun eine laengere Liste von Quellen, die ich abgegrast habe,

Sollte ich noch etwas vergessen haben, dann keine Hemmungen und mir eine Mail an ad001@uni-rostock.de* schicken.
* Keine unerwuenschte Werbung, kein Spam, kein... naja, die Nachricht duerfte klar sein.

Stichworte:


Impressum