Infrastructure as Code¶
Diese Seite erklärt, wie wir die Infrastruktur über Dateien im Repo verwalten, was dabei beim Ausrollen passiert und wo diese Arbeitsweise an ihre Grenzen kommt.
Server brauchen Konfiguration¶
Damit eine Software auf einem Server läuft, muss der Server dafür eingerichtet werden: welches Programm in welcher Version läuft, wo es seine Daten ablegt, unter welcher Adresse es erreichbar ist, welche Zugangsdaten und Schlüssel es nutzt. Unter Linux steht diese Konfiguration in der Regel in Textdateien auf dem Server.
Man kann diese Dateien direkt auf dem Server ändern, aber das hat Nachteile:
- Was geändert wurde, wann und warum, weiß hinterher nur, wer es getan hat.
- Soll ein Server neu eingerichtet werden, etwa nach einem Ausfall, muss man jede Änderung aus dem Gedächtnis wiederholen.
- Ändern zwei Leute an derselben Stelle, merkt das niemand, und ein Fehler lässt sich nicht einfach zurücknehmen.
Deshalb bearbeiten wir diese Dateien nicht auf dem Server. Die maßgebliche Fassung, die Quelle der Wahrheit, liegt in diesem Repo, von dem jede und jeder eine Kopie auf dem eigenen Rechner hat. Dort ändern wir die Konfiguration, und Werkzeuge übertragen sie auf den Server (siehe Wie das funktioniert).
Dasselbe gilt für Dienste, die wir über die Schnittstelle (API) eines Anbieters einrichten, etwa die DNS-Einträge bei deSEC oder die Anwendungen in Authentik: Auch hier steht die Konfiguration als Datei im Repo, und ein Werkzeug überträgt sie zum Anbieter.
Diese Arbeitsweise heißt Infrastructure as Code, und sie behebt die Nachteile von oben:
- Jede Änderung ist nachvollziehbar: Sie ist ein Commit im Repo, und in der Git-Historie steht, wer was wann geändert hat und warum.
- Wie ein Server eingerichtet ist, steht vollständig in seinen Dateien. Man muss sich nicht auf dem Server umsehen, um zu verstehen, was dort läuft, und kann im Repo nach allem suchen.
- Die Konfiguration eines Servers lässt sich jederzeit neu ausrollen, auf denselben oder einen neuen Server; was im Repo steht, kommt jedes Mal gleich heraus.
Welches Werkzeug wofür zuständig ist, steht in Lokales Tooling.
Wie das funktioniert¶
Die Dateien beschreiben den Sollzustand: wie der Server am Ende aussehen soll, zum Beispiel „ein Container HedgeDoc in Version 1.12.0 mit diesem Volume“. Sie beschreiben nicht die Befehle, die dorthin führen. Diese Art der Beschreibung heißt deklarativ.
Das Werkzeug ermittelt die nötigen Schritte selbst, in zwei Teilen (plan und apply):
- plan vergleicht den Sollzustand mit dem, was gerade auf dem Server eingerichtet ist (dem Istzustand), und zeigt den Unterschied an. plan ändert nichts.
- apply gleicht den Istzustand an den Sollzustand an: Es legt an, was fehlt, ändert, was abweicht, und entfernt, was nicht mehr im Repo steht.
flowchart LR
soll["Sollzustand<br>Dateien im Repo"]
ist["Istzustand<br>Server oder Anbieter"]
plan{{"plan<br>Unterschied anzeigen"}}
apply{{"apply<br>Ist an Soll angleichen"}}
soll --> plan
ist --> plan
plan -->|Unterschied ist gewollt| apply
apply --> ist
Weil apply immer vom Sollzustand ausgeht, ist es egal, ob man es einmal oder mehrmals ausführt: Stimmt der Istzustand schon, zeigt plan keinen Unterschied, und apply tut nichts.
Bei syslet heißen die Befehle cue cmd plan und cue cmd apply, bei desync und Terraform gibt es dieselben zwei Schritte.
Wie syslet dabei genau vorgeht, steht in Reconciliation model in der syslet-Doku und How an apply works in der syslet-Doku.
Drift¶
Ändert jemand etwas von Hand auf dem Server oder in der Web-Oberfläche eines Anbieters, weicht der Istzustand vom Repo ab. Diese Abweichung heißt Drift.
Drift an dem, was das Werkzeug verwaltet, zeigt das nächste plan als Unterschied an, und das nächste apply macht ihn rückgängig, egal wer apply ausführt. Bei syslet sind das die von syslet erzeugten Quadlet-Dateien der Container, Volumes und Netzwerke, die Podman Secrets, die vorhandenen Images und ob ein Dienst läuft.
Änderungen außerhalb davon sieht plan nicht, zum Beispiel Änderungen direkt in einem laufenden Container. Sie bleiben bestehen, bis der Container neu erzeugt wird, und tauchen im Repo nirgends auf.
Deshalb ändern wir Konfiguration nie von Hand; was man auf dem Server tun darf, steht in Was man von Hand darf.
Was Infrastructure as Code bei uns nicht leistet
Ein Server ist nicht mit einem cue cmd apply komplett wiederhergestellt.
- Das Repo enthält keine Daten. Es beschreibt nur die Konfiguration. Die Daten der Apps (Datenbanken, hochgeladene Dateien) kommen per Restore aus dem Backup zurück, mit eigenen Schritten je App.
- Die Images müssen noch verfügbar sein. Neu ausrollen klappt nur, solange die Version, die im Repo steht, noch beim Anbieter des Images zu haben ist.
- Nicht alles steckt im Repo. Die Grundeinrichtung der Hosts (statische Konfiguration), der WireGuard-Tunnel, die VMs bei Netcup und auf Proxmox und die Managed Services werden anders verwaltet und müssen zuerst stehen.
Wie ein Host komplett neu aufgebaut wird, steht in Host neu aufbauen; wie Backups funktionieren, in Backup.
Wo wir es nicht machen¶
Nicht alles verwalten wir per Code. Das sind die Gründe dafür:
Es gibt kein Werkzeug dafür. Für das Webhosting bei hosting.de und für Mailjet gibt es kein Werkzeug wie Terraform, das die Einstellungen aus Dateien setzt. hosting.de hat zwar eine vollständige API, aber ein eigenes Werkzeug dafür zu bauen und zu pflegen, lohnt sich für uns nicht. Wir verwalten sie über die Web-Oberfläche.
Es gibt nur Werkzeuge von Dritten. Für Netcup und Proxmox gibt es nur Terraform-Provider, die nicht vom Hersteller stammen. Wir setzen nur offizielle Provider ein (siehe Grundsätze) und verwalten beide über die Web-Oberfläche.
Es lohnt sich nicht. Die Domain-Registrierung ändert sich so gut wie nie; der Aufwand, sie per Code zu verwalten, stünde in keinem Verhältnis.
Es ändert sich laufend. Wer in welchen Gruppen ist, ändert sich ständig, etwa wenn jemand neu dazukommt oder eine Aufgabe im Verein übernimmt. Diese Zuordnungen verwalten wir deshalb nur in Authentik selbst.
Mehr dazu in Authentik.
Was genau wie verwaltet wird, zeigt die Übersicht Was wird wo verwaltet.
Beispiel aus dem Repo¶
In syslet/werner/stack-hedgedoc.cue steht ganz oben die Version von HedgeDoc als Tag in image: hedgedoc: tag:.
Wer dort eine neue Version einträgt und ausrollt, bekommt im plan angezeigt, dass der Container mit dem neuen Image neu erzeugt wird; apply führt das aus.
In desec/desec_garage_lab_de.cue stehen alle DNS-Einträge der Domain garage-lab.de.
Wer dort einen Eintrag ergänzt oder ändert, sieht ihn im plan als Änderung; apply überträgt ihn zu deSEC.
Weiterlesen¶
- Git-Workflow: wie Änderungen ins Repo und auf die Server kommen
- Was man von Hand darf: was auf dem Server erlaubt ist und was nicht
- Änderung ausrollen: die Schritte für eine Änderung
- plan zeigt unerwartete Änderungen: wenn plan mehr zeigt als die eigene Änderung
- Why syslet in der syslet-Doku