🚀 Platform Engineer Lektion 15/50 ~8 Min. Fortgeschritten

Golden Paths designen und versionieren

Paved Roads als versionierte Produkte: Lifecycle, Deprecation, Migration.

📝 Meine Notizen

Lernziele

Nach dieser Lektion kannst du erklären, warum Golden Paths einen Lifecycle wie ein Software-Produkt brauchen: semantische Versionierung, Deprecation-Fenster und Migrationspfade. Du kennst den Unterschied zwischen Scaffolding-Zeit und Laufzeit-Updates, weißt, warum „Tag 2 nach dem Template” das eigentlich schwere Problem ist, und kannst eine Deprecation-Policy skizzieren, die Teams mitnimmt statt überrollt.

Das Problem: Das Template altert, die 80 Services bleiben

In Lektion 14 hast du gesehen, wie ein Scaffolder-Template in fünf Minuten einen neuen Service erzeugt. Spul ein Jahr vor: 80 Services sind aus diesem Template entstanden. Jetzt stellt sich heraus, dass die Basis-Image-Wahl im Dockerfile eine Sicherheitslücke hat, das CI-Workflow-File ein veraltetes Action-Format nutzt und die Plattform von Ingress auf Gateway API umstellt.

Das Template zu fixen ist trivial — es hilft aber nur den Services, die ab jetzt entstehen. Die 80 existierenden Services tragen eine Kopie des alten Stands. Scaffolding ist Copy-Paste mit gutem Marketing: Der Moment des git init trennt das Template vom Service, danach driften beide auseinander. Genau deshalb ist die Kernfrage dieser Lektion nicht „Wie baue ich einen Golden Path?”, sondern: Wie betreibe ich ihn über Jahre?

Golden Paths sind Produkte: Versionierung als Vertrag

Die Antwort beginnt mit einer Haltung aus Lektion 2 (Platform as a Product): Ein Golden Path ist ein Produkt mit Nutzern, und Produkte brauchen Releases. Konkret heißt das:

Semantische Versionierung für Templates. Ein Template bekommt eine Version, und die Semantik ist die übliche: Patch für Fixes, die niemanden betreffen, Minor für neue optionale Fähigkeiten, Major für Änderungen, die von Service-Teams Arbeit verlangen — etwa ein neues Pflichtfeld, ein gewechseltes CI-System oder eine andere Verzeichnisstruktur. Das zwingt dich, bei jeder Änderung zu beantworten: Was bedeutet das für bestehende Nutzer?

Ein Changelog, das Menschen lesen. Nicht der Git-Log, sondern: Was ändert sich, warum, was musst du tun. Bei einem Major-Release gehört eine Migrationsanleitung dazu — im Idealfall ein Skript.

Provenance-Tracking. Du musst wissen, welcher Service aus welcher Template-Version entstanden ist. Praktisch löst man das mit einer Annotation in der catalog-info.yaml oder einer Marker-Datei im Repo, die der Scaffolder beim Erzeugen hineinschreibt. Ohne diese Information kannst du später weder gezielt migrieren noch messen, wie viele Services auf einem verwundbaren Stand sind — und genau diese Frage stellt dir das Security-Team irgendwann.

Die Architektur-Entscheidung: Was kopierst du, was referenzierst du?

Der wirksamste Hebel gegen Drift ist, die Kopie klein zu halten. Zerlege den Golden Path in zwei Schichten:

Referenzierte Bausteine — alles, was der Service zur Laufzeit oder Buildzeit nachlädt und was du daher zentral updaten kannst: ein gemeinsames Helm-Chart der Plattform (das Service-Repo enthält nur Values), wiederverwendbare CI-Workflows (in GitHub Actions: workflow_call aus einem zentralen Repo, versioniert über Tags), Basis-Images, gemeinsame Bibliotheken. Hebst du hier die Version an, folgen alle Services kontrolliert über ihre Versions-Pins — ohne dass jemand 80 Repos anfasst.

Kopierte Bausteine — was wirklich in den Service gehört, weil es service-spezifisch wird: der Anwendungs-Skeleton, die README, die Values-Datei. Diese Schicht driftet zwangsläufig, also halte sie minimal.

Die Faustregel: Je dünner die Kopie, desto billiger der Lifecycle. Ein Template, das 40 Dateien kopiert, erzeugt 40 Dateien Drift pro Service. Ein Template, das einen dünnen Skeleton kopiert und den Rest auf versionierte, zentrale Bausteine zeigt, verlagert Updates dorthin, wo ein einzelnes Team sie ausführen kann.

Für die verbleibende Kopie gibt es Drift-Werkzeuge: Tools wie Renovate halten Versions-Pins (Images, Actions, Chart-Versionen) in allen Repos per automatischem PR aktuell. Für strukturelle Änderungen bleibt der Weg über generierte Pull Requests — ein Skript, das die Änderung in alle betroffenen Repos schreibt und PRs öffnet, die die Teams reviewen und mergen. Aufwendig, aber ehrlich: Die Teams behalten die Kontrolle über ihr Repo.

Deprecation: das Auslaufen organisieren

Irgendwann existieren v1, v2 und v3 eines Pfads parallel — und jede unterstützte Version kostet Support, Doku und Testaufwand. Ohne explizites Auslaufen sammelst du Versionen wie ein Museum. Eine belastbare Deprecation-Policy hat vier Elemente:

  1. Status pro Version: active (empfohlen), maintained (Fixes, keine Features), deprecated (Abkündigung mit Datum), retired (keine Unterstützung). Dieser Status gehört sichtbar ins Portal, nicht in ein verstecktes Wiki.
  2. Ein angemessenes Zeitfenster zwischen Deprecation und Retirement — lang genug, dass Teams die Migration einplanen können; ein Quartal ist eine übliche Untergrenze für Pfade mit vielen Nutzern.
  3. Ein Migrationspfad mit Gefälle: Anleitung ist Minimum, Skript ist besser, automatisch generierter PR ist am besten. Die Erfahrung ist eindeutig: Migrationsquoten korrelieren direkt damit, wie wenig Arbeit beim Team landet.
  4. Eskalation mit Augenmaß: Erst Kommunikation, dann Erinnerung mit Daten („euer Service läuft auf v1 mit bekannter CVE”), zuletzt — und nur mit Management-Rückendeckung — ein hartes Datum. Wer mit dem harten Datum beginnt, verbrennt das Vertrauen, von dem die Plattform lebt.

Praxis: Versionierung in ein Template einbauen

Nimm ein Scaffolder-Template (das Demo-Template aus Lektion 14 reicht) und rüste den Lifecycle nach:

  1. Version sichtbar machen: Ergänze in der Template-Definition unter metadata ein Label wie template-version: "2.0.0" und gib es als Beschreibungstext im Formular aus.
  2. Provenance stempeln: Erweitere den Skeleton so, dass die erzeugte catalog-info.yaml eine Annotation acme.io/template-version: 2.0.0 enthält (im Skeleton als statischer Wert der aktuellen Version).
  3. Inventar bauen: Schreibe eine Abfrage, die alle Components nach dieser Annotation gruppiert — über die Backstage-Catalog-API oder simpel per Skript über alle Repos:
# Welche Repos wurden aus welcher Template-Version erzeugt?
for repo in $(gh repo list acme --limit 200 --json name -q '.[].name'); do
  v=$(gh api "repos/acme/$repo/contents/catalog-info.yaml" \
      -q '.content' 2>/dev/null | base64 -d | grep 'template-version' || true)
  echo "$repo: ${v:-unbekannt}"
done
  1. Deprecation-Notiz formulieren: Schreibe die Ankündigung für ein fiktives v1-Retirement — mit Datum, Begründung und Migrationsschritten. Diese Übung ist unbequemer als jede YAML-Änderung, und genau deshalb wertvoll.

Typische Stolperfallen

„Das Template ist gefixt” mit „das Problem ist gelöst” verwechseln: Der Fix erreicht nur neue Services. Ohne Provenance-Tracking und Rollout-Plan bleibt der Bestand verwundbar — und der Bestand ist fast immer größer als der Zustrom.

Alles ins Template kopieren: Jede kopierte Datei ist zukünftiger Drift. CI-Logik, Deployment-Manifeste und Basis-Konfiguration gehören in referenzierte, zentral versionierte Bausteine.

Versionen horten: Fünf parallel unterstützte Major-Versionen bedeuten fünffachen Pflegeaufwand. Wer nie abkündigt, betreibt bald mehr Vergangenheit als Gegenwart.

Migration per Ansage statt per Hilfe: Eine E-Mail „bitte bis Q3 migrieren” ohne Skript oder PR erzeugt Widerstand und Eskalationen. Plattform-Arbeit heißt: Die Migration so billig machen, dass Nicht-Migrieren die unattraktivere Option ist.

Interview-Vorbereitung

Die Standardfrage lautet meist „Wie hältst du Golden Paths aktuell?”. Starke Antwortstruktur: Problem (Scaffolding ist Kopie, Kopien driften, der Bestand wächst schneller als er sich erneuert) → Designprinzip (dünne Kopie, dicke referenzierte Schicht mit zentraler Versionierung) → Lifecycle (SemVer, Changelog, Provenance-Annotation, Statusmodell) → Migration (automatisierte PRs vor Anleitung vor Ansage, Deprecation mit Fenster und Eskalationspfad).

Wahrscheinliche Follow-ups:

  • „Woher weißt du, welche Services betroffen sind?” — Template-Version wird beim Scaffolding als Annotation/Marker eingebrannt; ein Inventar-Job aggregiert das.
  • „Wie updatest du 80 Services gleichzeitig?” — gar nicht „gleichzeitig”: zentrale Bausteine per Versions-Bump, Repo-Inhalte per generierten PRs plus Renovate für Pins; Teams mergen selbst.
  • „Wann ist ein Breaking Change im Template gerechtfertigt?” — wenn Sicherheits- oder Plattform-Anforderungen es erzwingen und der Migrationspfad bereitsteht; Major-Version plus Deprecation-Fenster, nie still.
  • „Was machst du mit Teams, die nicht migrieren?” — Gründe verstehen (oft fehlt Kapazität), Migration weiter verbilligen, Risiko transparent machen, Eskalation als letztes Mittel mit klarem Datum.

Zusammenfassung

Golden Paths sind nach dem Scaffolding nicht fertig, sondern geboren: Ab dann beginnt der Lifecycle. Die Architektur-Entscheidung „kopieren vs. referenzieren” bestimmt, wie teuer jedes Update wird; semantische Versionierung, Provenance-Tracking und ein Statusmodell machen den Bestand steuerbar; Deprecation mit echtem Migrationspfad hält die Zahl gepflegter Versionen klein, ohne Teams zu überfahren.

Templates erzeugen Services — aber Services brauchen Infrastruktur: Datenbanken, Buckets, Queues. Wie Teams die per Self-Service bekommen, ohne dass das Platform-Team zum Ticket-Backoffice wird, ist Thema der nächsten Lektion.