Im Zentrum von GitOps steht ein spezielles Code-Repository, ein sogenanntes Umgebungs-Repository, welches ein Dependency-Manifest für alle Anwendungen und der aktuell in der Zielumgebung gewünschten Infrastruktur enthält. Ein Prozess in der Zielumgebung, Operator genannt, überwacht die Umgebung und passt diese an den beschriebenen Zustand im Repository an. Wenn eine neue Anwendung deployt oder eine bestehende Anwendung aktualisiert werden soll, muss nur das Umgebungs-Repository aktualisiert werden – alles andere erledigt der Operator.
Komponenten
Umgebungs-Repository
Einer der Kerngedanken von GitOps ist es, Entwicklungsteams die Möglichkeit zu geben, die ihnen vertrauten Werkzeuge für den Betrieb der Infrastruktur zu nutzen. Eine deklarative Beschreibung der Anwendungen und Infrastruktur (z.B. Message Broker, Service Mesh, Monitoring-Tool) wird daher zentral, als “Single Source of Truth”, in einem Code-Repository gesammelt. Etabliert hat sich die Verwendung von Git, daher auch der Name GitOps. Im Prinzip kann aber jedes Versionskontrollsystem verwendet werden.
Zielumgebung
In Frage kommt jede Betriebsplattform, die sich als Environments-as-Code beschreiben lässt. Allerdings erleichtert die Verwendung von Kubernetes als Zielumgebung die Auswahl eines GitOps Operators. Selbstgebaute Operatoren können hier natürlich Abhilfe schaffen. Üblicherweise bilden unterschiedliche Cluster die verschiedenen Umgebungen (Dev, Staging, Prod, etc.) ab. Allerdings gibt GitOps, als Betriebskonzept, die Gestaltung der Umgebungsstruktur nicht vor.
Deployment Operator
Die Wahl eines GitOps Operators hängt maßgeblich von der Zielumgebung ab. Populäre Operatoren für Kubernetes sind Flux und Argo CD. Es gibt aber auch CI/CD Systeme, welche die Philosophie von GitOps auch auf Continuous Integration übertragen und somit nicht nur den Deployment-Prozess in die Zielumgebung heben, sondern auch das Testen von Anwendungen. Zu diesen GitOps CI/CD Systemen gehören Tekton und Jenkins-X.
Continuous Integration Pipeline
GitOps Operatoren übernehmen das Deployment, aber nicht immer das Testen und Bauen von Anwendungen. Da der Operator die gesamte Arbeit des Deployments von Anwendungen übernimmt, wird die ursprüngliche CI/CD-Pipeline des Build-Servers zu einer reinen CI-Pipeline. Zusätzlich bietet es sich an, eine CI-Pipeline für das Umgebungs-Repository zu nutzen, in der Smoke- und Integration-Tests der gesamten Umgebung ausführt werden. Das Kubestack-Framework für Kubernetes, erleichtert diesen CI-Prozess für die Infrastruktur.
GitOps Workflow
Code-Repositories sind zentrale Elemente bei einem GitOps Deployment-Prozess. Es gibt zwei Arten von Repositories: Anwendungs-Repository und Umgebungs-Repository. Anwendungs-Repositories enthalten den Code der Anwendung und ggf. die Manifeste für das Deployment der Anwendung. Das Umgebungs-Repository enthält ein Manifest, welches die aktuell gewünschte Infrastruktur der Zielumgebung durch Dependencies beschreibt. Solch ein Dependency-Manifest wird, z.B. bei der Verwendung von Helm, ‘Umbrella-Chart’ genannt. Eine andere Option wäre, die Deployment-Manifeste der Anwendungen direkt im Umgebungs-Repository zu verwalten, sodass es auch keine Deployment-Manifeste in den Anwendungs-Repositories selbst gibt.
Es gibt zwei Strategien, um Deployments umzusetzen: Push-basierte und Pull-basierte Deployments. Der Unterschied zwischen den beiden Deployment-Strategien besteht darin, wie Deployments angestoßen und von wo aus sie durchgeführt werden.
Push-basierte Deployments
Die Push-basierte Deployment-Strategie kann mit populären CI/CD-Tools wie beispielsweise Jenkins, CircleCI oder Travis CI umgesetzt werden. Immer wenn der Anwendungscode aktualisiert wird, wird die CI-Pipeline ausgelöst, Tests ausgeführt und die Container-Images erstellt. Anschließend wird das Umgebungs-Repository mit der neuen Anwendungsversion über einen automatisierten Pull-Request aktualisiert. Ob diese Pull-Requests nach einem erfolgreichen CI-Durchlauf für die Infrastrukturkonfiguration automatisch akzeptiert werden oder einer manuellen Prüfung unterliegen, macht den Unterschied zwischen Continuous Deployment und Continuous Delivery aus. Gibt es keinen manuellen Abnahmeprozess zwischen einer Codeänderung und deren Auslieferung in das Produktivsystem, spricht man von Continuous Deployment. Beim Continuous Delivery reicht die Befähigung aus, idealerweise mit einem Knopfdruck, ein automatisches Deployment manuell anzustoßen. Änderungen am Umgebungs-Repository lösen dann die Deployment-Pipeline aus und die Zielumgebung wird aus dem CI/CD System heraus aktualisiert. Bei diesem Ansatz ist es unerlässlich, Autorisierungsinformationen für die Zielumgebung der CI/CD Pipeline zur Verfügung zu stellen. Die CI/CD Pipeline hat also den Gottmodus aktiviert und stellt ein Sicherheitsrisiko dar. Ein weiterer wichtiger Aspekt bei der Verwendung dieses Ansatzes ist, dass die Deployment-Pipeline nur ausgelöst wird, wenn sich das Umgebungs-Repository ändert. Das führt dazu, dass manuelle Änderungen an der Zielumgebung so lange aktiv sein können, bis ein neues automatisiertes Deployment durchgeführt wird.
Pull-basierte Deployments
Die Pull-basierte Deployment-Strategie verwendet die gleichen Konzepte wie die Push-basierte Variante, mit dem Unterschied, dass das Deployment nicht im CI/CD System initiiert wird. Beim Pull-basierten Deployment-Ansatz wird ein Operator eingesetzt, der kontinuierlich den Soll-Zustand im Umgebungs-Repository mit dem Ist-Zustand in der eingesetzten Infrastruktur vergleicht (siehe Abb. 1 [1]). Immer wenn Unterschiede festgestellt werden, aktualisiert der Operator die Infrastruktur, um sie an die Beschreibung im Umgebungs-Repository anzupassen. Zusätzlich kann eine Image-Registry überwacht werden, um neue Versionen von Images zu finden, die deployt werden sollen. Dennoch wird auch dann noch, das entsprechende Deployment-Manifest im Umgebungs-Repository angepasst, sodass jede Änderung immer über dieses Repository läuft. Der Operator sollte außerdem immer in der gleichen Zielumgebung leben, wie die zu verteilenden Anwendungen. Dies verhindert den Gottmodus, wie er beim Push-basierten Ansatz zu beobachten ist, da die Autorisierungsinformationen innerhalb der Zielumgebung sicherer sind. Die Pull-basierte Deployment-Strategie sollte als sicherere und damit bessere Implementierung von GitOps bevorzugt werden.
Vorteile
GitOps kann zwar dazu verwendet werden, um eine Art “NoOps” zu implementieren, aber es macht nicht automatisch alle Betriebsaufgaben überflüssig. Normalerweise verwaltet ein Plattform-Team einen Teil der Infrastruktur zentral, wie die Netzwerkkonfiguration oder den verwendeten Cluster. Eine dezentrale Verwaltung dieser Konfigurationen durch Entwicklungsteams ist eher ungeeignet. GitOps macht ein Plattform-Team also nicht überflüssig, sondern erleichtert den Deployment-Prozess für Entwicklungsteams.
Schnellere und häufigere Deployments
Wahrscheinlich verspricht jede Continuous Deployment Technologie schnellere und häufigere Deployments zu ermöglichen. Die Einzigartigkeit von GitOps besteht darin, dass Entwicklungsteams für das Deployment von Anwendungen nicht die Tools wechseln müssen.
Einfache und schnelle Fehlerbehebung
Ein Rollback ist so einfach wie das Ausführen eines git revert
. Es bleibt nur noch das Beobachten der automatischen Wiederherstellung der Zielumgebung.
Sollte die Produktionsumgebung einen schwerwiegenden Ausfall erleiden, kann mithilfe des Umgebungs-Repositories derselbe Stand schnell reproduziert werden.
Sichere Deployments
Der GitOps Prozess erfordert Pull-Requests für jedes Deployment und erlaubt idealerweise keine manuellen Änderungen an der Zielumgebung. Außerdem werden Anwendungen vollständig aus der Zielumgebung heraus verwaltet, sodass GitOps-Tools keinen externen Zugriff benötigen.
Sich selbst dokumentierende Deployments
Gute Commit-Beschreibungen und Pull-Requests erzeugen genügend Dokumentation, um Deployments nachzuvollziehen. Da idealerweise keine manuellen Änderungen an der Zielumgebung möglich sind, werden so alle Umgebungsänderungen in Code gegossen und sind damit nachvollziehbar.
Schnelleres Onboarding
Entwicklungsteams können mit bereits bekannten Werkzeugen Anwendungen deployen, ohne individuelle Deployment-Prozesse lernen zu müssen. Das macht Deployments nicht nur schneller, sondern erfordert auch weniger kognitive Kapazität, sodass mehr davon in den Anwendungscode investiert werden kann.
Literatur
-
Beetz, Florian, Anja Kammer, and Simon Harrer. 2019. “Gitops – Cloud–native Continuous Deployment”. https://gitops.tech ↩