3Wie fange ich mit GitOps an?

Nach dem vorherigen Kapitel haben wir eine konkrete Vorstellung davon, welchen Unterschied GitOps im Entwicklungsalltag macht. In diesem Kapitel wollen wir erste praktische Schritte in Richtung GitOps unternehmen. Am Ende dieses Kapitels werden wir einen lokalen Kubernetes-Cluster haben, in dem ein GitOps-Operator läuft, der eine Beispielanwendung kontinuierlich aus einem Config-Repo deployt.

Bevor wir in den Code und die Praxis eintauchen, möchten wir aber zuerst ein paar Werkzeuge an die Hand geben, die für jede Situation nützlich sind, in der man GitOps implementieren will: eine grundsätzliche Empfehlung und eine Orientierungshilfe.

3.1Agile Empfehlung: zügiger Durchstich

Die vier Prinzipien können einschüchternd wirken, weil sie absolute Standards setzen, die auf den ersten Blick keinen Spielraum lassen. Glücklicherweise ist GitOps aber nicht zuallererst ein himmelhohes Ideal, das kein gewöhnlicher Mensch erreichen kann. Stattdessen reden wir hier von einer Reise und einem schönen Reifeprozess. Sehr empfehlenswert zu diesem Thema ist auch der Vortrag »GitOps as a Journey« von Dan Garfield (Codefresh), Scott Rigby (Weaveworks) und Chris Short (AWS) auf der GitOpsCon 20221.

Wir empfehlen deshalb grundsätzlich ein agiles Vorgehen: Versuche nicht, sequenziell Prinzip für Prinzip lückenlos zu erfüllen. Ziele stattdessen auf einen Durchstich ab, quasi ein Minimum Viable Product (MVP), mit dem du alle vier Prinzipien minimal erfüllst. Danach bringe iterativ immer mehr Ressourcen deines Systems unter GitOps-Kontrolle.

In aller Regel hat man nämlich bereits deklarative Manifeste, die man nicht erst noch erzeugen muss. Das sind beispielsweise Kubernetes-Manifeste, Docker-Compose-Manifeste oder Terraform-Dateien. Damit ist Prinzip 1 grundlegend abgedeckt.

Git ist sehr weit verbreitet als Versionierungstechnologie. Wenn man seine Manifeste in Git speichert, hat man Prinzip 2 bereits zu einem großen Teil erfüllt.

Den GitOps-Operator installieren

Was GitOps am meisten von anderen Deployment- und Betriebsansätzen differenziert, sind Prinzip 3 und 4: der Operator im Zielsystem, der Deklarationen kontinuierlich überwacht und anwendet. An diesem Punkt ist die erste praktische Änderung nötig. Im Kubernetes-Umfeld haben wir mit Flux CD2 und Argo CD 3 zwei reife und etablierte Alternativen an GitOps-Tools. Wir verwenden in diesem Kapitel Argo CD als Startpunkt, weil die eingebaute UI sich gut zur Visualisierung eignet und weil Argo CD meist mehr Anklang bei Entwickelnden findet, während Flux bei Plattformbetreibern beliebter ist.

In Kapitel 4 auf Seite 69 gehen wir tiefer auf die Unterschiede zwischen Argo CD und Flux ein und welches Tool sich für welche Anforderungen besser eignet.

Config-Repos mit dem GitOps-Operator verknüpfen

Nach der Installation muss Argo CD so konfiguriert werden, dass es die Manifeste im Git-Repo lesen kann. Dafür müssen wir wiederum ein Manifest erstellen, das dieses Git-Repo referenziert. Bei Argo CD nennt man solche Referenzen Applications.

Analog zu den Applications bei Argo CD gibt es bei Flux verschiedene Ressourcentypen wie Kustomizations und HelmReleases.

