Systemd vs OpenRC

Systemd vs. OpenRC

Ich habe kürzlich einen Server mir Alpine Linux aufgesetzt. Die Distribution wurde mir von einem Kollegen empfohlen, der eher im BSD Kosmos heimisch ist und deshalb ein grundlegendes Problem mit Systemd hat. Da Alpine Linux den Ruf hat sehr schnell, stabil und schlank zu sein, habe ich mich dafür entschieden das Betriebssystem auszuprobieren. Alpine Linux benutzt nicht wie die meisten Linux-Disributionen Systemd als Initsystem, sondern verwendet OpenRC. Ich habe diese Gelegenheit als Aufhänger genommen um herauszufinden, warum Systemd in der Unix Community so umstritten ist und was OpenRC anders macht.

Systemd

Ein 2010 veröffentlichtes Init-System von Lennart Poettering(auch bekannt von PulseAudio) und Kay Sievers(auch bekannt von udev). Systemd setzt auf aggressive Parallelisierung um einen möglichst schnellen Bootprozes zu gewährleisten. Sofern die Abhängigkeiten es erlauben werden Prozesse so früh wie möglich und so parallel wie möglich gestartet. Neben dem Init-Daemon stellt Systemd auch noch ein Logging-System (journald), Login und Session-Management (logind), Netzwerkkonfiguration (networkd) und DNS Auflösung (resolved). Systemd wird standardmäßig von vielen gängigen Linux-Disributionen genutzt, darunter Arch Linux, Debian oder RedHat.

Technische Details

Struktur

Systemd abstrahiert das Betriebssystem in sogenannte Units. Zu den gängigsten Unit-Typen gehören:

  • Service: Daemons und Prozesse (z.B. nginx.service)
  • Target: Stellen einen Zustand des Systems dar und fassen mehrere Units zusammen (z.B. graphical.target)
  • Socket: Netzwerk- und Unix Domain Sockets (z.B. sshd.socket)
  • Timer: Regelmäßige Tasks als Alternative zu cron (z.B. backup.timer)
  • Mount: Mountpoints im Dateisystem (z.B. home.mount)
  • Device: Hardware Devices (z.B. dev-sda1.device)
  • Path: Monitoring von Dateien und Directories (z.B. config-watcher.path)

Units werden in Konfigurationsdateien definiert. In sogenannten Unit-Files können Funktion und Art einer Unit beschrieben werden. Das Funktioniert vereinfacht gesagt in drei Abschnitten. Im [Unit] Abschnitt werden Metadaten und Beziehungen zu anderen Units definiert. Der zweite Abschnitt ist nach dem Unit-Typ benannt (z.B. [Socket]) und definiert was ausgeführt wird und wie es ausgeführt wird. Im [Install] Abschnitt wird das Verhalten beim Aktivieren und Deaktiveren der Unit definiert.

Bootprozess

  1. Der Kernel startet systemd als PID 1
  2. Mounten des Dateisystems und Initialisieren der Hardware
  3. Bestimmen des zu erreichenden targets (normalerweise graphical.target oder multiuser.target)
  4. Bauen eines Trees basierend auf den Abhängigkeiten
  5. Paralleles Starten der Units basierend auf ihren Abhängigkeiten
  6. Erreichen des gewünschten Targets

Damit soviele Services wie möglich gleichzeitig gestartet werden können, stellt Systemd D-Bus-Verbindungen und IPC-Sockets für einen Service bereit, bevor dieser überhaupt gestartet ist. Erhält ein Service auf diesem Weg Nachrichten, die er noch nicht annehmen kann, buffert der Kernel diese.

OpenRC

Ein Init System des NetBSD Entwicklers Roy Marples für Unix-Systeme. OpenRC fokussiert sich dabei auf das Management der Abhängigkeiten. Das Programm ist dafür bekannt besonders schlank zu sein und einem einfachen und klaren Design zu folgen. Deshalb kommt OpenRC bei der performance-orientierten Distribution Alpine Linux zum Einsatz, welche sich vor allem durch ihre häufige Verwendung in Containern, immer größerer Beliebtheit erfreut. Auch Gentoo Linux, eine Distribution die sich an fortgeschrittene Nutzer, die nach viel Gestaltungsfreiheit suchen richtet, setzt auf das schlanke Init-System.

Technische Details

Struktur

In OpenRC werden Services in Runlevels unterteilt. Ein Runlevel stellt dabei einen bestimmten Zustand dar, für welchen die entsprechenden Services laufen müssen. Die folgenden Runlevel gibt es (unter anderem):

  • default: Standard Runlevel, welches normalerweise für das Hinzufügen neuer Services genutzt wird
  • sysinit: Startet Systemspezifische Prozesse wie /dev oder /sys und mounted das /lib/rc/init.d Verzeichnis, in welchem Runtime-Informationen über Services gespeichert werden
  • boot: Mounten von Dateisystemen, Hardware-Initialisation und Logging
  • single: Terminiert alle Services die nicht ins sysinit Runlevel fallen
  • reboot: Wechselt in den shutdown Runlevel und startet den Host neu
  • shutdown: Wechselt in den shutdown Runlevel und stoppt den Host

Bootprozess

  1. Der Init Prozess mit PID1 startet die OpenRC binary
  2. Bauen eines Abhängigkeitsgrafen basierend auf den Konfigurationsdateien der Runlevel und der Services
  3. Starten der Service-Skripte (/etc/init.d) mit deren Konfigurationsdateien (/etc/init.d)
  4. Wenn alles Service-Skripte ausgeführt wurden terminiert OpenRC, es bleibt kein persistenter Daemon zurück

OpenRC startet die Services standardmäßig serialisiert, also ein Service nach dem anderen, aber das Init System unterstützt auch einen parallelisierten Boot-Modus. Um die Services ohne persistenten Daemon-Prozess verwalten zu können, schreibt OpenRC Informationen über ihren Zustand in das Datesystem unter /lib/rc/init.d.

Kontroverser Monolith gegen schlankes Einzwecksystem

Die großen Flame-Kriege

Es gibt sehr wenige Themen in der Unix-Welt, die so kontrovers diskutiert werden wie Systemd. Um zu verstehen wie es dazu kommen konnte hilft ein Blick in die Historie. Die Software wurde 2010 von Pettering und Sievers programmiert. Beide Entwickler arbeiteten im Jahr der Veröffentlichung von Systemd für RedHat und das Init System wurde 2011 in Fedora standardmäßig aktiviert. Die Distribution setzte als erste per Default auf Systemd und wurde damit ihrem Ruf als Testballon für das RedHat Ökosystem gerecht. Je mehr Systemd an Popularität gewann, desto lauter wurden Stimmen sachlicher und unsachlicher Kritik. Diese richtete sich gegen das Design des Systems und gegen die Entwickler selbst.

Do many things and do them poorly

Der Hauptkritikpunkt ist relativ einfach: Systemd verletzt die Unix Philosphie. Diese lautet: do one thing and do it well. Programme sollen im Unix-Universum möglichst einfach und schlank gestaltet werden, genau ein Problem lösen und für größere Aufgaben mit anderen Programmen zusammenarbeiten. ls -l zeigt den Verzeichnisinhalt an, möchte ich Infos über eine bestimmte Datei haben, kann ich den Output mit grep “Dateiname” verknüpfen etc. Systemd hingegen startet nicht nur Services beim booten, sondern implementiert ein Logging-System, Session Management, einen Netzwerk-Daemon und einen DNS-Resolver. Die hohe Komplexität von Systemd birgt automatisch ein gesteigertes Fehler- und Schwachstellenpotential, was viele besonders beim Init System sehr kritisch sehen. Auch dass die Logs nicht, wie für Unix üblich in Plaintext, sondern in Binär geschrieben werden, sorgt für Unmut.

Der Kernkonflikt: komplexe und einfache Software

Systemd löst extrem viele Probleme. Es bootet durch die agressive Parallelisierung wahnsinnig schnell und verwaltet dabei Abhängigkeiten korrekt. Es vereinfacht die Konfiguration mithilfe der Unit Files und schafft mit seinen anderen Funktionalitäten ein kohärentes Ökosystem. Das Initsystem versucht die verschiedenen Distributionen zu vereinheitlichen, wodurch die Arbeit mit verschiedenen Linux Varianten erleichtert werden soll. Systemd soll eine umfangreiche Gesamtlösung darstellen und dabei mit guter Performance auftrumpfen. Software die so etwas leisten muss, wird automatisch komplex. Das geht allerdings nicht unbedingt mit der ursprünglichen Unix Philosophie konform. OpenRC hingegen übernimmt nur die klassischen Aufgaben eines Init-Systems. Aber auch dieser Ansatz hat Nachteile. Bei OpenRC funktionieren weniger Dinge out of the box, um das Logging muss man sich auch selbst kümmern. Letztendlich stellt sich die Frage ob die Unix Philosophie den Anforderungen der heutigen Zeit Stand hält. Meine persönliche Antwort auf diese Frage ist ganz klar: ja. Einfache und schlanke Software vermeidet viele Probleme die wir mit IT-Systemen in der modernen Zeit haben. Das gilt für Schwachstellen, Administration, Ressourcenverbrauch und viele weitere Aspekte. Trotzdem ist die Entscheidung für Systemd in vielen Fällen sehr nachvollziehbar. Durch die weite Verbreitung ist man meistens schon mit dem Programm vertraut, außerdem arbeiten viele Entwickler am System mit. Man tauscht gestalterische Freiheit für mehrere fertige Features ein und das System ist sehr performant. Wie so oft gibt es kein richtig oder falsch. Beide Init-Systeme haben ihre Daseinsberechtigung.