Zum Inhalt springen
BlogLinuxTag der Veröffentlichung: Die Automatisierung der Linux-Distribution (mit Ubuntu 20.04)

Release Day: Automatisieren der Linux-Distro (mit Ubuntu 20.04)

automating-distributions

Hallo! Ich bin Brad, ein Systems Engineer von Linode. Der heutige Tag markiert mit der Veröffentlichung von Ubuntu 20.04 einen wichtigen Tag in der Linux-Welt. Es handelt sich um die nächsten LTS-Version (Long Term Support) einer der beliebtesten Distributionen. Wie bei Ubuntu 18.04 vor zwei Jahren erwarten wir, dass dies unser am populärstes Image wird, das bereits allen Linode-Kunden zur Verfügung steht.

Dank der Automatisierung, die wir für die Erstellung, das Testen und die Bereitstellung neuer Images entwickelt haben, ist die umgehende Verfügbarkeit der Distribution hier bei Linode zur Norm geworden. Aber was genau ist ein Image (oder ein Template, wie sie manchmal genannt werden), und wie werden sie hergestellt? Um diese Frage zu beantworten, fangen wir damit an, wie Betriebssysteminstallationen normalerweise funktionieren. ​

Installieren eines Betriebssystems

Möglicherweise sind Sie mit dem Prozess der manuellen Installation eines Betriebssystems auf einem Heimcomputer oder einem Server vertraut. Normalerweise beinhaltet dies das Herunterladen einer Installations-ISO, das Brennen auf eine CD oder ein USB-Laufwerk und das Booten des Systems. Normalerweise gehen Sie durch eine Reihe von Menüs (oder manuelle Befehle), mit denen sich verschiedene Aspekte der Installation steuern lassen, z.B. auf welcher Festplatte installiert werden soll, welche Software/Pakete Sie einbinden möchten und vielleicht auch einige Anpassungen wie das Setzen eines Benutzernamens und Passworts. Wenn alles erledigt ist, haben Sie ein (hoffentlich) voll funktionsfähiges Betriebssystem, das Sie hochfahren und benutzen können.

Dieses Verfahren funktioniert gut für Anwender, die einmalige Installationen durchführen. Aber wenn Sie mehr als nur eine kleine Handvoll Systeme installieren müssen, dann ist der manuelle Installationsprozess einfach unbrauchbar. An dieser Stelle kommen die Images ins Spiel. ​

Was ist ein Image?

Ein Image ist im Wesentlichen ein vorinstalliertes Betriebssystem, das Sie auf so vielen Systemen wie benötigt einsetzen können. Es funktioniert, indem Sie eine normale Installation durchführen und dann eine Kopie dieser Installation erstellen, die Sie später auf einem anderen System "einfügen" können. Es gibt eine Vielzahl von Möglichkeiten und Formaten, in denen Sie Images zur späteren Verwendung speichern können, aber in den meisten Fällen handelt es sich dabei um exakte Byte-für-Byte-Kopien der Originalinstallation.

Jetzt müssen wir eine manuelle Installation nur einmal durchführen, und schon können wir sie überall wiederverwenden. Aber das geht noch besser: Linode unterstützt eine Vielzahl von Distributionen, von den üblichen Verdächtigen (Debian, Ubuntu, CentOS, OpenSUSE) bis hin zu einigen, die Sie bei anderen Anbietern vielleicht nicht finden (Alpine, Arch und sogar Gentoo), jede mit eigenem Veröffentlichungszeitplan und eigener Support-Lebensdauer. Es wäre enorm zeitraubend und unfallträchtig, manuelle Installationen für alle von uns unterstützten Distributionen durchzuführen (selbst wenn's nur einmal ist), zumal man sich Zeit nehmen muss, Funktionstüchtigkeit sowie Fehlerlosigkeit der Images sicherzustellen. Deshalb haben wir uns stattdessen dafür entschieden, den Image Building Prozess selbst zu automatisieren, und zwar mit Hilfe eines wunderbaren Tools namens Packer von HashiCorp. ​

Automatisierung des Build

Auch wenn alle Linux-Distributionen eine gemeinsame Basis (nämlich den Linux-Kernel) haben, unterscheiden sie sich doch alle sehr voneinander, etwa in der Art und Weise, wie sie installiert werden. Einige Distributionen verwenden Befehlszeilenanweisungen, andere verwenden Menüoberflächen und wieder andere bieten Möglichkeiten, automatisch durch diese Menüs zu navigieren. Glücklicherweise ist Packer ein sehr vielseitiges Werkzeug und kann mit all diesen Anwendungsfällen umgehen.

Als erstes weisen wir Packer an, eine virtuelle Maschine (VM) zu erstellen, die einem Linode so ähnlich wie möglich ist. Das bedeutet, dass wir die gleiche "Hardware" und die gleichen Funktionen emulieren, die wir für echte Linoden verwenden. So wird die Installation in einer Umgebung durchgeführt, die der endgültigen Laufzeitumgebung sehr ähnlich ist. Stellen Sie sich vor, Sie installieren ein Betriebssystem auf einem USB-Laufwerk und verwenden dann dieses Laufwerk, um einen völlig anderen Computer zu starten. Wenn Sie Glück haben, funktionieren das vielleicht, aber in den meisten Fällen wird irgendein Hardware-Gerät nicht erkannt, oder vielleicht bootet es erst gar nicht. Indem wir eine Installationsumgebung haben, die der tatsächlichen Betriebsumgebung entspricht, beseitigen wir diese Probleme.

Sobald die VM erstellt ist, bootet Packer sie von der Installations-ISO der Distribution, die er von einer angegebenen URL abruft. Der Prozess variiert ab hier stark zwischen den verschiedenen Distributionen. Bei befehlsgesteuerten Distributionen wie Arch füttern wir sie mit einem Bash-Skript, das eine Basisinstallation durchführt. Für menügesteuerte Distributionen wie Ubuntu verwenden wir die von der Distribution bevorzugte Methode, dem Installer Antworten zu liefern (typischerweise entweder Preseed auf Debian-ähnlichen Distributionen oder Kickstart auf RHEL-ähnlichen Distributionen). Zusätzlich zu unserer VM erstellt Packer auch einen winzigen HTTP-Server, mit dem alle benötigten Dateien in die VM übertragen werden. ​

All dies wird über eine JSON-Datei gesteuert, die die Einstellungen und Build-Optionen definiert, die Packer verwenden wird. Um einen Build zu initiieren, müssen wir (zum Beispiel) einfach Folgendes starten: packer build ubuntu-20.04.json.

Anpassung

In den meisten Fällen führen wir Installationen durch, die so unverfälscht wie möglich sind. Das bedeutet, dass wir nur Pakete installieren, die als "Standard" (manchmal auch "Basis" oder "Default") bezeichnet werden. Zusätzlich zu diesen Standardpaketen installieren wir auch eine kleine Handvoll so genannter "Support"-Pakete: Basis-Dienstprogramme wie iotop, mtr und sysstat, die bei der Behebung eventuell auftretender Probleme helfen können. Infolgedessen kann das Linode Support Team vernünftigerweise davon ausgehen, dass diese Tools bei der Unterstützung der Kunden installiert werden.

Nachdem die Installation abgeschlossen ist, aber noch bevor die VM heruntergefahren wird, nehmen wir einige letzte Anpassungen vor. Sie sollen die ordnungsgemäße Funktion aller Teile der Linode-Plattform gewährleisten. Zum Beispiel stellen wir sicher, dass der Bootloader mit den richtigen Einstellungen für LISH (unser Werkzeug für den Out-of-Band-Konsolenzugriff) konfiguriert ist. Im Allgemeinen versuchen wir jedoch, die Dinge so nah wie möglich an ihren Standardeinstellungen zu halten. Auf diese Weise bekommt ein Nutzer, der eine bestimmte Distribution bevorzugt, was er kennt. Es wird sich nicht so anfühlen, als würde er das Auto eines anderen fahren.

Packaging

Nachdem Installation und Konfiguration abgeschlossen sind, fährt Packer die VM herunter und exportiert ihr Datenträgerabbild in eine Datei. Hört sich an, als wären wir fertig, aber es sind noch ein paar Schritte übrig. Die Festplatte eines typischen Computers beginnt mit einer Partitionstabelle (entweder MBR, oder GPT auf neueren Systemen). Linoden sind insofern einzigartig, als der GRUB-Bootloader selbst auf unseren Hosts und nicht auf jedem Linode liegt (die Konfiguration wird jedoch immer noch aus Linode gelesen). Das bedeutet, dass wir die Partitionstabelle komplett entfernen können, so dass wir nur eine einzige Partition haben.

Um dies zu erreichen, führen wir fdisk -l disk.img auf dem Datenträgerabbild aus, um festzustellen, wo die Partition beginnt, wo sie endet, und wie groß die Blockgröße ist. Wir verwenden dann dd if=disk.img of=part.img bs=### skip=### count=### , um die Partition unter Einsatz des Starting Offsets unseres vorherigen Befehls zu "stapeln". Genauer gesagt wird jedes "###" in diesem Befehl durch Output unseres früheren fdisk -Befehls ersetzt.

Genau wie bei einem neuen Computer wird der meiste Speicherplatz auf dem Laufwerk leer sein, dies wird sich in unserem Datenträgerabbild widerspiegeln. Es wäre dumm, all diese "leeren" Bytes zu kopieren, also ist das nächste, was wir tun eine Deflate-Kompression des Images (später, wenn Sie ein Image für Ihr Linode bereitstellen, werden wir es neu aufblasen , um den verfügbaren Platz auf Ihrer Instanz auszufüllen). Da alle unsere Images ext4-Partitionen verwenden, können wir mit  resize2fs -M part.img unser Image automatisch auf die kleinstmögliche Größe schrumpfen, indem wir den leeren Raum entfernen. Um die Integrität des resultierenden Images zu gewährleisten, führen wir abschließend einen fsck aus, bevor wir es komprimieren, und zwar mit gzip.

Test

Nachdem das Image zusammengestellt und vorbereitet wurde, muss sichergestellt werden, dass es auch tatsächlich funktioniert. Unser neu erstelltes Image wird in eine Testumgebung versetzt, in der eine Reihe von Linode-Instanzen in verschiedenen Konfigurationen vom Image bereitgestellt werden. Wir haben eine automatisierte Testsuite entwickelt, die alle möglichen verschiedenen Dinge prüft, etwa die Netzwerk-Konnektivität oder einen Working Package Manager sowie verschiedene Funktionen der Linode-Plattform wie Backups oder die Größenanpassung der Festplatte. Dann heizen wir den Instanzen so richtig ein. Wenn ein Test fehlschlägt, wird der Prozess sofort abgebrochen und der Build gilt als gescheitert. Zusätzlich erhalten wir die Info, welcher Test fehlgeschlagen ist und warum.

Die automatisierte Erstellung und Prüfung auf diese Weise ermöglicht schnelle Entwicklungszyklen, die es uns wiederum ermöglichen, bessere Images schneller zu veröffentlichen. Wir haben unseren Testprozess so strukturiert, dass das Hinzufügen neuer Prüfungen ganz einfach ist. Wenn ein Kunde jemals ein Problem mit einem unserer Images meldet, können wir schnell eine Korrektur freigeben - und einen weiteren Punkt zu unserer wachsenden Liste von Tests hinzufügen - fast wie bei einem Immunsystem! ​

Genau so, aber anders

Die massenhafte Bereitstellung von Systemen von einem gemeinsamen Image aus ist großartig, aber was ist mit den Dingen, die für eine bestimmte Instanz einzigartig sind, wie etwa das Root-Passwort oder die Netzwerkkonfiguration? Unsere Images sind von Haus aus so konfiguriert, dass sie DHCP verwenden. Dieses sorgt dafür, dass Ihr System automatisch die ihm zugewiesene IP-Adresse und einen eindeutigen Hostnamen von unseren DHCP-Servern erhält. Wir bieten jedoch auch eine Reihe von "Helfern" an, wie Network Helper (der automatisch die statische Netzwerkkonfiguration auf Ihrem Linode vornimmt) und unser Root-Passwort-Rücksetz-Tool (das Ihr anfängliches Root-Passwort festlegt und das Sie auch in Notfällen benutzen können, wenn Sie es zurücksetzen müssen). Diese Tools ermöglichen es beispielsweise, spezifische Informationen auf Ihrem Linode über das Basis-Image anzuwenden.

Natürlich handhabt nicht jede Distribution diese Aufgaben auf die gleiche Art und Weise, deshalb müssen unsere Werkzeuge wissen, wie sie diese Dinge auf allen von uns unterstützten Distributionen erledigen können. Neue Hauptversionen einer Distribution erfordern in der Regel einige Aktualisierungen, um sie voll funktionsfähig zu machen. Zum Beispiel konfiguriert Debian traditionell die Vernetzung in /etc/network/interfaces, CentOS dagegen in /etc/sysconfig/network-scripts. Glücklicherweise stellen die meisten Distributionen vorab Betaversionen zur Verfügung, so dass wir genügend Zeit haben, diese Änderungen vorzunehmen. ​

Fazit

Wie Sie sehen, gibt es eine Menge Dinge, die in die Unterstützung einer neuen Distribution einfließen. Was ist also der wahre Nutzen einer Automatisierung dieses Prozesses? Nun, vor Jahren, bevor wir den besagten Prozess hatten, dauerte eine typische Distributionsfreigabe (vom Aufbau über das Testen bis zur Verfügbarkeit) im Idealfall einen Tag, normalerweise aber mehrere Tage, und viele Leute waren daran beteiligt. Im Vergleich dazu erforderte die heutige Version von Ubuntu 20.04 nur fünf Zeilen Code-Änderungen. Zudem dauert sie von Anfang bis Ende noch nicht mal eine Stunde. Dieser Ansatz zur Erstellung von Images erspart uns eine Menge Zeit und Ärger und führt zu konsistenten Builds, die gründlich getestet und ständig verbessert werden. Wenn Sie irgendwelche Vorschläge oder Dinge haben, die Sie gerne sehen würden, lassen Sie es uns wissen! Ich hänge im IRC als "blaboon" auf OFTC und als "lblaboon" auf Freenode herum. Wenn Sie daran interessiert sind, Packer selbst auszuprobieren, gibt es dort eine großartige Dokumentation, die Sie hier finden können. Wir haben auch unseren eigenen Linode-Builder für Packer, mit dem Sie Ihre eigenen angepassten Images auf unserer Plattform erstellen können. Weitere Dokumentation zur Verwendung des Linode Builder for Packer finden Sie in unserer Guides


Sie sind kein Linode-Kunde? Melden Sie sich hier mit einer Gutschrift von 20 $ an.


Kommentare (4)

  1. Author Photo

    This is brilliant and very timely (for me) as I happened to spend some of last weekend to “reverse engineer” the build process (and discovered the GRUB config quirks) while tried to test migrating a Linode VM over to a on-premises (lab) VM Host and vice versa. Maybe this would be a good write-up, if you are searching for tutorial/blog topics. Many thanks for publishing this!

  2. Nathan Melehan

    Hey A. –

    That sounds like a cool topic! If you’re interested, we actually have a paid freelance contributor program for our documentation library called Write For Linode. You can learn more about the program and apply to it here: https://www.linode.com/lp/write-for-linode/

    • Author Photo

      Hi Nathan
      Thanks for this, it looks very tempting. I started to work on the process for the first migration but I was stopped by Grub2. As described in the Packaging section above, the stripped out boot partition stops me to boot up the the image in my VM Host and I haven’t been able boot up the image dd’d out of Linode. If I create a vanilla VM image with the same Ubuntu version as in my Linode VM, the (virtual) disk is partitioned with two partitions, sda1 hosting grub (I assume this is what you strip out in the build process) and sda2, which is “/”. The image “exported” out of Linode, on the other hand has only a single partition as described above. Is there any documentation describing how to undu the stripping out of sda1, or how insert a new boot (sda1) partition back into the image? Many thanks, A

      • Author Photo

        Ok, I managed to get through booting my local clone in the end and it turns out that the startup process didn’t crash (as I thought), it was just slow*. It is because (unsurprisingly) it has a hard-coded static IP address which now lives on the wrong network, so I had to wait until the network config time-out* during the boot-up process.

        That’s easy enough I’ll just change the config in /etc/network/interfaces (the default/standard place in Ubuntu, and as also mentioned in this article). Looking at the “interfaces” file it, is blank with a note that things have moved on (since I last had to deal with linux networking) and it is now handled by something called “netplan”. [grrrrr….]

        No matter, it can’t be that hard, let’s see what /etc/netplan says. Well, the yaml file says my ethernet interface should be called `enp0s3` and should be getting the address from dhcp. But my actual interface name is `eth0` and has a static address. Where is this coming from?! [&$#^%#]

        Time to “brute force” search the entire config.
        `find /etc/ -exec grep ‘12.34.56.78’ {} \; 2>/dev/null` results in 3 hits, one is by an application so there are only two potential places to change, it might be easy enough to check**:

        `grep -Rn ‘12.34.56.78’ * 2>/dev/null`

        systemd/network/05-eth0.network
        systemd/network/.05-eth0.network

        It was auto-generated by Linode’s Network Helper (as described in the article) which is not available in my lab, unsurprisingly, so let’s just copy back the original config:

        `cp 05-eth0.network 05-eth0.network.bak`
        `cp .05-eth0.network 05-eth0.network`
        `shutdown -r now`

        Bingo!!! The VM came up with a new dynamic IP address and I can ping and nslookup to my heart content!!! I haven’t checked if the actual web application survived the extraction, and what else may have broken in the process.

        *and probably a lot more linode specific configs that are inaccessible to my local clone.
        **The actual IP address is not this

        Lessons learned: It is a lot more complicated to migrate out of Linode to a local VM or different cloud and require a lot of effort to fix/adapt the extracted application and the OS, it would be a lot faster just to build the lab up from the ground up. It might be a simpler process to move the other way around (i.e. develop in my own lab and pull the result into Linode) but wouldn’t hold my breath trying.

        Not sure if my experience warrants an article beyond this (chain of) comment(s). But it was a great weekend project and an inspirational learning exercise, many thanks, Linode!

Kommentar abgeben

Ihre E-Mail Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit *gekennzeichnet