Sobald wir dieses Referenzmanifest deployt haben, werden die vorhandenen Manifeste von Argo CD überwacht und in GitOps-Manier kontinuierlich angewandt. Ab hier sind auch alle vier Prinzipien erstmals grundlegend erfüllt.Vollständig erfüllt sind sie noch nicht, denn folgende Kriterien erfüllt unser Aufbau an diesem Punkt meistens noch nicht:

  1. Bei Prinzip 2: Die reine Nutzung von Git erfüllt die Anforderung von Versionierung, aber nicht automatisch die von Unveränderbarkeit. Je nach gewünschtem Grad an Unveränderbarkeit sind weiterführende Schritte nötig wie beispielsweise das Pinnen von Image-Tags. (Wir haben bereits bei Abschnitt 1.3.2 auf Seite 18 darüber gesprochen.)
  2. Ebenfalls bei Prinzip 2: Oftmals haben wir es auch mit Secrets zu tun, die wir nicht direkt in Git versionieren wollen. Diesem Thema wenden wir uns in Kapitel 5 auf Seite 97 zu.

Prinzip 1 sagt nichts aus über den Umfang des Systems.

Wenn wir von Vollständigkeit reden, sollten wir noch einmal im Detail Prinzip 1 untersuchen: Dieses Prinzip besagt, dass der Zustand des von GitOps verwalteten Systems deklarativ beschrieben sein muss. Es besagt nicht, dass die Gesamtheit des Systems, innerhalb dessen ein GitOps-Operator läuft, vollständig deklarativ beschrieben sein muss.

Es ist mit Sicherheit gut, wenn so viele Komponenten unseres Softwaresystems wie möglich von GitOps verwaltet werden, und unserer Erfahrung nach entwickelt GitOps schnell eine Sogwirkung, sodass Teams von alleine versuchen, immer mehr Teile des Systems unter GitOps-Kontrolle zu bringen. Dazu kann beispielsweise die zugrunde liegende Infrastruktur gehören (siehe Kapitel 11 auf Seite 291).

Aber Prinzip 1 legt umgekehrt fest, dass es dann erfüllt ist, wenn das System, das von GitOps verwaltet wird, deklarativ beschrieben wird. Nicht alle Bestandteile eines Systems werden wir immer deklarativ ausdrücken können oder wollen. In Kapitel 9 auf Seite 247 betrachten wir Entitäten und Aktionen, die wir möglicherweise bewusst außerhalb der GitOps-Überwachung behandeln möchten.

3.2Fragen zur Orientierung

Als weiteres Hilfsmittel vor der praktischen Umsetzung wollen wir eine Orientierungshilfe geben, mit der man GitOps-Implementierungen einschätzen und zueinander in Bezug setzen kann.

Zum Thema GitOps finden sich Unmengen an Tutorials, Blogposts, Konferenzbeiträgen und dergleichen, die sehr detailliert eine konkrete Implementierung von GitOps vorstellen. Viele davon sind wertvoll für die Umsetzung, auch wenn manche sich leider auf veraltete Definitionen von GitOps stützen und damit den Begriff »GitOps« verwischen. Ihnen allen ist aber gemein, dass sie denjenigen nicht wirklich helfen, die GitOps und seine Prinzipien zuerst noch grundlegend kennenlernen müssen, bevor sie anfangen können mit einer Implementierung.

Mit den folgenden Fragen wollen wir Verwirrung verringern und dabei helfen, GitOps-Lösungen einzusortieren, damit wir – um das geläufige Sprichwort positiv umzuformulieren – wieder »den Wald trotz lauter Bäumen« sehen können. Sie beschränken sich auf die für GitOps relevanteren Aspekte und lassen damit bewusst manche Dimensionen aus, die für die ganzheitliche Beurteilung eines Softwaresystems relevant sein können.

  1. Prinzip 1:Was für Deklarationen nutzen wir? Das können unterschiedlichste Dateiformate sein: Kubernetes-Manifeste, Docker-Compose-Manifeste, Terraform-Dateien, Pulumi-Code, Helm-Charts oder andere. Auch Kombinationen von verschiedenen Deklarationstypen sind möglich, beispielsweise Terraform für Infrastruktur und Helm-Charts für Deployments.
  2. Prinzip 2:Welchen Speicher nutzen wir? Das kann sich in der Technologie und im Hosting unterscheiden:
    • Die Technologie kann beispielsweise Git, Mercurial oder Fossil sein. Sie kann auch seltenere Varianten umfassen wie AWS S3 oder Registries, die mit der Spezifikation der Open Container Initiative (OCI) compliant sind (OCI-Registries).
    • Beim Hosting reden wir meistens von der Bereitstellung eines Git- oder Mercurial-Servers, und hier unterscheiden wir nochmals zwischen Modus und Produkt:
    • Modus: Wird es als Software-as-a-Service (SaaS) bezogen oder selbst betrieben?
    • Produkt: Nutzen wir GitLab, GitHub, Bitbucket oder ein anderes Produkt?
  3. Prinzipien 3 und 4:Welchen GitOps-Operator nutzen wir? Typische Antworten hier sind Argo CD, Flux, Portainer oder selbst entwickelte Tools.
  4. Welche Secrets-Verwaltung nutzen wir? (Wir sehen in Kapitel 5 auf Seite 97 genauer, warum das Verwalten von Secrets eine so wichtige Rolle spielt.) Mögliche Antworten können hier sein:
  5. Welche private Image-Registry nutzen wir? Weil wir in aller Regel mit Containern arbeiten, ist es zur Orientierung hilfreich zu wissen, wo unsere Container-Images gelagert werden. Meistens lohnt es sich hier zu differenzieren zwischen privaten und öffentlichen Images. Öffentliche Images werden oftmals von Docker Hub oder Quay genommen, während private, selbstgebaute Images beispielsweise in der Azure Container Registry, einem selbstbetriebenen Harbor oder einer anderen privaten Registry gelagert werden. Die Antwort auf diese Frage kann sich in manchen Fällen mit der Antwort auf Frage 2 überlappen oder sogar deckungsgleich sein. Ein paar kurze Beispiele dafür:

