In einer klassischen Pipeline baut CI den Code und schiebt das Ergebnis dann mit kubectl apply oder helm upgrade in den Cluster. Das funktioniert, aber die Pipeline braucht Admin-Zugangsdaten für jeden Cluster, niemand kann sicher sagen, was läuft, ohne den Cluster zu fragen, und ein von Hand bearbeitetes Deployment weicht still von dem ab, was im Repo steht.
GitOps dreht die Richtung um. Git hält den Sollzustand, und ein Agent im Cluster zieht ihn fortlaufend und bringt den Cluster in Übereinstimmung. Dieser Artikel erklärt die Prinzipien, den Zwei-Repo-Workflow, den die meisten Teams nutzen, wie Promotion und Rollback funktionieren, und zeichnet den ganzen Ablauf.
Die vier Prinzipien
Das OpenGitOps-Projekt der CNCF definiert GitOps mit vier Prinzipien:
- Deklarativ: Der Sollzustand des Systems wird deklarativ ausgedrückt.
- Versioniert und unveränderlich: Dieser Zustand wird so gespeichert, dass eine vollständige, unveränderliche Versionshistorie erhalten bleibt, was in der Praxis Git bedeutet.
- Automatisch gezogen: Software-Agenten ziehen den Sollzustand aus der Quelle.
- Kontinuierlich abgeglichen: Agenten vergleichen ständig den Istzustand mit dem Sollzustand und korrigieren die Differenz.
Der dritte Punkt trennt GitOps von „Deployment aus einer Pipeline, die Git liest“. Der Cluster zieht; nichts von außen schiebt in ihn hinein.
Zwei Repos: Code und Config
Die meisten Teams trennen zwei Arten von Änderungen:
- Das App-Repo enthält den Quellcode. CI baut ihn, führt Tests aus, scannt ihn und pusht einen unveränderlichen Image-Tag in eine Registry.
- Das Config-Repo enthält die Kubernetes-Manifeste, Helm-Values oder Kustomize-Overlays für jede Umgebung. Es beschreibt, was wo laufen soll, einschließlich der Image-Tags.
Die Verbindung zwischen beiden ist eine kleine, explizite Änderung: CI oder ein Image-Automation-Tool öffnet einen Pull Request im Config-Repo, der den Image-Tag für Staging erhöht. Dieser Pull Request ist der Deployment-Antrag, mit Review und Audit-Trail.
Der Controller im Cluster
Argo CD und Flux sind die beiden verbreiteten GitOps-Controller. Beide laufen im Cluster, pollen das Config-Repo oder empfangen dessen Webhooks, rendern die Manifeste, vergleichen sie mit den Live-Objekten und wenden die Differenz an.
Ihre Abgleichseinstellungen entscheiden, wie streng das System ist:
- Automatischer Sync: neue Commits anwenden, ohne dass jemand einen Knopf drückt.
- Pruning: Objekte löschen, die aus Git entfernt wurden.
- Self-Heal: direkt im Cluster vorgenommene Änderungen rückgängig machen. In den Optionen für den automatischen Sync von Argo CD ist Self-Heal ein eigener Schalter neben Auto-Sync.
Self-Heal ist die Einstellung, die Git zur tatsächlichen Quelle der Wahrheit macht. Ohne sie wird ein kubectl edit um 3 Uhr nachts dauerhaft und unsichtbar.
Promotion und Rollback
Umgebungen sind Ordner, Overlays oder Dateien im Config-Repo. Promotion bedeutet, eine Version von einer zur nächsten zu kopieren:
- Der Pull Request erhöht den Staging-Tag; Staging aktualisiert sich wenige Minuten nach dem Merge.
- Tests und Prüfungen laufen gegen Staging.
- Ein zweiter Pull Request hebt Produktion auf denselben Tag. Ihn zu mergen ist das Produktions-Deployment.
Rollback ist ein git revert dieses Merges. Der Controller sieht den alten Tag und wendet ihn an. Weil die gesamte Historie in Git liegt, hat die Frage „Was lief letzten Dienstag um 14:00 Uhr in Produktion?“ eine exakte Antwort.
Wer den Pull Request öffnet
Es gibt zwei gängige Wege, ein neues Image mit dem Config-Repo zu verbinden:
- CI öffnet ihn. Der letzte Pipeline-Schritt klont das Config-Repo, ändert eine Zeile, committet auf einen Branch und öffnet einen Pull Request. Das ist explizit und leicht zu debuggen, und die Pipeline braucht nur ein Token für dieses eine Repository.
- Ein Image-Automation-Tool committet ihn. Die Image-Automation-Controller von Flux und das Projekt Argo CD Image Updater können eine Registry beobachten, neue Tags auswählen, die zu einer Policy passen, und sie nach Git zurückschreiben. Nützlich für Staging-Umgebungen, die immer den neuesten Build ausführen sollen.
Viele Teams kombinieren beides: Automatisierung hält Staging aktuell, während Produktionsänderungen immer als geprüfter Pull Request von einer Person oder einem Release-Job kommen. Wofür du dich auch entscheidest, schreib es ins Diagramm, denn „Wie kommt eine neue Version hierher?“ ist die erste Frage, die jeder zu einem GitOps-Setup stellt.
Ein Release, von Anfang bis Ende
Folge Version 1.8.0 eines Shop-Services vom Commit bis in die Produktion:
- Ein Entwickler merget eine Änderung ins App-Repo. CI führt Tests aus, baut das Image, scannt es und pusht
shop:1.8.0in die Registry. - CI öffnet im Config-Repo einen Pull Request, der den Staging-Tag von 1.7.3 auf 1.8.0 ändert. Ein Reviewer gibt ihn frei und merget ihn.
- Innerhalb von ein, zwei Minuten bemerkt der Controller den neuen Commit, rendert die Staging-Manifeste und aktualisiert das Deployment. Kubernetes rollt neue Pods aus, die das Image aus der Registry ziehen.
- Die Smoke-Tests auf Staging sind grün. Die Release-Verantwortliche öffnet einen zweiten Pull Request, der Produktion auf 1.8.0 setzt.
- Nach diesem Merge rollt Produktion auf dieselbe Weise aus. Steigen die Fehlerraten, bringt ein Revert des Merge-Commits 1.7.3 zurück.
An keiner Stelle brauchte etwas außerhalb des Clusters Cluster-Zugangsdaten, und jeder Schritt hat einen Commit hinterlassen.
Secrets
Secrets im Klartext gehören nicht in Git. Gängige Ansätze:
- Verschlüsselt in Git, mit Tools wie Sealed Secrets oder SOPS, entschlüsselt nur im Cluster.
- Referenzen in Git, Werte anderswo, mit einem Operator wie External Secrets, der aus einem Secrets-Manager liest.
So oder so bleibt das Config-Repo reviewbar, und die Secret-Werte tauchen nie in einem Diff auf.
Das Architekturdiagramm
Diagramminhalt
- Developer
- App repo: code
- CI: build, test, scan
- Container registry
- Config repo: desired state
- Kubernetes cluster
- GitOps controller
- staging
- shop v1.8.0
- production
- shop v1.7.3
- push
- trigger
- image 1.8.0
- PR: bump staging tag
- pull every few minutes
- apply
- nodes pull images
So liest du es:
- Obere Reihe, der Build: Ein Entwickler pusht ins App-Repo, CI baut und testet Image 1.8.0 und pusht es in die Registry.
- Mitte: CI öffnet einen Pull Request, der den Staging-Tag im Config-Repo erhöht. Das ist die einzige Stelle, an der CI das Deployment berührt.
- Unten, der Cluster: Der GitOps-Controller zieht das Config-Repo (gestrichelt) und wendet es auf den Staging-Namespace an, der jetzt 1.8.0 ausführt, und auf Produktion, die noch 1.7.3 ausführt, bis ihr eigener Pull Request gemergt ist. Nodes ziehen Images aus der Registry (gepunktet).
- Der Markdown-Block nennt die Workflow-Regeln: Promotion per Pull Request, Rollback per Revert, Abweichungen per Self-Heal zurückgesetzt.
Was sich für das Team ändert
- CI verliert die Cluster-Zugangsdaten. Der Cluster greift nach außen; die Pipeline braucht nur Schreibzugriff auf ein Repo.
- Reviews decken Deployments ab. Wer was wann und warum deployt hat, steht in der Pull-Request-Historie.
- Abweichungen werden sichtbar. Der Controller zeigt nicht synchrone Ressourcen an, statt sie zu verstecken.
- Debugging verlagert sich. „Warum wurde das nicht deployt?“ beantworten Sync-Status und Events des Controllers, also mach sie für die Leute sichtbar, die mergen.
Was in ein GitOps-Diagramm gehört
- Beide Repos, und der Pull Request, der sie verbindet.
- Die Zugrichtung, vom Controller zum Config-Repo, nicht von der Pipeline zum Cluster.
- Jede Umgebung mit der Version, die sie ausführt, damit Promotion sichtbar ist.
- Sync-Einstellungen: Auto-Sync, Prune, Self-Heal.
Das Diagramm der Deployment-Strategien zeigt, wie das Rollout selbst Canary oder Blue-Green sein kann, das CI/CD-Pipeline-Diagramm behandelt die Build-Stufen im Detail, das Kubernetes-Architekturdiagramm zeigt den Cluster selbst, und der Artikel von Kubernetes-YAML zum Diagramm zeigt, wie man die Manifeste des Config-Repos in ein Bild verwandelt.
In Archboard nachbauen
- Melde dich mit Google oder GitHub an und leg ein Diagramm an.
- Füge eine Person aus dem C4-Modell-Pack hinzu, zwei Code-Repository-Nodes und eine CI/CD-Pipeline aus dem DevOps-Pack sowie eine Container-Registry aus dem Docker-Pack.
- Füge aus dem Basis-Pack einen Rahmen für den Cluster hinzu, mit einem Container für den GitOps-Controller.
- Füge aus dem Kubernetes-Pack zwei Namespace-Nodes hinzu, mit je einem Deployment, beschriftet mit der Version, die es ausführt.
- Zeichne das Ziehen als gestrichelte Kante vom Controller zum Config-Repo und füge einen Markdown-Block aus dem Basis-Pack mit den Workflow-Regeln hinzu.
Das Beispiel nutzt 12 Diagramm-Nodes und bleibt damit im Free-Plan.
FAQ
Was ist der Unterschied zwischen GitOps und CI/CD? CI/CD baut, testet und liefert Software aus. GitOps ist eine Art, den Auslieferungsteil zu erledigen: Der Sollzustand liegt in Git, und ein Agent in der Zielumgebung zieht und gleicht ihn ab, statt dass eine Pipeline Änderungen hineinschiebt.
Sollte ich Argo CD oder Flux nutzen? Beide setzen dasselbe Modell um. Argo CD hat eine umfangreiche Weboberfläche und anwendungszentrierte Ansichten; Flux ist ein Satz kombinierbarer Controller, die viele Teams komplett über Git und die CLI steuern.
Brauche ich getrennte App- und Config-Repositories? Das ist eine verbreitete Konvention, keine Regel. Getrennte Repos halten die Deployment-Historie sauber und lassen die Konfiguration sich ändern, ohne den Code neu zu bauen.
Wie mache ich mit GitOps ein Rollback? Revertiere den Commit, der die Version im Config-Repo geändert hat. Der Controller wendet den vorherigen Zustand an.
Wie werden Secrets bei GitOps behandelt? Speichere sie verschlüsselt in Git, oder speichere Referenzen in Git und lass einen Operator die Werte im Cluster aus einem Secrets-Manager holen.