Aus Linux-Magazin 06/2021

Images bauen mit Kiwi

© Fernando Gregory Milan / 123RF.com

In vielen Fällen erleichtern und beschleunigen Images die Installation neuer Systeme. Das Werkzeug Kiwi hilft dabei, passende Systemabbilder selbst aus dem Hut zu zaubern.

Als System-Images bezeichnet man Abbilder installierter und vorkonfigurierter Betriebssysteme inklusive Anwendungssoftware zum sofortigen Einsatz. Es gibt sie in verschiedenen Ausprägungen. Am bekanntesten ist wohl die Variante als virtuelles System, das man in der PaaS-Cloud nutzt. Zu den weiteren Einsatzgebieten zählen das Preload auf Desktop-Systemen und Laptops oder das SD-Karten-Image für den Einplatinencomputer.

Man kann System-Images Schritt für Schritt erzeugen, indem man ein System nach Wunsch beziehungsweise vorliegenden Standards installiert und konfiguriert und anschließend eine Kopie der Installation anlegt. Dabei sollte man aber nicht vergessen, bestimmte Konfigurationsdateien zu entfernen, zum Beispiel solche, die Merkmale des Quellsystems enthalten wie MAC-Adressen oder die IDs von Festplatten. Allerdings ist dieses Vorgehen relativ aufwendig und fehleranfällig. Leichter geht der Image-Bau von der Hand, wenn man ein Werkzeug wie Kiwi benutzt.

Kiwi NG [1] oder kurz Kiwi baut unterschiedliche Typen von System-Images, etwa solche zum Start als virtuelle Maschine oder zum Installieren auf einem Bare-Metal-System. Bei Letzterem kopiert das Tool das fertige Systemabbild direkt auf das lokale Speichermedium, sodass es beim nächsten Start der Hardware sofort für den Einsatz bereitsteht.

Diese Installationsart lässt sich noch um Konfigurationsdienste erweitern wie »yast-firstboot« bei Suse. Dieses YaST-Modul fragt dann beim ersten Start Informationen zum Benutzer ab wie Name und Passwort oder auch die Zeitzone (Abbildung 1). Kiwi kann aber nicht nur Images für Suse erstellen. Das klappt auch für alle anderen RPM-basierten Distributionen sowie für Debian/Ubuntu und auch Arch Linux. Die Installation von Kiwi selbst erläutert der Kasten “Kiwi NG einrichten”.

Abbildung 1: Abfrage des Root-Passworts durch YaST2-Firstboot beim ersten Start.

Abbildung 1: Abfrage des Root-Passworts durch YaST2-Firstboot beim ersten Start.

Kiwi NG einrichten

Je nach eingesetzter Distribution bieten die Maintainer über den OpenSuse-Build-Service fertige Installationspakete an [5]. Gibt es auf dem System eine Python3-Installation mit Pip, lässt sich Kiwi NG auch mit dem Kommando »pip install Kiwi« installieren. Nach dem Einrichten ruft man das Binary »Kiwi-ng« auf. Die erste Version von Kiwi war in Perl geschrieben und trug die Versionsnummer 7. Sie wird heute auch als Legacy Kiwi bezeichnet. Für Version 9 erfolgte ein kompletter Rewrite in Python – Kiwi NG war geboren.

Verwenden von Kiwi

Um Kiwi verwenden zu können, benötigen Sie unabhängig vom Typ des zu erstellenden Systemabbilds eine Beschreibung des Systems. Sie muss im XML-Format vorliegen und alle Informationen zum späteren System enthalten, also etwa Paketlisten und -Quellen, anzulegende Benutzer mit Passwörtern und Gruppen oder die Partitionierung beziehungsweise das LVM-Layout. Listing 1 zeigt ein Beispiel.

Listing 1

XML-Profilbeschreibung für Kiwi

<?xml version="1.0" encoding="utf-8"?>
<image schemaversion="6.8" name="Leap-15.2_example">
  <preferences>
    <version>1.15.2</version>
    <packagemanager>zypper</packagemanager>
    <locale>de_DE</locale>
    <keytable>de</keytable>
    <timezone>Europe/Berlin</timezone>
    <rpm-excludedocs>true</rpm-excludedocs>
    <rpm-check-signatures>false</rpm-check-signatures>
    <bootsplash-theme>bgrt</bootsplash-theme>
    <bootloader-theme>OpenSuse</bootloader-theme>
    <type image="vmx"
      filesystem="ext4"
      bootloader="grub2"
      kernelcmdline="splash"
      firmware="efi">
    </type>
  </preferences>
  <users>
    <user password="$1$wYJUgpM5$RXMMeASDc035eX.NbYWFl0"
      home="/root"
      name="root"
      groups="root"/>
  </users>
  <repository type="rpm-md" alias="Leap_15_2" imageinclude="true">
    <source path="obs://OpenSuse:Leap:15.2/standard"/>
  </repository>
  <packages type="image">
    <package name="checkmedia"/>
    <package name="patterns-OpenSuse-base"/>
    <!-- .... -->
    <package name="openssh"/>
    <package name="kernel-default"/>
  </packages>
  <packages type="bootstrap">
    <package name="udev"/>
    <package name="filesystem"/>
    <package name="glibc-locale"/>
  </packages>