3.3Eine Beispielimplementierung mit Argo CD

In Kapitel 2 auf Seite 25 haben wir ein beispielhaftes Szenario mit mehreren Anwendungen und Clustern ausgemalt. Im Rest dieses Kapitels gehen wir erste Schritte und üben ein, wie das Arbeiten im GitOps-Stil praktisch aussieht. Die dabei entstehende Implementierung ist sehr vereinfacht und nicht produktionsreif. Wir favorisieren an dieser Stelle einen zügigen Aufbau und geringe Komplexität vor zu frühen Abstraktionen.

Diese Implementierung ist nur eine Variante von vielen Wegen, wie man GitOps umsetzen kann. Wir beschränken uns an dieser Stelle bewusst auf eine einzige Variante, um zuerst den ganzen Pfad durchzugehen und eine Implementierung vollständig von Anfang bis Ende abzudecken. Dabei werden wir viele Themen nur streifen und erst das ganze Spektrum sehen, bevor wir uns dann in den nachfolgenden Kapiteln den einzelnen Themen in der Tiefe widmen.

3.3.1Zielsetzung

Anfangs wollen wir die gerade formulierten Orientierungsfragen nutzen, um den endgültigen Zielzustand zu beschreiben:

  1. Was für Deklarationen nutzen wir? Kubernetes-Manifeste in einer Kustomize-Struktur.
  2. Welchen Speicher nutzen wir? Git mit einem SaaS-Provider, beispielsweise GitLab.
  3. Welchen GitOps-Operator nutzen wir? Argo CD.
  4. Welche Secrets-Verwaltung nutzen wir? HashiCorp Vault mittels External Secrets Operator.
  5. Welche private Image-Registry nutzen wir? Keine, wir nutzen nur ein Image aus der GitHub Container Registry.

Die vollständige Architektur versuchen wir in Abb. 3–1 übersichtsartig darzustellen. Die Beispielimplementierung fängt in diesem Kapitel erst noch in einem vereinfachten Zustand an und wir bauen sie stellenweise im Lauf des Buches aus. (Konkret werden wir uns beispielsweise mit HashiCorp Vault erst in Kapitel 5 auf Seite 97 befassen.)

image

Abb. 3–1
Vollständige Architektur der Beispielimplementierung

Den reduzierten Zielzustand für dieses Kapitel versuchen wir in Abb. 3–2 genauer darzustellen: Wir werden in GitLab ein Config-Repo haben, aus dem das ganze Environment aufgebaut wird. Als einzigen Workload wollen wir eine simple Beispielanwendung ausführen (podinfo4 von Weaveworks). Das Container-Image dafür liegt in der GitHub Container Registry.

Wir werden den Argo CD Autopilot5 verwenden, um eine Repository-Struktur aufzubauen und Argo CD in den Cluster zu installieren. Mithilfe eines Argo CD ApplicationSet werden wir die Beispielanwendung als Application deployen, und dadurch werden unsere Anwendungen auf GitOps-Weise in den Cluster betrieben.

Abb. 3–2 sieht womöglich erst einmal erschreckend komplex aus. Wir arbeiten uns von oben nach unten vor und werden Schritt für Schritt die einzelnen Bereiche erhellen. Es mag hilfreich sein, im Verlauf dieses Kapitels immer wieder auf dieses Diagramm zurückzugreifen.

image

Abb. 3–2
Zielzustand der Beispielimplementierung am Ende dieses Kapitels

Wir führen konkret folgende Schritte aus:

  1. Wir setzen einen lokalen Kubernetes-Cluster auf.
  2. Wir installieren Argo CD in den Cluster und befüllen ein Config-Repo durch den Argo CD Autopilot.
  3. Wir deployen die Beispielanwendung über das Config-Repo.
  4. Wir deployen eine Änderung an der Beispielanwendung, um den vollständigen Deployment-Fluss nachzuvollziehen.

Schauen wir uns zuerst an, welche Voraussetzungen wir für die Implementierung benötigen:

3.3.2Voraussetzungen

Um die Implementierung selbst nachspielen zu können, benötigst du

3.4Schritt 1: Einen Cluster starten

Ganz zu Beginn starten wir einen lokalen Cluster mit minikube. Dafür genügt der Befehl minikube start.

3.5Schritt 2: Argo CD installieren

Bevor wir Argo CD mithilfe des Autopiloten installieren, versuchen wir einige grundlegende Dinge über Argo zu verstehen: Argo ist eine Familie an Projekten, zu denen offiziell die folgenden gehören:

  1. Argo CD: das GitOps-Tool für Continuous Delivery
  2. Argo Rollouts: eine Erweiterung der typischen Deployment-Strategien in Kubernetes
  3. Argo Workflows: parallelisiertes Ausführen von Jobs, besonders genutzt für Machine Learning und Data Science
  4. Argo Events: Webhooks für Kubernetes-Ressourcen exponieren

Der Argo CD Autopilot gehört noch nicht offiziell zur Argo-Familie, bietet uns aber dennoch einige Vorteile:

Config-Repo erstellen und Autopilot autorisieren

Wir werden jetzt zuerst Argo CD aufsetzen mithilfe des Autopiloten und anschließend nachvollziehen, was alles in diesen wenigen Schritten passiert ist. Im Zuge dessen werden wir auch ein Config-Repo befüllen. Dafür erstellen wir ein neues Repo in GitLab unter https://gitlab.com/projects/new. (Die HTTPS-URL dieses Repositorys bezeichnen wir im Folgenden mit GITLAB_REPO_URL.) Dieses Repo lassen wir gleich vom Autopiloten befüllen.

Als Beispiel stellen wir auf GitLab auch ein fertig befülltes Referenz-Config-Repo zur Verfügung14. Der Unterordner ch03/ in diesem Repo enthält die Inhalte, wie sie am Ende dieses Kapitels aussehen können. Ein eigenes Repo zu erstellen ist dennoch nötig, weil du andernfalls keine Schreibrechte auf das Config-Repo hast.

Damit auch der Autopilot in unser neues Repo committen kann, benötigt er Credentials. Dafür erzeugen wir in GitLab einen Personal Access Token (PAT) mit Schreibzugriff auf unser neues Repo. Unter https://gitlab.com/-/profile/personal_access_tokens wählen wir unter »Select scopes« nur den Scope write_repository aus. Den Wert, der anschließend unter »Your new personal access token« angezeigt wird, referenzieren wir im Folgenden mit GITLAB_PAT.

Dann exportieren wir folgende Variablen und starten die initiale Provisionierung:

Listing 3–1
Initiales Provisionieren mit Argo CD Autopilot

1

export GIT_USER=YOUR_GITLAB_USERNAME

2

export GIT_TOKEN=GITLAB_PAT

3

# Example repo and directory:

4

# GIT_REPO=https://gitlab.com/gitops-book/erp-gitops/ch03

5

export GIT_REPO=GITLAB_REPO_URL

6

argocd-autopilot repo bootstrap

Argo CD wird gestartet, und es dauert einige Minuten, bis der Cluster die Images heruntergeladen hat. Nach wenigen Minuten sollte am Ende der Terminal-Ausgabe ein Text ähnlich wie der folgende erscheinen:

Listing 3–2
Ende der initialen Ausgabe

1

INFO argocd initialized. password: 59NKDxtX-uvK0zwn

2

INFO run:

3

 

4

kubectl port-forward -n argocd \

5

svc/argocd-server 8080:80

Wir starten diesen Port-Forward und öffnen https://localhost:8080 im Browser. Dort melden wir uns mit dem Usernamen »admin« und dem Passwort aus der Terminal-Ausgabe an.

Argo CD leitet uns direkt zu HTTPS weiter. Die meisten Browser sind damit bei localhost nicht unmittelbar einverstanden und müssen entsprechend konfiguriert werden. In Chrome und verwandten Browsern (auch Edge) kannst du dem Vertrauen von selbstsignierten Zertifikaten unter localhost zustimmen unter einer bestimmten URL15. Andere Browser ermöglichen das Öffnen der Seite, indem man auf der Warnseite einer Ausnahmeoption zustimmt.

Nach dem Login sollten wir vier Applications zu sehen bekommen wie in Abb. 3–3.

3.5.1Ressourcentypen von Argo CD verstehen

Mit diesen wenigen Befehlen sind mehrere Dinge auf einmal geschehen: Der Autopilot hat Argo CD direkt in den Cluster installiert und anschließend einige Manifeste ins Config-Repo committet. Abb. 3–4 zeigt die Ordnerstruktur im Repository.

Wir werden in diesem Kapitel nur mit den Ordnern apps und projects umgehen. Die genaue Struktur, die der Autopilot erzeugt, werden wir in 6.7.1 auf Seite 170 genauer betrachten.

image

Abb. 3–3
Die UI von Argo CD nach der initialen Provisionierung durch den Autopiloten

image

Abb. 3–4
Ordnerstruktur wie von Argo CD Autopilot erzeugt

Damit wir besser verstehen, wie Argo CD funktioniert, betrachten wir drei Custom Resource Definitions (CRDs), die Argo CD von Haus aus mitbringt:

  1. Application: Sie bündelt Kubernetes-Manifeste und synchronisiert sie in den Cluster. Die Quelle einer Application kann ein Git-Repository sein (entweder mit bloßen Manifesten oder Kustomizations) oder ein Helm-Repository.
  2. ApplicationSet: Ein ApplicationSet kann Applications generieren anhand von Templates und Variablen.
  3. AppProject bezeichnet: Mithilfe eines AppProject können Applications und ApplicationSets gruppiert werden. Sie sind optional und wirken in der Ergonomik ähnlich wie Kubernetes-Namespaces.

Der untere Teil von Abb. 3–2 auf Seite 53 kann in diesem Abschnitt sehr hilfreich sein, um visuell besser zu verstehen, wie die verschiedenen Argo-CD-Ressourcentypen miteinander zusammenhängen.

Wir betrachten an dieser Stelle noch jeweils ein Beispiel für eine Application und ein ApplicationSet unter den Dateien, die vom Autopilot erzeugt wurden. Eine der Applications, die erzeugt wurden, ist die Application argo-cd im Namespace argocd:

Listing 3–3
Eine Application in bootstrap/argo-cd.yaml

1

apiVersion: argoproj.io/v1alpha1

2

kind: Application

3

metadata:

4

creationTimestamp: null

5

labels:

6

app.kubernetes.io/managed-by: argocd-autopilot

7

app.kubernetes.io/name: argo-cd

8

name: argo-cd

9

namespace: argocd

10

spec:

11

destination:

12

namespace: argocd

13

server: https://kubernetes.default.svc

14

ignoreDifferences:

15

- group: argoproj.io

16

jsonPointers:

17

- /status

18

kind: Application

19

project: default

20

source:

21

path: bootstrap/argo-cd

22

repoURL: https://gitlab.com/gitops-book/erp-infra.git

23

syncPolicy:

24

automated:

25

allowEmpty: true

26

prune: true

27

selfHeal: true

28

syncOptions:

29

- allowEmpty=true

Eine Application hat ein Ziel (ein Kubernetes-Cluster, in diesem Fall der Cluster, in dem Argo CD selbst läuft) und eine Quelle (in diesem Fall das Config-Repo, mit dem wir gerade arbeiten). Wenn eine Application ein Git-Repo referenziert, können in diesem Repo auch weitere Applications liegen; eine Application ist schließlich selbst nur ein gewöhnliches Kubernetes-Manifest.

Auf diese Weise kann man Applications auch hierarchisch verschachteln. Diese Herangehensweise wird als »App of Apps« bezeichnet (mehr dazu in Abschnitt 6.6.2 auf Seite 168). In der UI von Argo CD können wir dieses Pattern direkt bei der Application autopilot-bootstrap sehen: Sie bindet zwei Applications und ein ApplicationSet ein (siehe Abb. 3–5).

image

Abb. 3–5
App of Apps: Die Application autopilot-bootstrap bindet weitere Applications ein.

ApplicationSets wiederum sind Templates, aus denen Applications erzeugt werden durch Variablen und Generatoren. Die Funktionsweise lässt sich mit Deployments und Pods vergleichen: Ein ApplicationSet und die Applications, die daraus erzeugt werden, sind analog zu einem Deployment, aus dem Pods (genauer gesagt ReplicaSets) erzeugt werden. Das Template im ApplicationSet ist dann analog zum Pod-Template im Deployment.

Ein ApplicationSet lässt sich auch in gewisser Weise mit einem Helm-Chart vergleichen: Das Template im ApplicationSet entspricht den Templates im Chart. Die Generatoren im ApplicationSet entsprechen ungefähr den Values-Files, aus denen konkrete Helm-Releases instanziiert werden können.

Ein Beispiel für ein ApplicationSet unter den vom Autopilot generierten Dateien ist das ApplicationSet cluster-resources im Namespace argocd. Wir stellen es aus Platzgründen hier nur verkürzt dar:

Listing 3–4
Ein ApplicationSet in bootstrap/cluster-resources.yaml

1

apiVersion: argoproj.io/v1alpha1

2

kind: ApplicationSet

3

metadata:

4

# ...

5

name: cluster-resources

6

namespace: argocd

7

spec:

8

generators:

9

- git:

10

files:

11

