GitOps baut auf Infrastructure-as-Code auf und will über
einen deklarativen Ansatz Infrastrukturen und Anwendungen verwalten und mit Git
kontrollieren. Ziele dieser Idee sind automatisierte Abläufe, Zeitersparnis und
eine bessere sowie sicherere Zusammenarbeit einzelner Teams an den Repositories.
Voraussetzungen für GitOps und dessen Umsetzung mit der Open-Source-Software
Argo CD liefert unser Workshop.
Im Cloudzeitalter lautet die Devise, dass IT-Organisationen
manuelle Arbeitsschritte möglichst hinter sich lassen und zu automatisierten
Prozessen gelangen. Dies gilt für das Bereitstellen von einzelnen Ressourcen bis
hin zum vollautomatisierten Bauen und Ausrollen von Anwendungen. Das aktuelle
Ökosystem bietet dazu bereit Tools wie Ansible, das einfache automatische
Infrastruktur-Deployments erlaubt. Im Softwareumfeld findet sich das Pendant in
Continuous Integration/Continuous Deployment (CI/ CD) mit Werkzeugen wie
beispielsweise Jenkins. Darüber hinaus gibt es eine Vielzahl kommerzieller
Anwednungen im Bereich Cloudmanagement, zum Beispiel VMware Aria Automation
(vorher vRealize Automation) oder Morpheus Data.
Ein relativ neuer Ansatz in diesem Gebiet, der jüngst viel an
Fahrt aufgenommen hat, ist GitOps. Dieser schickt sich an, im cloudnativen
Umfeld zum Standard zu werden und lässt sich im Grunde einfach erklären: GitOps
bedient eine codebasierte Infrastruktur, bei der sämtlicher Code in einem
Git-System beheimatet ist und somit als Quellkontrollsystem dient. Git ist
hierbei also die Single-Source-of-Truth. Dies bedeutet, dass sämtliche
Konfigurationsänderungen nicht mehr im Zielsystem direkt, sondern im Git
erfolgen. Mithilfe von Agenten gelangen diese Konfigurationsänderungen
anschließend in das Zielsystem.
Weiterentwicklung von IaC
GitOps ist somit eigentlich kein neuer Ansatz, sondern eine
konsequente Weiterentwicklung von Infrastructure-as-Code (IaC). Insgesamt bilden
fünf Kernprinzipien die Grundlagen von GitOps:
Im Cloudzeitalter lautet die Devise, dass IT-Organisationen
manuelle Arbeitsschritte möglichst hinter sich lassen und zu automatisierten
Prozessen gelangen. Dies gilt für das Bereitstellen von einzelnen Ressourcen bis
hin zum vollautomatisierten Bauen und Ausrollen von Anwendungen. Das aktuelle
Ökosystem bietet dazu bereit Tools wie Ansible, das einfache automatische
Infrastruktur-Deployments erlaubt. Im Softwareumfeld findet sich das Pendant in
Continuous Integration/Continuous Deployment (CI/ CD) mit Werkzeugen wie
beispielsweise Jenkins. Darüber hinaus gibt es eine Vielzahl kommerzieller
Anwednungen im Bereich Cloudmanagement, zum Beispiel VMware Aria Automation
(vorher vRealize Automation) oder Morpheus Data.
Ein relativ neuer Ansatz in diesem Gebiet, der jüngst viel an
Fahrt aufgenommen hat, ist GitOps. Dieser schickt sich an, im cloudnativen
Umfeld zum Standard zu werden und lässt sich im Grunde einfach erklären: GitOps
bedient eine codebasierte Infrastruktur, bei der sämtlicher Code in einem
Git-System beheimatet ist und somit als Quellkontrollsystem dient. Git ist
hierbei also die Single-Source-of-Truth. Dies bedeutet, dass sämtliche
Konfigurationsänderungen nicht mehr im Zielsystem direkt, sondern im Git
erfolgen. Mithilfe von Agenten gelangen diese Konfigurationsänderungen
anschließend in das Zielsystem.
Weiterentwicklung von IaC
GitOps ist somit eigentlich kein neuer Ansatz, sondern eine
konsequente Weiterentwicklung von Infrastructure-as-Code (IaC). Insgesamt bilden
fünf Kernprinzipien die Grundlagen von GitOps:
1. Deklarative Konfiguration: Alle Ressourcen, die ein
GitOps-Prozess verwaltet, liegen vollständig deklarativ vor.
2. Es ist eine versionskontrollierte und unveränderliche
Speicherung notwendig. Die deklarativen Beschreibungen sind in einem Repository
gespeichert und erreichen damit Unveränderlichkeit, Versionierung und
Versionsgeschichte. Als ideales System, das dies alles unterstützt, kommt in der
Regel Git zum Einsatz.
3. Die Bereitstellung muss automatisiert erfolgen und darf
keine manuellen Vorgänge enthalten.
4. Das Updaten der Umgebung geschieht mit einem Reconciler.
Dies ist ein Agent, der das Zielsystem mit dem in Git gespeicherten Inhalt
vergleicht. Sind Unterschiede vorhanden, wird das Zielsystem angeglichen. Dies
erfolgt mittels Pull-Prinzip und erfordert, dass ein Agent im Zielsystem
installiert sein muss. In der Praxis wird dieses Kriterium jedoch oftmals nicht
in voller Stringenz ausgelegt und nur darauf geachtet, dass der Abgleich
regelmäßig stattfindet – auch wenn es mittels Push-Prinzip erfolgt.
5. Der Abgleich zwischen dem
Software-Versionsverwaltungssystem und dem Zielsystem basiert nicht auf einem
Bedarf oder Ereignis, sondern fortwährend in einer Schleife.
Zentrale Bedeutung in einem GitOps-Workflow hat der Prozess,
der Änderungen in ein Git-Repository transportiert. Um ein Approval zu
ermöglichen, geschieht eine Änderung in der Regel nicht direkt im Master,
sondern über einen dedizierten Branch, der anschließend als Pull-
beziehungsweise Merge-Request in den Master eingebracht wird. In einem solchen
Workflow erstellt ein Teammitglied im ersten Schritt ein Pull/Merge-Request, um
neue oder aktualisierte Manifeste in den Haupt-Branch des Repositories zu
integrieren. Anschließend wird das Request von einer autorisierten Person
bestätigt oder abgelehnt. Optional lassen sich die Manifeste vorher noch durch
automatisierte Test in einer CI-Pipeline überprüfen. Nach erfolgter Bestätigung
integrieren sich die Änderungen in den Haupt-Branch des Repositories. Diese
Anpassungen wendet ein automatisierter CD-Prozess auf die Umgebung an, sodass
deren Zustand den des GitOps-Repositories widerspiegelt.
IT-Veteranen haben jetzt gewiss schon erkannt, dass GitOps
selbst keine grundlegend neue Funktionalität mit sich bringt. Alle
angesprochenen Funktionen und Abläufe sind auch durch bereits langjährig
etablierte Software darstellbar. Dennoch gibt es gute Gründe für GitOps: Als
Erstes ist die erhöhte Produktivität zu nennen, die sowohl bei der Entwicklung
als auch im Betrieb messbar ist. Dann gestaltet sich die Entwicklung selbst
durch die deklarative Natur des GitOps-Ansatzes einfacher und besser
nachvollziehbar. Zudem erhöht sich durch die Abkehr von manuellen,
fehlerträchtigen Prozessen die Stabilität, die Automatisierung sorgt also für
mehr Verlässlichkeit und die deklarative Natur von GitOps fördert die
Standardisierung. Schließlich ist deklarativer Code einfach les- und prüfbar,
was Vorteile in Sachen Security mit sich bringt.
Tools für GitOps
Die bekanntesten Tools in der GitOps-Welt sind Argo CD [1] und
Flux [2]. Beide ermöglichen ein Coninuous Deployment in Kubernetes-Clustern. Im
weite- ren Verlauf dieses Workshops arbeiten wir beispielhaft mit Argo CD. Doch
Git-Ops findet sich auch in anderen namhaften Produkten:
- VMware bietet mit seinen freien Carvel-Tools [3] eine
Möglichkeit, nicht nur Manifeste in Kubernetes zu deployen, sondern ganze
Softwarepakete. Carvel unterstützt dabei das Bauen, Paketieren und Ausrollen von
Anwendungen.
- Der "Kubernetes Helm Operator" [4] bietet GitOps für Helm
Charts.
- Jenkins X [5] als Nachfolger von Jenkins stellt eine
CI/CD-Plattform basierend auf GitOps-Mechanismen bereit.
- Atlantis [6] ermöglicht Pull-Requests mit Terraform.
- GitLab [7] hat in seine DevOps-Plattform ebenfalls
GitOps-Funktionalität eingebaut.
- Anthos Config Management [8] in der Google-Cloud ermöglicht
Richtlinienobjekte in Kubernetes-Clustern nach dem GitOps-Mechanismus.
Push versus Pull
Der GitOps-Push-Ansatz nutzt traditionelle CI/CD-Pipelines, um
die Umgebungen zu aktualisieren. Hierbei startet nach jeder Änderung an dem
Repository eine CD-Pipeline über ein externes Tool wie etwa Jenkins oder
GitLab-CI/CD, die die Änderungen nach dem Push-Prinzip auf die Infrastruktur
anwendet. Im Falle von Kubernetes sind dies das Anwenden von Manifesten zur
Bereitstellung und Aktualisierung von Applikationen.
Ein Vorteil dabei ist die Flexibilität derartiger Pipelines.
Während Pull-Tools in der Regel nur innerhalb spezifischer Umgebungen wie etwa
Kubernetes funktionieren, lassen sich herkömmliche Pipelines für
unterschiedlichste Anwendungsfälle nutzen. Weitere Argumente für den Push-Ansatz
sind Erfahrung und Effizienz: Traditionelle CD-Prozesse haben sich bereits für
eine Vielzahl von Szenarien etabliert, sodass es naheliegt, diese
standardisierten Bereitstellungsprozesse auch für cloudnative Workloads zu
verwenden. Damit können sich IT-Abteilungen auf die Problemlösung konzentrieren,
statt neue Technologien einzuführen und Know-how aufbauen zu müssen.
Beim Pull-Ansatz wird die CD-Pipeline durch einen Agenten
ersetzt, der innerhalb der Umgebung läuft. Dieser überwacht den Status des
Git-Repositories und vergleicht in regelmäßigen Abständen den definierten
Zustand in Git mit dem aktuellen der Umgebung. Erfolgt eine Änderung am
Repository oder der Umgebung, erkennt der Controller die Abweichung zwischen dem
definierten und dem aktuellen Zustand des Clusters und stellt den definierten
Status automatisch her.
Der Pull-Ansatz ermöglicht damit konsistente Umgebungen. Da
sowohl der definierte Zustand in Git als auch der aktuelle des Clusters im Blick
ist, lassen sich alle Änderungen und Abweichungen, die nicht mit der Definition
in Git übereinstimmen, erkennen und korrigieren. Beim Verwenden eines
Push-Ansatzes führt die CI/CD-Pipeline nach einer Änderung am Repository
vordefinierte Befehle zur Bereitstellung oder Aktualisierung von Applikationen
aus, besitzt danach allerdings keine Informationen über den aktuellen Status der
Umgebung. Entsprechende Überwachungsanwendungen sind von jeder Push-Pipeline
zusätzlich zu implementieren.
Des Weiteren minimiert der Pull-Ansatz Sicherheitsrisiken:
Jedes Projekt, das Anwendungen per Push über eine externe CI/CD-Pipeline
bereitstellt, benötigt Zugangsdaten für die Zielumgebung. Diese müssen
konfiguriert und von der externen Pipeline sicher verwaltet und gespeichert
werden. Beim Pull befindet sich der Agent innerhalb der Umgebung und benötigt
daher keine vertraulichen Daten für den Zugriff auf die Infrastruktur.
Das Pull-Konzept eignet sich vor allem für cloudnative
Umgebungen, in denen Anwendungen und Services in Kubernetes-Clustern laufen.
Dementsprechend sind die meisten modernen GitOps-Tools auch speziell für den
Einsatz im Kubernetes-Umfeld konzipiert.
Argo CD für Kubernetes
Im Folgenden demonstrieren wir die praktische Umsetzung von
GitOps am Beispiel Argo CD. Dies ist ein freies Continuous-Delivery-Tool für
Kubernetes, das spezifisch auf deklaratives GitOps ausgerichtet ist. Die
Software wird als Kubernetes-Controller in einem Cluster installiert und
überwacht dort kontinuierlich Ressourcen und vergleicht den aktuellen Status der
Umgebung mit dem des Git-Repositories, in dem sich die deklarativen
Kubernetes-Manifeste befinden. Diese definieren alle Anwendungen und Services,
die auf Kubernetes bereitgestellt werden sollen, und beschreiben somit den
gewünschten Zustand des Clusters.
Die Manifeste wendet Argo CD automatisiert nach dem
Pull-Ansatz auf den Cluster an, bis der aktuelle Status des Clusters mit dem des
Git-Repositories übereinstimmt. Durch die kontinuierliche Überwachung des
Repositories werden Änderungen und Aktualisierungen, die das DevOps-Team im
Repository an den YAML-Dateien vornimmt, von Argo CD erkannt und die Umgebung
wird automatisch aktualisiert, solange bis alle Manifeste mit dem
Kubernetes-Cluster synchronisiert sind.
Der Deployment-Status einer Anwendung in der Argo-CD-GUI.
Manifeste und Secrets verwalten
Bevor wir in die Praxis mit Argo CD einsteigen, sind noch einige Hilfsmittel
notwendig. Für die Verwaltung von Kubernetes-Manifest-Dateien haben sich in den
letzten Jahren ebenfalls Best Practices und Tools herauskristallisiert. In einem
GitOps-Repository befinden sich solche Manifeste im YAML-Format und
spezifizieren den gewünschten Zustand aller bereitzustellenden Objekte. Zur
effizienten Verwaltung der Manifeste eignen sich die Tools Helm [9] und
Kustomize [10].
Helm vereinfacht die Verwaltung von Kubernetes, indem es erlaubt, eine
vollständige Applikation als Paket in einem Helm Chart zu definieren. Ein
solches legt eine Verzeichnisstruktur fest, in der sich mehrere
Kubernetes-Manifeste befinden, die gemeinsam eine komplexe Anwendung abbilden.
Kommt ein Helm Chart auf einem Cluster zur Anwendung, installiert dies die
Applikation in Kubernetes. Helm besitzt außerdem ein Templating-Feature, das
ermöglicht, in Kubernetes-Manifesten, die sich in Helm Charts befinden,
hartcodierte Werte durch dynamische Platzhalter zu ersetzen. Die Werte dieser
Platzhalter werden extern spezifiziert, beispielsweise in einer
values.yaml-Datei, die sich ebenfalls im Helm Chart befindet. Der Benutzer des
Charts kann damit durch Änderung der values.yaml-Datei alle Parameter in
Kubernetes-Manifesten anpassen, die ihre Werte aus dieser Quelle beziehen.
Kustomize ist ein Tool, das die Anpassung von Kubernetes-Objekten über eine
spezifische Datei ermöglicht. Im Gegensatz zu Helm arbeitet Kustomize nicht mit
Templating, sondern mit Overlays. Die originalen YAML-Dateien bleiben
unverändert und können mit einem Kustomize Overlay überlagert werden, um mehrere
unterschiedliche Varianten auf Basis eines originalen Manifests zu erzeugen.
Damit lassen sich die originalen YAML-Dateien beispielsweise als Basis für
mehrere identische Umgebungen (etwa Production, Development, Test) angeben und
relevante Werte durch Overlays für jede Umgebung ändern.
Die Verwaltung von Kubernetes-Objekten mit einer Kustomize-Datei wird von der
kubectl-CLI unterstützt. Admins stellen diese mit kubectl apply und dem "-k"-
oder "--kustomize"-Flag bereit. Im dabei verwendeten Git-Repository befinden
sich mehrere kustomization.yaml-Dateien, die die bereitzustellenden
Basisressourcen definieren und diese bei Bedarf mit entsprechenden Overlays
patchen.
Auch in GitOps-Projekten besteht die Notwendigkeit, mit Secrets zu arbeiten.
Dabei können Open-Source-Anwendungen wie Hashicorp Vault [11] (Open Source) oder
CyberArk Conjur [12] (das es auch in einer kommerziellen Variante gibt) zum
Einsatz kommen. Ein anderes Werkzeug, das komplett ohne Installation einer
Standalone-Software auskommt, ist Sealed Secrets [13]. Es erlaubt, vertrauliche
Daten mit asymmetrischer Kryptografie zu verschlüsseln, sodass diese sich
anschließend sicher veröffentlichen lassen.
Dabei kommt ein Sealed-Secrets-Controller innerhalb des Kubernetes-Clusters zum
Einsatz, der ein Schlüsselpaar generiert. Den öffentlichen Schlüssel nutzt der
Controller, um aus unverschlüsselten Kubernetes-Secrets verschlüsselte Sealed
Secrets zu erzeugen. Die YAML-Dateien der erstellten Sealed Secrets können
anschließend sicher in einem Git-Repository veröffentlicht werden und sind
ausschließlich mit dem privaten Schlüssel des Sealed-Secret-Controllers, der
innerhalb des Clusters existiert, wieder entschlüsselbar. Für einen Test von
Argo CD können Sie auch mit normalen Kubernetes-Secrets arbeiten, doch in
produktiven Umgebungen sollten sie unbedingt einen der erwähnten Secrets-Manager
nutzen.
Argo CD installieren
Die Installation von Argo CD und dessen GUI geht relativ einfach. Sie erfolgt
einfach per Kubernetes Manifest:
kubectl create namespace Argo CD
kubectl apply -n Argo CD -f
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Alternativ kann dies mittels des Kustomize-Tools oder per Helm Chart erfolgen:
Für die Arbeit mit Argo CD benötigen Sie noch die CLI. Diese ist für macOS,
Linux und WSL Homebrow verfügbar und Sie spielen sie via brew install Argo CD
ein. Eine detaillierte Installationsbeschreibung liefert [14].
Struktur des
GitOps-Repositories
Kubernetes stellt Applikationen und Services bereit, indem deklarative Manifeste
auf den Cluster angewendet werden. Diese Manifeste können Sie im Git-Repository
mit unterschiedlichen Methoden spezifizieren, damit Argo CD diese erkennt und
korrekt anwendet. Neben Verzeichnissen, die einfache YAML-Dokumente enthalten,
unterstützt Argo CD auch verschiedene Konfigurations- und Managementtools. In
der Praxis sind dies die bereits vorgestellten Helm und Kustomize.
In der Verzeichnisstruktur des Repositories, in der sich Kubernetes-Manifeste,
Kustomize-Dateien und Helm Charts befinden, enthalten die Verzeichnisse "root",
"services" und "infrastructure" die folgenden Dateien:
- root: Verweist auf die Kubernetes-Manifeste aller Tools und Abhängigkeiten,
die in jedem Kubernetes-Cluster bei der Initialisierung installiert werden
müssen, um die Anforderungen und Funktionalitäten des Projekts umzusetzen (zum
Beispiel Argo CD)
- services: Enthält die Kubernetes-Manifeste aller anderen Applikationen und
Services des Kubernetes-Clusters. Diese können beispielsweise Endbenutzern zur
Verfügung stehen.
- infrastructure: Zeigt optionale Infrastrukturmodule, die sich mittels
Git-Ops-Technologien deployen lassen.
Um mit Argo CD eine Applikation bereitzustellen, erstellen Sie ein
Kubernetes-Manifest vom Typ "(kind) Application" und der API
"argoproj.io/v1alpha1". Die Definition schaut dann wie in Listing 1 aus. Im
Source-Feld definieren Sie die Quell-Manifest-Dateien der Anwendung als das
Git-Repository. In "Destination" geben Sie dann an, wo die Anwendung
bereitgestellt werden soll. Dieses Manifest müssen Sie im Argo-CD-Server mittels
kubectl-Befehl einspielen, um es ausrollbar zu machen. Alternativ nutzen Sie die
CLI:
Haben Sie die Applikation installiert, lässt sich deren Status mit Argo CD app
get guestbook überprüfen. Ein beispielhaftes Ergebnis dieses Kommandos zeigt der
Listing-Kasten 2.
Den ersten Sync mit dem Zielserver stoßen Sie anschließend wie folgt an:
Argo CD app sync guestbook
Haben Sie die GUI installiert, können Sie die beschriebenen Schritte auch im
Browser ausführen.
Fazit
GitOps ist derzeit einer der großen Trends in cloudnativen Infrastrukturen. Die
Vorteile liegen unter anderem in der Produktivität, der Standardisierung und der
erhöhten Security. Eines der bekanntesten Tools für GitOps ist Argo CD, dessen
Einsatz wir ebenso vorgestellt haben wie die anderen nützlichen Werkzeuge aus
diesem Umfeld.