</image>

Nach der Paketinstallation

Meist genügt es nicht, Pakete lediglich zu installieren; es gilt, auch deren Konfiguration anzupassen. Die einfachste Variante zum Einfügen eigener Dateien in die spätere Appliance ist es, ein Verzeichnis namens »root/« zu erstellen und dort die Struktur des späteren Dateisystems mit dem Speicherort der Konfigurationsdatei nachzubauen.

Soll es im späteren System beispielsweise eine Datei »/etc/appliance_version« geben, muss sie mit dem gewünschten Inhalt unter »root/etc/appliance_version« liegen. Kiwi kopiert den Inhalt dieses Verzeichnisses nach der Installation der im XML-Profil genannten Pakete in das spätere Dateisystem. Damit lassen sich auch Dateien aus den Installationspaketen überschreiben und so anpassen.

Nachdem man die Pakete ins künftige System kopiert und eingerichtet hat, muss man eventuell noch Dienste für den automatischen Start konfigurieren. Dafür bietet Kiwi die Möglichkeit, Skripte zu hinterlegen, die das Tool an definierten Stellen des Bauprozesses aufruft.

Grob lässt sich die Arbeit von Kiwi in zwei Hauptprozesse aufteilen: die Vorbereitung (Preparation) und die Erstellung (Create). Der Vorbereitungsteil umfasst die bis jetzt besprochenen Schritte, also das Installieren der Pakete, das Erstellen von Benutzern und Gruppen, das Kopieren der Dateien aus dem Root-Verzeichnis und eventuell zusätzlich angegebener Archive sowie abschließend der Aufruf des Skripts »config.sh«, falls es vorhanden ist.

Zum Schluss noch ein Skript

Kiwi führt »config.sh« in einer Chroot-Umgebung im künftigen Dateisystem aus. Das Skript darf beliebige Programmaufrufe enthalten, die das System weiter anpassen. Das kann das bereits erwähnte Aktivieren von Diensten beim Start sein (»systemctl enable Dienst«), aber auch die Verkleinerung des Dateisystems durch das Entfernen nicht benötigter Dateien. Damit ist der Vorbereitungsteil abgeschlossen; Kiwi hat die künftige Appliance in ein Verzeichnis installiert und nach den Vorgaben angepasst.

Im nächsten Schritt erstellt Kiwi aus diesem Verzeichnis nun einen oder mehrere Image-Typen. Vorher sollten Sie die Konfigurationsdateien im künftigen Dateisystem nochmals überprüfen. Das ist für die Arbeiten an einem neuen Image sehr hilfreich, wenn es gilt, viele Anpassungen am Dateisystem vorzunehmen. Besteht dafür kein Bedarf, lassen sich auch in einem Aufruf von Kiwi direkt der Vorbereitungs- und Bauprozess abarbeiten und das gewünschte Systemabbild direkt erstellen.

Das Beispiel aus Listing 2 erstellt aus dem Verzeichnis heraus, in dem die benötigten Beschreibungsdateien liegen (Parameter »–description«), ein Image vom Typ OEM. Es entsteht im per »–target-dir« angegebenen Verzeichnis (hier »/tmp/Kiwi-ng-builddir«), wo anschließend auch die Abbilddateien des fertigen Images liegen.

Listing 2

Image bauen

$ sudo Kiwi-ng --type oem system build --description . --target-dir /tmp/Kiwi-ng-builddir

Beispiele anpassen

Beispiele für Image-Beschreibungen, also XML-Profile mit Skripten und Root-Verzeichnis, stellen die Kiwi-Maintainer in einem Repository auf Github [2] zur Verfügung. Das lokale Klonen des Repositorys inklusive der enthaltenen Beispiele ermöglicht einen schnellen Einstieg. Die Beispiele lassen sich dann direkt ausprobieren.

Auf Basis der Beispiele der Maintainer erstellen Sie ganz schnell ein eigenes Image mit individuellen Anpassungen für eine virtuelle Maschine. Dazu klonen Sie das Repository via Git und wechseln in das entsprechende Verzeichnis (Listing 3). Den Inhalt des Beispielverzeichnisses sehen Sie ab Zeile 4.

Listing 3

Repo klonen

$ git clone https://github.com/OSInside/Kiwi-descriptions
$ cd Kiwi-descriptions/suse/x86_64/suse-leap-15.2
$ ls -1
config.sh
config.xml
root
root/etc
root/etc/udev
root/etc/udev/rules.d
root/etc/udev/rules.d/70-persistent-net.rules
root/etc/motd
root/etc/sysconfig
root/etc/sysconfig/network
root/etc/sysconfig/network/ifcfg-lan0