- path: bootstrap/cluster-resources/*.json

12

repoURL: https://gitlab.com/gitops-book/erp-infra.git

13

# ...

14

template:

15

metadata:

16

labels:

17

app.kubernetes.io/managed-by: argocd-autopilot

18

app.kubernetes.io/name: cluster-resources-{{name}}

19

name: cluster-resources-{{name}}

20

namespace: argocd

21

spec:

22

destination:

23

server: '{{server}}'

24

# ...

25

source:

26

path: bootstrap/cluster-resources/{{name}}

27

repoURL: https://gitlab.com/gitops-book/erp-infra.git

28

syncPolicy:

29

automated:

30

allowEmpty: true

31

selfHeal: true

In diesem Fall werden Variablen in doppelten geschwungenen Klammern wie {{name}} ersetzt durch ihre Werte in den Dateien unter bootstrap/cluster-resources/*.json, und aus den resultierenden ausgefüllten Templates erzeugt das ApplicationSet dynamisch Applications.

3.6Schritt 3: Eine eigene Application erzeugen

Wir werden jetzt ein AppProject, eine Application und ein Kubernetes-Deployment erzeugen. Das Deployment wird von der Application verwaltet werden, und die Application wird wiederum dem AppProject zugeordnet sein.

Die Zuordnung von Applications in ein AppProject ist optional (es gibt standardmäßig ein AppProject namens »default«), doch es bietet Vorteile: Man kann Berechtigungen auf den zugehörigen Applications zentral steuern und beispielsweise festlegen, in welchen Namespaces diese Applications Ressourcen erzeugen dürfen.

Wir erstellen in diesem Fall ein AppProject namens podinfo-dev, welches das gesamte Environment für unseren Workload enthalten wird:

Listing 3–5
Erstellen des AppProjects

1

argocd-autopilot project create podinfo-dev

Der Autopilot erzeugt daraufhin eine Datei namens projects/podinfodev.yaml, welche das AppProject und das ApplicationSet enthält.

Anschließend erzeugen wir eine (leere) Application:

Listing 3–6
Erstellen der Application

1

argocd-autopilot app create podinfo \

2

--project podinfo-dev --type kustomize \

3

--app deployment.yaml

Der Autopilot committet dabei eine Kustomization in das Repository, die auf die Datei apps/podinfo/base/deployment.yaml verweist, die aber noch nicht existiert. Erzeugen wir sie, um unsere Beispielanwendung zu deployen!

Bevor wir das tun können, müssen wir noch den neuesten Stand des Repositorys pullen, weil der Autopilot alle Commits im Hintergrund (und nicht in der Working Directory unserer Shell-Session) macht. Anschließend können wir unser Manifest erzeugen:

Listing 3–7
Erstellen des Deployments

1

git pull

2

kubectl create deployment podinfo \

3

--dry-run=client -o=yaml --port=9898 \

4

--image=ghcr.io/stefanprodan/podinfo:6.4.0 \

5

> apps/podinfo/base/deployment.yaml

Dieses Manifest könnten wir an diesem Punkt auch imperativ deployen mit kubectl apply, um das Deployment im Cluster zu installieren. Wenn wir aber mit GitOps arbeiten, wollen wir stattdessen die Datei committen und die Arbeit des Ausrollens dem GitOps-Operator überlassen. Committen wir also die Datei:

Listing 3–8
Erstellen des Deployments

1

git add apps/podinfo/base

2

git commit -m "feat: add podinfo deployment"

3

git push

Wenn wir ein paar Sekunden warten, sollte die UI von Argo CD uns eine neue Application mit einem gesunden Deployment zeigen wie in Abb. 3–6 und Abb. 3–7.

image

Abb. 3–6
Eine neue Application in der Übersicht

Wir können uns auch noch konkreter von der gesunden Ausführung der Anwendung überzeugen, indem wir einen Port-Forward starten und anschließend die URL http://localhost:9898 im Browser öffnen.

Listing 3–9
Port-Forward des Deployments

1

kubectl port-forward deploy/podinfo 9898:9898

2

# Open http://localhost:9898

Eine Ansicht wie in Abb. 3–8 sollte uns begegnen.

image

Abb. 3–7
Ein gesundes Deployment in der neuen Application

image

Abb. 3–8
Podinfo im Browser

3.7Schritt 4: Eine Änderung deployen

Nach diesem erfolgreichen Setup sind wir in der Lage, Änderungen an unserer Beispielanwendung voll kontinuierlich von Argo CD deployen zu lassen. Als einfaches Beispiel nehmen wir eine Skalierung: Sagen wir, wir wollen das Deployment auf zwei Replicas hochskalieren.

Ohne GitOps würden wir das vielleicht imperativ machen, indem wir folgenden Befehl ausführen:

Listing 3–10
Imperatives Skalieren des Backends

1

kubectl scale deploy/podinfo --replicas=2

Wenn wir diesen Befehl ausführen, startet zwar ein zweiter Pod, aber dieser fährt fast sofort wieder herunter. Das liegt daran, dass unsere manuelle Änderung am Deployment sofort von Argo CD überschrieben wird.

Statt imperativ zu arbeiten, können wir komplett GitOps-konform arbeiten, indem wir diese Änderung stattdessen deklarativ im Manifest vornehmen: Wir bearbeiten also die Deployment-Datei, die wir in Schritt 3 erzeugt haben, und setzen .spec.replicas=2. Nachdem wir diese Änderungen committen und pushen, startet eine zweite Replica erfolgreich (siehe Abb. 3–9).

image

Abb. 3–9
Eine zweite Replica startet

3.8Fazit

In diesem Kapitel haben wir Hilfsmittel kennengelernt, um GitOps-Lösungen einschätzen und miteinander vergleichen zu können. Diese Hilfsmittel haben wir direkt angewandt bei einer Beispielimplementierung.

Im Rahmen dieser Implementierung haben wir Argo CD mithilfe des Argo CD Autopilot in einem lokalen Cluster installiert und unsere beiden Beispielapplikationen dorthin deployt. Wir haben Argo CD und seine Ressourcentypen kennengelernt, insbesondere Application-Sets mit ihren Templating-Möglichkeiten.

Ebenso haben wir den Unterschied erlebt zwischen imperativem und deklarativem Deployen, indem wir eine der Anwendungen zuerst imperativ und dann deklarativ skaliert haben. Das greifbarste Ergebnis dieses Kapitels ist das Config-Repo, das wir erstellt und mit Manifesten befüllt haben.