Debian blind installieren
Ich habe mir nach langer Abstinenz mal wieder einen Server bei Hetzner gemietet. In der Serverbörse verschachert der Anbieter ältere Geräte als Einzelstücke, die von ihrem bisherigen Mieter zurückgegeben wurden und die teilweise aufgrund individueller Ausstattung nicht in den Mainstream hineinpassen. Dabei kann man als Kunde auch richtige Schnäppchen machen.
So bin ich seit zwei Wochen stolzer Mieter eines Hetzner-Servers mit Core i7-Vierkerner der Bloomfield-Generation mit Hyperthreading mit stolzen 48 GB RAM. Die Miete liegt bei unter 40 Euro im Monat und lässt den ähnlich alten, zum Mai gekündigten 1&1 Rootserver, der mit nur 4 GB RAM ähnlich viel Geld kostet, ziemlich alt aussehen.
Aber so ein Schnäppchen hat natürlich auch Nachteile. So gibt es nur eine einzige IPv4-Adresse, und IPv6-Adressraum, der über das standardmäßig dazugehörende einzelne /64 hinausgeht, lässt sich der Anbieter mit einer Einrichtungsgebühr in der Größenordnung von zwei Monatsmieten relativ fürstlich bezahlen. Und es gibt keine serielle Konsole. Man kann sich für einen bestimmten Zeitraum ein KVM-over-IP-Gerät anschließen lassen und die ersten x Stunden sind sogar inklusive, aber das ist natürlich nur ein magerer Ersatz. Die vom Anbieter angepriesene vnc-Installation funktioniert freilich nur für die von ihm vorbereiteten Systeme; bei näherer Betrachtung liegt das aber auch auf der Hand: Wie soll das sonst ohne Spezialhardware gehen.
In diesem Artikel soll es darum gehen, wie ich mein zgserver-Debian "blind" auf die Maschine bekommen habe.
Die Serverbörse-Server werden aufgrund ihrer hohen Streuung bei der Ausstattung nicht mit einem installierten Betriebssystem, sondern mit leeren Platten im Rescuesystem übergeben. Bei der Bestellung des Servers kann man in ein Textfeld einen ssh-Key hineinpasten, der dann für den Login auf dem Server dient. Auch den Host-Key des Rescuesystems kann man an dieser Stelle einsehen. Das ist eine schöne Lösung.
Das Rescuesystem entpuppt sich als ein aus dem Netz gebootetes, aktuelles Debian stable mit einem per NFS eingehängten root-Filesystem, über das ein tmpfs gelegt ist. Somit kann man ohne weiteres eigene Software installieren oder nachapten. Auch das ist hübsch. Gefällt mir.
Das Netzwerksetup ist wie bei Mietservern üblich bestenfalls als "seltsam" einzustufen. Die IPv4-Adresse des Systems kommt mit Netzmaske /29, wobei das Netzwerk selbst einmal "wie üblich" auf eth0 geroutet ist und zusätzlich eine zweite /29-Route auf das Gateway, das selbst die erste Adresse im /29 hat, existiert. Das IPv6 ist sehr viel mainstreamiger: Die ::2 im Netz ist auf dem Ethernet konfiguriert, daraus macht der Kernel eine implizite /64-Route auf das Ethernet. Das Defaultgateway ist fe80::1.
Aber nun zur blinden Installation. So ganz blind war sie allerdings nicht, denn ich habe geschummelt. Hilfsmittel war ein anderer Mietserver mit Virtualisierungsfunktion. Das ganze hätte ich auch bei mir zuhause machen können, aber da in der Mitte der Arbeiten ein "dd" auf den neuen Mietserver steht, habe ich das gleich an einer Stelle gemacht, an der eine akzeptable Datenübertragungsdate zum neuen System zur Verfügung steht, sonst hätte ich das alles - potenziell mehrfach - über die mageren 10 Mbit Upstream meiner Unitymedia-Anbindung schieben müssen.
Meine Idee ist, das System als VM exakt so aufzusetzen, wie es später auf der Hardware laufen wird, bis hin zum exakt nachgebauten Netzwerksetup, und das fertige System dann schlicht per dd auf die Platte des Mietservers draufzuklatschen. Im VM-Setup hat man vollen Zugriff auf Netzwerkverkehr, grafische und serielle Konsole, so dass man hier in aller Ruhe debuggen kann, ohne raten zu müssen. Praktischerweise kann man IPv4-Netze ja auch natten, wenn sie nicht aus den RFC1918-Ranges stammen, und IPv6 mit Gateway auf fe80::1 interessiert sich das System nur marginal für die auf dem Interface wirklich konfigurierte IP-Adresse. Somit kann man sich das Netzwerk in der virtualisierten Installationsumgebung genau so "zurechtfaken" wie es das später auf Hardware laufende System vorfinden wird und das System auf diese Weise in aller Ruhe und exakt so installieren, wie es später laufen wird.
Also lege ich auf dem "Gastgeber" ein neues Bridge-Interface an, konfiguriere dort fe80::1 und die IPv4-Adresse des Hetzner-Gateways. Da der Provider des "Gastgebers" Pakete mit Quelladresse aus dem Hetzner-Netz nicht routen wird (und die Antworten auf diese Pakete sowieso nicht "bei uns" rauskämen), trage ich das Hetzner-Netz zusammen mit den RFC1918-Ranges in die Liste der zu nattenden Netze ein. Mit Aktivierung dieser Konfiguration ist das Hetzner-/29 vom Gastgeber aus nicht mehr zu erreichen, da der Gastgeber dieses Netz jetzt als "für mich lokal" ansieht, aber mit dieser Einschränkung kann man leben. Für IPv6 könnte man ebenfalls NAT machen, aber das habe ich noch nie gemacht, deswegen lasse ich es hier jetzt auch. Später mal.
Da der Hetzner-Server zwei Platten hat und ich das Host-System gerne als RAID 1 betreiben würde, bekommt die VM ein "degraded" RAID 1 mit nur einer Platte. Schließlich kann die zgserver-Installation beginnen und läuft auch anstandslos durch. Da die Platte im virtualisierten System vda heißt, im endgültigen System jedoch sda heißen wird, macht man es sich einfacher, wenn man sich von den Devicenamen so weit wie möglich entkoppelt. Durch das RAID und RAID autodetect und LVM ist diese Disziplin inzwischen ein Selbstgänger; das war vor Jahren noch erheblich komplexer. Schreibt man irgendwo doch noch Devicenamen hin, ist man gut bedient, die Angebote aus /dev/disk/by-* zu verwenden; diese sind später im endgültigen System identisch. Ich mag an dieser Stelle /dev/disk/by-label ganz besonders; hier tauchen die beim Anlegen der Dateisysteme vergebenen Volumelabels auf.
Damit ich bei Problemen auf dem Mietserver später nicht komplett im Dunkeln stehe, kommt noch eine systemd-Unit dazu, die nach "network-online" ausgeführt wird und die den Netzwerkstatus ins Journal (und damit ins syslog) schmeißt. Auf diese Weise kann man dann im Fall von "kommt nicht" remote in das Rescuesystem booten und dort dann sehen, welcher Teil der Netzwerkkonfiguration nicht korrekt etabliert werden konnte:
[4/324]mh@gancho:~ $ cat /etc/systemd/system/lognetworkstatus.service [Unit] Description=Log network config to syslog Wants=network-online.target After=network-online.target Wants=syslog.service After=syslog.service [Service] Type=oneshot ExecStartPre=/sbin/ip a ExecStartPre=/sbin/ip r ExecStartPre=/sbin/ip -6 r ExecStart=/bin/true StandardOutput=journal [Install] WantedBy=multi-user.target Alias=syslog.service [5/325]mh@gancho:~ $
Zusätzlich kommt nach Strickmuster von grml als eigenes Rescuesystem ein mit Netzwerkkonfiguration und Passworten versehenes grml dazu. Entgegen meiner Aussage in dem Artikel funktioniert das mit dem heute aktuellen grml 2014.11 noch ganz prima. Der nächste Boot lässt sich mit GRUB_DEFAULT=saved in /etc/default/grub und grub-set-default auswählen. Ich glaube aber nicht, dass ich das jemals brauchen werde, das Hetzner-Rescuesystem ist "gut genug".
Für das abgetrennte /boot-Filesystem hatte ich anfänglich auch ein RAID 1 vorgesehen; das beißt sich aber mit dem grml (das squashfs wird nicht gefunden). Vielleicht wäre das auch mit einer passenden grml-Startoption gegangen, ich habe das allerdings nicht weiter verfolgt und stattdessen /boot auf eine "normale" Partition gelegt. Interessanterweise ist nach dieser Operation das RAID für die unter dem root-Filesystem liegende PV trotzdem /dev/md1 geblieben.
Als IPv6-Adresse kam noch zusätzlich zur Hetzner-Adresse eine aus dem "eigentlichen" IPv6-Range des Gastgebers dazu, damit das System dann auch per IPv6 erreichbar wäre. So konnte dann der Test in allen relevanten Lebenslagen inklusive dem Test des eigenen Notfall-grmls laufen, was dann auch relativ schmerzlos über die Bühne ging. Vielleicht sollte ich an dieser Stelle noch erwähnen, dass ich systemd-networkd verwende, weil ich das orthogonale, aus vielen kleinen, sauber nach Layern getrennte Konfigurations-Layout in /etc/systemd/network gut leiden kann. So möchte man das als Serverjockey haben.
Dann kommt der große Moment der Kopie auf das "richtige" System, mit dd if=/dev/vda bs=64M | lzop auf der einen und lzop -d | dd of=/dev/sda auf der anderen Seite. ssh dazwischen, fertig ist der Zauber. Dann geht es weiter wie bei einem regulären Umzug: Dateisysteme im rescuesystem einhängen, /dev --bind mounten, in das neue System hineinchrooten, /proc und /sys einhängen, die IPv6-Adresse aus dem Installationssystem entfernen, /etc/fstab und /boot/default/grub anpassen, grub-install /dev/sda, update-grub.
Dann der große Moment des Reboots. Und wider erwarten hat es auf Anhieb geklappt. Man kann sich über so einfache Dinge wie ein beantwortetes Ping durchaus freuen wie ein Kleinkind über eine Kugel Eis.
Ohne Rücksicht auf Verluste (es ist ja nur eine jederzeit wiederherstellbare Kopie) habe ich dann die Partitionsgröße an die gewünschte Größe auf der neuen Platte angepasst. Bei parted bedeutet das, die Partition zu löschen und mit der neuen Größe und (wichtig!) dem identischen Startsektor nochmal anzulegen. Da ich eins der moderneren RAID-Formate gewählt hatte, war hierbei noch eine Beschwörung mit mdadm notwendig, um die neue Lage des "hinteren" RAID-Superblocks bekanntzugeben: mdadm --grow --size=max /dev/md1. Danach noch ein pvresize /dev/md1 und die Platte fühlt sich an als wäre sie immer schon so groß gewesen.
Im nächsten Schritt habe ich dann die zweite Platte identisch partitioniert wie die erste und die "richtige" Partition dem nun nicht mehr degradeten RAID 1 hinzugefügt. Der Rebuild startet automatisch. Die vorne dran liegenden Partitionen (bios_grub und die für /boot) bleiben ungenutzt bzw. dienen als Backup für ihre Gegenstücke von der ersten Platte. Beim Versagen der ersten Platte ist sowieso wahrscheinlich, dass man das System entweder gar nicht mehr wird booten können oder es mit Hilfe des Rescuesystems so zurechtfrickeln muss, dass man es von der zweiten Platte booten kann.
Damit ist die "blinde" Installation des Basissystems fertig; der Rest kann so weitergehen wie auf einem "normal" installierten System. Zum Abschluß bitte nicht vergessen, den Gastgeber der Installation wieder zurückzubauen, da dort ja immer noch "fremde" IPv4-Adressen konfiguriert sind. Das kann später zu subtilen Fehlern führen, nach denen man sich erfahrungsgemäß gerne einen Wolf sucht.
Comments
Display comments as Linear | Threaded
Jakob on :
Nett. Hab ich so ähnlich auch erst vor ein paar Tagen gemacht, allerdings keine Neuinstallation übertragen, sondern das alte Live-System (das ich nicht ohne Not neu aufsetzen möchte) und mit rsync (over ssh, klar). Vorher auf dem neuen Server mit dem Rettungssystem die Partitionen entsprechend angelegt, gemountet, den alten Server auch in rescue gebootet, mount und los geht's. War bisher mein schnellster Umzug. Wäre sogar noch schneller gewesen, wenn ich vorher noch auf der alten Kiste etwas aufgeräumte hätte...
Marc 'Zugschlus' Haber on :
Mit rsync umgezogen hab ich schon ein paarmal gemacht, aber da hatte ich immer eine serielle Konsole parat für den Fall dass irgend ein Devicenamen nicht passt. Hier war die Herausforderung dass die Kiste beim neuen Hoster blind booten können muss, daher der Nachbau des Setups 1:1 in der Virtualisierung.