Die Datei »config.xml« steuert den Bauprozess beziehungsweise legt fest, was installiert und konfiguriert werden soll. Nach dem Bauprozess kopiert Kiwi den Inhalt des Root-Verzeichnisses in das Root-Dateisystem. Abschließend läuft das Skript »config.sh«. Im Beispiel aus Listing 4 aktiviert das Skript den SSH-Daemon sowie Chronyd und setzt das Systemd-Target auf “grafisch” (entspricht dem früheren Runlevel 5).

Listing 4

config.sh

test -f /.kconfig && . /.kconfig
test -f /.profile && . /.profile
echo "Configure image: [$Kiwi_iname]..."
suseSetupProduct
suseInsertService sshd
suseInsertService chronyd
baseSetRunlevel 5

Häufig ist es sinnvoll, Zeitserver einzubinden (Abbildung 2), entweder die des NTP-Pool-Projekts oder auch eigene. Dazu genügen wenige Anpassungen. Dafür müssen die Pakete chrony und chrony-pool-empty installiert sein. Ohne Angabe des Letzteren installiert das System ein für OpenSuse-Zeitserver vorkonfiguriertes Paket. Die zu nutzenden Zeitserver stehen in der Datei »root/etc/chrony.d/server.conf« (Listing 5).

Abbildung 2: Die Konfiguration der zu nutzenden Zeitzone durch YaST2-Firstboot beim ersten Start.

Abbildung 2: Die Konfiguration der zu nutzenden Zeitzone durch YaST2-Firstboot beim ersten Start.

Listing 5

Zeitserver

server 0.de.pool.ntp.org
server 1.de.pool.ntp.org
server 2.de.pool.ntp.org
server 3.de.pool.ntp.org

Für den Start des Diensts Chronyd sorgt der Eintrag »suseInsertService chronyd« in der »config.sh«. Stattdessen kann das Skript auch einen Systemctl-Aufruf oder beliebige andere Befehle enthalten. Für einige Standardprozesse bietet Kiwi zur weiteren Vereinfachung vorbereitete Funktionen an wie im Beispiel »suseInsertService«. Eine Liste mit Erklärungen [3] dazu findet sich auf der Webseite des Projekts.

Eine eigene “Message of the Day” liefert ein entsprechender Eintrag in der Datei »root/etc/motd« (Listing 6).

Listing 6

MotD

Willkommen auf unserer angepassten OpenSuse Leap 15.2 Appliance.

Finale Konfiguration

Soll der Benutzer die fertige Appliance beim ersten Start einrichten, gibt es dafür bei OpenSuse das Paket yast2-firstboot [4]. Ist es installiert, fragt das System beim ersten Start den Benutzer nach der individuellen Konfiguration. Dazu zählen Benutzername und Passwort, Hostname, Netzwerkkonfiguration, Zeitzone und vieles mehr.

Die aufzurufenden Module stehen in der Datei »root/etc/YaST2/firstboot.xml« im späteren Dateisystem. Listing 7 zeigt eine Beispielkonfiguration, die die Module für die Systemsprache, das Tastaturlayout, die Zeitzone sowie einen zu erstellenden Benutzer startet. Auch das Root-Passwort wird hier abgefragt und gesetzt. Damit entsteht aus einem Vorbild ein kundenspezifisches Image, dass sich sofort installieren und nutzen lässt. (jcb/jlu)

Listing 7

Systemkonfiguration abfragen

<?xml version="1.0"?>
<productDefines  xmlns="http://www.suse.com/1.0/yast2ns"
  xmlns:config="http://www.suse.com/1.0/configns">
  <textdomain>firstboot</textdomain>
  <globals>
  <enable_autologin config:type="boolean">false</enable_autologin>
  </globals>
  <workflows  config:type="list">
    <workflow>
      <stage>firstboot</stage>
      <label>Configuration</label>
      <mode>installation</mode>
      <modules  config:type="list">
        <module>
          <label>Language and Keyboard</label>
          <enabled config:type="boolean">true</enabled>
          <name>firstboot_language_keyboard</name>
        </module>
        <module>
          <label>Time and Date</label>
          <enabled config:type="boolean">true</enabled>
          <name>firstboot_timezone</name>
        </module>
        <module>
          <label>Users</label>
          <enabled config:type="boolean">true</enabled>
          <name>firstboot_user</name>
        </module>
        <module>
          <label>Root Password</label>
          <enabled config:type="boolean">true</enabled>
          <name>firstboot_root</name>
        </module>
      </modules>
    </workflow>
  </workflows>
</productDefines>

Die Autoren

Christian Schneemann arbeitet bei der B1 Systems GmbH als Linux-Consultant und Developer mit Schwerpunkt Systemmanagement und Deployment. Er beteiligt sich an der Entwicklung von kundenspezifischen Linux-Appliances und betreut diese im Kundenauftrag. Sebastian Meyer ist seit 2013 als Linux-Consultant und Trainer für die B1 Systems GmbH tätig. Seine Schwerpunkte liegen im System- und Softwaremanagement mit den unterschiedlichsten Tools zum Konfigurationsmanagement und Deployment.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 1 HeftseitePreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben