"Wie installiere ich alle meine Rechner neu?" Diese oder ähnliche Fragen stellt sich jeder Administrator mal. Während bei kleinen Rechnerparks noch der Turnschuhadmin von Rechner zu Rechner rennt, ist ab einer gewissen Anzahl eine automatische Installation angebracht.
Je nach Betriebssystem gibt es diverse Namen für eigentlich immer ähnliche Techniken. Sei es nun
FAI (Fully Automated Installation) oder
WDS (Windows Deployment Services). Natürlich gibt es auch reine Image-Software wie z.B.
Norton Ghost.
Alle Installationsarten haben eine Gemeinsamkeit: der Rechner kann vom Netzwerk booten und bekommt danach über das Netzwerk die Installationsdateien. Dieser Netzwerkboot per PXE hat den angenehmen Vorteil: man muss nicht von Rechner zu Rechner wandern sondern quasi auf Knopfdruck ein Image ausrollen. Sollte beispielsweise der Rechner gerade aus sein, kann man per Wake On Lan diesen booten.
Ob nun ein echtes Image oder die Installationsdateien verwendet werden - beides hat einen entscheidenen Nachteil: das Netzwerk wird belastet. Aus schlechten Erfahrungen in der Vergangenheit werden heutzutage nicht mehr alle Rechner in ein Netzwerk gesetzt sondern per Firewall sauber getrennt. Was Würmer an der Verbreitung hindert, hat aber Nachteile: oft ist die Firewall-Appliance nicht stark genug ausgelegt um eine gleichzeitige Installation dutzender von Rechnern zu verkraften.
Im folgenden möchte ich eine kleine Lösung für dieses Problem vorstellen. Die grundsätzliche Idee ist einfach: das Aufrüsten der Firewall ist zu kostspielig. Ein einfacher Linuxserver mit zwei Netzwerkkarten ist schnell genug, aber wir wollen und können damit nicht die Appliance mit den ganzen Funktionen ersetzen.
Also stellen wir neben die Firewall eine zweite die nur während des Deployment-Prozesses tätig ist.
Die eigentliche Aufgabe besteht nun darin eine Fallunterscheidung zu treffen. Während beim normalen Boot alles wie gewohnt ablaufen soll, muss beim Booten über's Netzwerk alles über den neuen Linux-Server laufen. Das ganze klappt wunderbar wenn ein paar Rahmenbedingungen erfüllt sind - am wichtigsten ist hierbei die Verwendung eines passenden DHCP-Servers.
Zuerst einmal brauchen wir ein neues IP-Segment für die Image-Verteilung. Da öffentliche Adressen Mangelware sind, begnügen wir hier uns mit einem privatem Segment. Da wie schon gesagt, mehrere Netzbereiche versorgt werden sollen, nehmen wir hier ein 10er Bereich und unterteilen ein /16 in 255 Segmente.
CODE:
shared-network "SharedSubnet_10.0.47.0" {
failover peer "failover";
allow unknown-clients;
allow bootp;
allow booting;
next-server 10.0.47.254;
filename "pxelinux.0";
option routers 10.0.47.254;
option subnet-mask 255.255.255.0;
subnet 10.69.47.0 netmask 255.255.255.0 {
pool {
range 10.69.47.1 10.69.47.99;
allow members of "PXE";
}
}
}
Durch die Allow-Zeile wird dieser DHCP-Pool nur verwendet wenn tatsächlich über das Netzwerk gebooted wird. Das Erkennen eines Netzwerkboots erfolgt über die Angabe des Herstellers im DHCP-Request. Neben dem "pxe-kernel" welches über den nicht dokumentierten Kernelparameter dhcpclass gesetzt wurde, forderte der Kernel trotzdem auch noch als "Linux ipconfig" eine IP an.
CODE:
class "PXE" {
match if substring(option vendor-class-identifier, 0, 9) = "PXEClient" or
option vendor-class-identifier = "pxe-kernel" or
option vendor-class-identifier = "Linux ipconfig";
ping-check false;
}
Der ping-check erwies sich als nötig, da der Linux-Kernel eine IP-Adresse anfragt und gleichzeitig die alte noch in Benutzung ist. Der DHCP-Server pingt also die alte Adresse an und stellt fest, dass er sie nicht vergeben kann, da sie scheinbar noch in Verwendung ist. Was also normalerweise das Netzwerk vor der doppelten Vergabe einer IP schützt, ist hier kontraproduktiv.
Nun fehlt nur noch ein DHCP-Relayagent auf dem Linux-Server und die Rechner bekommen eine DHCP-Adresse. Bleibt aber ein Problem: je nachdem welcher Agent schneller antwortet bekommt der Rechner eine Adresse aus dem regulärem Pool oder aus dem neuen Deployment Pool.
Hier hilft ein explizites Verbieten - leider können wir die Gruppendefinition nicht verwenden, wenn die Rechner per statischen Host-Eintrag mit einer festen IP-Adresse versorgt werden. Hier hilft folgende Zeile im alten Segment für das Netzwerk:
CODE:
if substring(option vendor-class-identifier, 0, 9) = "PXEClient" or
option vendor-class-identifier = "fbipxe-kernel" or
option vendor-class-identifier = "Linux ipconfig"
{ deny booting; } else {allow booting; }
Wieder haben wir die oben schon verwendete Fallunterscheidung. Diesmal wird jedoch die grundsätzliche DHCP-Funktion ein- oder ausgeschaltet. Die Benennung des Parameters booting ist ein wenig unglücklich - hier ist nicht das Booten des Rechners gemeint sondern das Zuweisen einer Adresse per DHCP.
Jetzt fehlen nur noch ein paar Kleinigkeiten. Unter anderem müssen die DHCP-Server eine Rückroute zum 10.10.0.0/16 Segment haben. Auch die beim Deployment beteiligten Rechner brauchen eine solche Route. Damit nicht jeder Server angefasst werden muss, werden alle anderen Netzwerkzugriffe per NAT auf eine bekannte Adresse gemappt. Damit die neue Firewall kein Sicherheitsloch aufreisst, sorgen noch ein paar iptables-Regeln dafür, dass nur die benötigten Dienste erreichbar sind.
Das Ergebnis kann sich sehen lassen: die Installation mehrerer Rechner geschieht jetzt völlig unabhängig von der Firewall. Jetzt bremsen nur noch die Netzwerkanbindung vom Linux-Server sowie natürlich die Anbindung vom Deployment-Server und dessen Festplatten. Aber gerade die Netzwerkanbindung kann man leicht skalieren. Eine Server-Netzwerkkarte gibt es im unteren dreistelligen Bereich. Die Edge-Switche kann man durch einfache Portaggregation schneller an die Core-Switche anbinden. Erst wenn die Backbone aufgerüstet werden muss, wird es wiederrum teuer. Aber 10 Gigabit-Ethernet ist ja im kommen.