ADMIN

2023

06

2023-05-30T12:00:00

Automatisierung

SCHWERPUNKT

082

Automatisierung

Infrastructure-as-Code

Automatisierung mit GitOps

Alles deklariert

von Dr. Guido Söldner

Veröffentlicht in Ausgabe 06/2023 - SCHWERPUNKT

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:
helm repo add argo https://argoproj.github.io/argo-helm
 
helm install my-release argo/argo-cd
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.
Listing 1: Kubernetes-Manifest für Argo CD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
    name: guestbook
    namespace: Argo CD
spec:
    project: default
    source:
       repoURL: https://github.com/argoproj/ArgoCD-example-apps.git
       targetRevision: HEAD
       path: guestbook
    destination:
       server: https://kubernetes.default.svc
       namespace: guestbook
Software mit Argo CD deployen
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:
Argo CD app create guestbook
    --repo https://github.com/argoproj/Argo CD-example-apps.git
    --path guestbook --dest-server https://kubernetes.default.svc
    --dest-namespace guestbook
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.
Listing 2: Status einer installierten Applikation
Name:                     guestbook
Server:                    https://kubernetes.default.svc
Namespace:            default
URL:                       https://10.97.164.88/applications/guestbook
Repo:                      https://github.com/argoproj/Argo CD-example-apps.git
Target:
Path:                      guestbook
Sync Policy:          
Sync Status:           OutOfSync from (1ff8a67)
Health Status:        Missing
GROUP         KIND                 NAMESPACE         NAME                    STATUS                 HEALTH
apps               Deployment       default                     guestbook-ui          OutOfSync              Missing
                       Service               default                     guestbook-ui          OutOfSync              Missing
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.
(jp)
Link-Codes
[4]Kubernetes Helm Operator: https://github.com/fluxcd/helm-operator/
[5]Jenkins X: https://jenkins-x.io/
[10]Kustomize: https://kustomize.io/
[11]Hashicorp Vault: https://www.vaultproject.io/
[12]Open-Source-Variante von CyberArk Conjur: https://www.conjur.org/