In den Deployment-Flüssen im vorherigen Kapitel haben wir mit einem Prüfschritt am Schluss sichergestellt, dass unsere Anwendung stabil und mit der neuesten Version läuft (siehe Abschnitt 7.4.1 auf Seite 218). Wenn wir unseren Prüfschritt im Cluster ausführen, ist er losgelöst von unserer CI-Pipeline und wir können nicht ohne Weiteres über Fehlschläge dieses Schritts benachrichtigt werden. Zusätzlich können unserem GitOps-Operator verschiedenste Probleme begegnen, während er im Cluster tätig ist:
Zusätzlich ist es denkbar, dass wir keinen aktiven Prüfschritt implementiert haben. Für den produktiven Betrieb jedoch ist Alerting grundsätzlich unabdingbar, egal in welcher Form. Daher wollen wir uns genauer anschauen, wie ein GitOps-Operator uns benachrichtigen kann, wenn Fehler auftreten oder Ressourcen in einem ungesunden Zustand sind. In diesem Kapitel befassen wir uns bewusst nur mit Alerting und nicht mit Monitoring oder gar Observability. Wir betrachten konkret folgende Fragestellungen:
Abschließend betrachten wir in Abschnitt 8.3 auf Seite 245, wie wir diese in einer ganzheitlichen Strategie einsetzen können.
Beginnen wir damit, wie wir den Gesundheitszustand von Ressourcen feststellen können. Dabei schauen wir zunächst an, was Kubernetes (Abschnitt 8.1.1) und Helm (Abschnitt 8.1.2 auf Seite 235) unabhängig von GitOps an Bordmitteln mitbringen. Dann betrachten wir, wie Flux (Abschnitt 8.1.3 auf Seite 235) und Argo CD (Abschnitt 8.1.4 auf Seite 238) darauf aufbauen.
Ressourcenzustand in Kubernetes als »low hanging fruit«
Den Gesundheitszustand feststellen zu können ist die Grundlage für das Versenden von Benachrichtigungen in Abschnitt 8.2 auf Seite 239. Kubernetes bietet bereits von Haus aus bei jeder Ressource einen automatisch ermittelten Gesundheitszustand an. Am geläufigsten werden die Zustandsübergänge eines Pods sein, der von »Pending« am Anfang seines Schedulings hin zu »Running« wechselt, oder auch die Übergänge eines Deployments, das sich im Zustand »Progressing«, »Complete« oder »Failed« befinden kann. Dieser Gesundheitszustand wird über das Tool kstatus ermittelt.
Dieser Status einer Kubernetes-Ressource kann hilfreich bei der Umsetzung von Alerting sein, weil wir hier nur wenig selbst implementieren müssen und uns stark auf Vorgefertigtes verlassen können. Außerdem bauen manche GitOps-Operatoren wie Flux bei ihrem eigenen Alerting maßgeblich auf den Kubernetes-Zustand von Ressourcen auf, wie er von kstatus gepflegt wird.
Im folgenden Unterabschnitt beschäftigen wir uns genauer damit, wie der Gesundheitszustand einer Kubernetes-Ressource bestimmt wird. Dabei gehen wir teilweise stark in technische Details! Lass dich davon nicht abschrecken: Die wichtigsten Erkenntnisse fassen wir am Ende des Unterabschnitts kurz zusammen.
kstatus überprüft den Zustand der Angleichung.
Wie trifft Kubernetes selbst eine Aussage darüber, ob eine Ressource gesund ist – und welche Aussagekraft hat diese Feststellung? Kubernetes hat bei seinen Statusüberprüfungen vor allem ein Ziel: sicherzustellen, dass die Angleichung (»Reconciliation«) einer Ressource erfolgreich war. Eine Ressource wird also grundsätzlich immer dann als »gesund« markiert, wenn die Realität im Cluster der Spezifikation im Manifest entspricht.
Intern nutzt Kubernetes das Tool kstatus als Teil der cli-utils1, um den Status einer Ressource festzustellen. Die möglichen Statuswerte, die kstatus definiert, sind folgende sechs:
kstatus stützt sich dabei auf die API-Konventionen von Kubernetes2. Laut diesen kann jede Kubernetes-Ressource eine Liste unter .status.conditions exponieren, die verschiedene »Gesundheitsaspekte« der Ressource beschreibt. Wir zeigen ein Beispiel, wie eine solche Liste beziehungsweise Map an Conditions bei einem Deployment aussehen kann:
Listing 8–1
Beispielstatus eines Deployments
1
apiVersion: apps/v1
2
kind: Deployment
3
metadata:
4
name: argocd-server
5
namespace: argocd
6
# ...
7
spec:
8
# ...
9
status:
10
availableReplicas: 1
11
conditions:
12
- lastTransitionTime: "2023-04-04T07:42:23Z"
13
lastUpdateTime: "2023-04-04T07:42:23Z"
14
message: Deployment has minimum availability.
15
reason: MinimumReplicasAvailable
16
status: "True"
17
type: Available
- lastTransitionTime: "2023-04-04T07:41:46Z"
19
lastUpdateTime: "2023-04-04T07:42:23Z"
20
message: >-
21
ReplicaSet "argocd-server-64957744c9"
22
has successfully progressed.
23
reason: NewReplicaSetAvailable
24
status: "True"
25
type: Progressing
26
observedGeneration: 2
27
readyReplicas: 1
28
replicas: 1
29
updatedReplicas: 1
kstatus mappt Conditions auf einen Status.
Wir sehen zwei Conditions:
kstatus würde diese Conditions sehr wahrscheinlich auf den Status »Current« abbilden, weil die Conditions darauf hindeuten, dass die Deklaration im Manifest Wirklichkeit geworden ist.
Das Feld .status.conditions ist eine Liste. Der Verdacht könnte naheliegen, dass diese Liste eine Chronologie abbildet, also den zeitlichen Verlauf von Statusänderungen (noch dazu, weil Zeitstempel vermerkt sind).
Hier wird allerdings eben keine Historie abgebildet: In Wirklichkeit ist diese Liste ein Objekt, bei dem der Wert von type der jeweilige Schlüssel eines Unterobjekts ist. Jeder Listeneintrag beschreibt einen unterschiedlichen Gesundheitsaspekt der Ressource, und die Liste in ihrer Gesamtheit drückt den insgesamten Gesundheitszustand der Ressource aus.
Der Parameter .status.conditions.*.status kann die Werte »True«, »False« oder »Unknown« haben. Im obigen Manifest wäre auch folgende Kombination von Status möglich:
Eine solche Kombination würde dem Zustand »InProgress« von kstatus entsprechen.
Zustände via kstatus sind in der Hand der Controller-Entwickelnden.
Da es sich bei den eben beschriebenen Conditions nur um eine Konvention handelt, ist niemand, der CRDs entwickelt, dazu verpflichtet, Conditions in seinen Ressourcen auszuweisen. Es kann also durchaus Ressourcentypen geben, bei denen der entsprechende Controller das Feld .status niemals setzt. Bei allen nativen Kubernetes-Ressourcentypen wie unter anderem Deployments, StatefulSets, Services und Secrets ist diese Konvention aber glücklicherweise bereits erfüllt.
Welche Prüfungen ein Controller konkret durchführt (wenn er überhaupt welche durchführt) und auch welche Condition-Types er anbietet, ist von außen nicht unmittelbar erkenntlich. Wir sind bei kstatus auch nicht in der Lage, eigene Healthchecks für Ressourcentypen oder einzelne Ressourcen zu definieren. Wir müssen uns letztlich darauf verlassen, dass die Implementierung der Healthchecks der Ressourcentypen in unserem Cluster sinnvoll und zuverlässig ist. kstatus benennt dabei selbst einige semantische Herausforderungen bei der Statusüberprüfung wie ungesetzte Conditions bei Controller-Unverfügbarkeit, Uneindeutigkeit und den Status abhängiger Ressourcen3.
kstatus deckt bei guter Konfiguration einfache Szenarien ab.
Beschränken wir uns für einen Moment auf unser simples curl-Beispiel von Abschnitt 7.1.1 auf Seite 197. In diesem Fall wollen wir nur folgende Fragen beantworten:
Die erste Frage können wir über den Kubernetes-Status unserer Pods beantworten, indem wir aussagekräftige Probes definieren für Startup, Liveness und Readiness, denn dadurch wird auch der Gesundheitszustand unseres Pod-Controllers (zum Beispiel Deployment, StatefulSet, DaemonSet) korrekt gesetzt. (Diese Probes zu setzen gehört letztlich auch unabhängig von unserem Beispiel zu einer verantwortlichen Pflege der eigenen Kubernetes-Workloads. Wenn wir nämlich beispielsweise keine Readiness-Probe definieren, riskieren wir Downtime während eines Rollouts, weil der Kubernetes-Service dann sehr wahrscheinlich eingehende Requests zu früh auf neue Pods verteilt, bevor sie bereit sind zu antworten.)
Die zweite Frage können wir über den Gesundheitszustand von Service und Ingress beantworten: Wenn der Service gesund ist, sollte DNS innerhalb des Clusters funktionieren. Und wenn der Ingress und Ingress-Controller gesund sind, sollte der Service von außerhalb des Clusters erreichbar sein. Allerdings wird der Status des Ingress nur dann gesetzt, wenn ein Ingress-Controller installiert ist.
Hier wird kstatus im schlechtesten Fall eine falsch positive Meldung abgeben: Wenn keine Conditions vorhanden sind, wird eine Ressource standardmäßig als »Current« markiert. (Einen Ingress-Controller zu installieren gehört allerdings auch zu einer üblichen »Grundhygiene« in einem Kubernetes-Cluster.) An dieser Stelle können wir sehen, dass kstatus sich letztlich nicht gut für das Prüfen von Integrationen eignet, weil immer nur der Status einer einzelnen Ressource, nicht aber der Zustand der Verknüpfung mehrerer Ressourcen geprüft werden kann.
Die dritte Frage können wir in einem GitOps-Szenario nicht in der jeweiligen Situation beantworten, sondern nur grundlegend, und zwar mit »Ja«. Mit einem GitOps-Operator laden wir schließlich ständig das Config-Repo mit dem neuesten Image-Tag und wenden es kontinuierlich an. Somit ist quasi eine der »Grundannahmen unserer Welt«, dass unsere Workloads beziehungsweise deren Manifeste korrekt konfiguriert sind mit der neuesten Anwendungsversion. Nur wenn wir unserem GitOps-Operator grundlegend misstrauen würden, müssten wir an dieser Stelle zusätzliche Mechanismen einbauen.
Jobs können komplexere Tests mit kstatus abbilden.
Wir haben beim Ingress gesehen: Wenn wir uns nur auf die Status-Conditions unserer einzelnen Ressourcen verlassen, können wir uns leicht selbst täuschen – ganz so wie Unit-Tests ohne Integrationstests unvollständig sind. In Listing 7–2 auf Seite 220 haben wir allerdings ein Beispiel dafür gesehen, wie wir mittels eines Jobs einfache Tests innerhalb des Clusters ausführen lassen können. Auch Tools wie Testkube haben wir in jenem Abschnitt kennengelernt, über deren Custom Resources wir auch komplexere Tests abbilden und ausführen können. Mittels des Zustands solcher Jobs oder Testkube-Ressourcen können wir also gewisse Gesundheitsaspekte unserer Anwendung über kstatus abbilden. (Beim Job definieren wir diese Gesundheitsaspekte über Container-Image und -Befehl, bei Testkube über ausführliche Tests.)
Fassen wir noch einmal zusammen:
Helm ermöglicht gezieltes Testen mit Hooks.
Helm bietet neben Templating auch ein ausgefeiltes Release-Management an. Chart-Tests in Helm4 folgen einem ähnlichen Prinzip wie die eben referenzierten Jobs, nur sind sie in den Helm-spezifischen Releasezyklus eingebunden mithilfe von Hooks: Alle Ressourcen, die mit der Annotation helm.sh/hook="test" versehen sind, können nach dem Ausrollen eines Helm-Charts mit dem Befehl helm test angewandt werden.
Wenn ein Helm-Test fehlschlägt, wird das Helm-Release selbst nicht als fehlgeschlagen markiert. Das Helm-Release ist zwar keine Kubernetes-Ressource und kann somit auch gar keinen Kubernetes-Status haben, aber auch in der Helm-CLI werden wir mit helm ls sehen, dass ein Release, dessen Tests fehlschlagen, trotzdem als »deployed« angezeigt wird.
Mit einem Chart-Test können wir das Release also nicht als fehlgeschlagen markieren. Wenn wir stattdessen die Hook-Annotation ändern auf helm.sh/hook="post-install,post-upgrade", dann werden die entsprechend annotierten Ressourcen nach jedem Installieren oder Upgrade ausgeführt und das Helm-Release wird entsprechend als fehlgeschlagen oder deployed markiert.
Je nachdem, wie umfangreich und stabil unsere Tests im Helm-Chart sind, können wir je nach Kontext die Hook-Arten unserer Test-Workloads abwägen. Sehr leichtgewichtige Hooks mit reinen Smoke-Tests können durchaus geeignet sein für einen Post-Install- und Post-Upgrade-Hook. Was darüber hinausgeht, ist meist wahrscheinlich besser in einem Test-Hook aufgehoben.
Flux nutzt kstatus.
Flux verlässt sich standardmäßig auf kstatus, und auch alle CRDs von Flux exponieren den Konventionen gemäß Status-Conditions.
Wenn wir Flux nutzen und Kustomizations deployen, nutzen wir zwei Custom Resources (siehe Tabelle 7–2 auf Seite 209): eine Quelle (zum Beispiel ein GitRepository) und eine Kustomization als Ziel. Gelingt Flux das Ausrollen der Kustomization, wird die Kustomization-Ressource in den Conditions als gesund markiert.
Wir können bei Flux-Kustomizations auch noch zusätzliche Healthchecks einbauen5. Diese überprüfen den Kubernetes-Status der Ressourcen, die zur Kustomization gehören. Wenn diese es nicht innerhalb eines Timeouts (definiert als beispielsweise .spec.timeout="5m" für 5 Minuten) in einen gesunden Zustand schaffen, wird die Kustomization als fehlgeschlagen markiert. Wir können entweder auf alle Ressourcen warten, die in der Kustomization enthalten sind, indem wir .spec.wait=true setzen, oder stattdessen auf bestimmte (auch externe) Ressourcen warten mit .spec.healthChecks.
In Listing 8–2 zeigen wir als Beispiel eine Kustomization, die bis zu zehn Minuten darauf wartet, dass ein bestimmtes HelmRelease gesund ist. Diese Kustomization würde sich selbst dann als fehlgeschlagen ausweisen, wenn entweder ihre eigenen inkludierten Ressourcen nicht deploybar sind oder wenn das überprüfte HelmRelease innerhalb des Timeouts keinen gesunden Zustand erreicht.
Listing 8–2
Kustomization mit Healthcheck auf ein HelmRelease
1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: webapp
5
spec:
6
interval: 10m
7
prune: true
8
sourceRef:
9
kind: GitRepository
10
name: webapp
11
healthChecks:
12
- apiVersion: helm.toolkit.fluxcd.io/v2beta1
13
kind: HelmRelease
14
name: backend
15
namespace: dev
16
timeout: 5m
Synchrone Test-Jobs mittels mehrerer Kustomizations
Jobs sind die einzige Ressource, für die Flux das Status-Polling von kstatus mit eigenen Anpassungen überschreibt, damit deren Zustand korrekt in den Zustand einer Kustomization einfließt6. Flux bietet ebenso gesonderte Hinweise an für das Verwenden von Kustomizations zusammen mit Jobs, die vor oder nach dem Ausrollen ausgeführt werden sollen7: Man erstellt eine Kustomization für den Kern-Workload und eine zusätzliche Kustomization für den Job. Die Job-Kustomization enthält in diesem Fall eine Ressource wie beispielsweise den Job in Listing 7–2 auf Seite 220.
In Listing 8–3 sehen wir ein Beispiel dafür mit zwei Kustomizations, die zwar gleichzeitig angewandt werden, aber quasi nacheinander starten: Die erste Kustomization enthält den Kern-Workload und wird als Erstes deployt. Sie hat .spec.wait=true gesetzt, damit sie erst dann als gesund markiert wird, wenn alle ihre Ressourcen vollständig konvergiert sind. Die zweite Kustomization enthält einen Job, und ihre Angleichung wird mittels .spec.dependsOn erst nach dem Konvergieren der ersten Kustomization gestartet. Mittels .spec.force=true erzwingen wir das Neuerzeugen des Jobs, wenn sich unveränderliche Parameter ändern.
Listing 8–3
Zwei Kustomizations mit Reihenfolge
1
apiVersion: kustomize.toolkit.fluxcd.io/v1
2
kind: Kustomization
3
metadata:
4
name: webapp
5
spec:
6
sourceRef:
7
kind: GitRepository
8
name: webapp
9
path: "./core/"
10
interval: 5m
11
timeout: 2m
12
prune: true
13
wait: true
14
---
15
apiVersion: kustomize.toolkit.fluxcd.io/v1
16
kind: Kustomization
17
metadata:
18
name: webapp-test
19
spec:
20
dependsOn:
21
- name: webapp
sourceRef:
23
kind: GitRepository
24
name: my-app
25
path: "./post-deploy-tests/"
26
interval: 10m
27
timeout: 5m
28
prune: true
29
wait: true
30
force: true
Flux ermöglicht Helm-Hooks.
Wenn wir Helm-Charts mit Flux deployen, haben wir drei Custom Resources (siehe Tabelle 7–2 auf Seite 209): ein HelmRepository und ein HelmChart als Quellen und ein HelmRelease als Ziel. Da Flux die native Helm-Library nutzt, wird der Release-Zustand, den Helm ermittelt, auch in der HelmRelease-Ressource als Kubernetes-Status widergespiegelt. Wenn wir also beispielsweise Jobs mit Hook-Annotationen für Post-Install und Post-Upgrade inkludiert haben wie in Abschnitt 8.1.2 auf Seite 235, dann wird deren Erfolg oder Fehlschlag in den Gesundheitszustand des HelmRelease mit einbezogen.
Auch die Nutzung von Helm-Tests ist möglich8: Durch Setzen von .spec.test.enable=true werden Chart-Tests beim Installieren und Upgraden automatisch mit ausgeführt, und ihr Ergebnis fließt ebenfalls in den Gesundheitszustand des HelmRelease mit ein.
Argo CD nutzt eigene Healthchecks in Lua ohne kstatus oder Helm-Hooks.
Argo CD bietet die größte Flexibilität hinsichtlich Healthchecks. Der native Kubernetes-Status von Ressourcen spielt gar keine Rolle, stattdessen hat Argo CD komplett eigene Healthchecks definiert: Ein Ingress wird beispielsweise nur dann als gesund markiert, wenn .status.loadBalancer.ingress mindestens einen Wert für hostname oder IP enthält9. Momentan gibt es für acht der in Kubernetes eingebauten Ressourcentypen einen in Argo CD eigens definierten Healthcheck.
Diese Argo-CD-Healthchecks werden in der Programmiersprache Lua geschrieben. Mithilfe dieser Healthchecks kann man die Statustypen, die eine Ressource in ihren Conditions hat, auf die sechs Argo-CD-Statuswerte abbilden. Für einige Ressourcentypen, die nicht zu den Standard-Kubernetes-Ressourcentypen gehören, wurden solche Healthchecks bereits von der Community beigesteuert. (Die vollständige Liste aller Community-Healthchecks ist in den Resource-Customizations von Argo CD zu finden10.)
Es gab Diskussionen darüber, kstatus in Argo CD zu integrieren11, aber das Thema scheint momentan eher zweitrangig zu sein. Ein eindeutiges Mapping von Argo-CD-Status zu kstatus-Werten ist ebenfalls nicht möglich: Für »Terminating« bei kstatus gibt es kein Äquivalent bei Argo CD, während es für Argo CDs »Suspended« keine Entsprechung bei kstatus gibt.
Im Gegensatz zu Flux gehören auch Helm-Hooks nicht zu Argos Repertoire, weil Argo CD nicht die Helm-Library zum Ausrollen verwendet, sondern nur die Templates als Manifeste rendert und anschließend anwendet.
Wie und worüber können unsere GitOps-Operatoren benachrichtigen, wenn sich der Gesundheitszustand von Applications, Kustomizations oder HelmReleases verändert?
Abschnitt 4.9 auf Seite 82 stellt für Flux und Argo CD bereits zwei Möglichkeiten vor: Alerting über Metriken und Notification-Controllers. Unserer Erfahrung nach ist der Start mittels der eventbasierten Notification-Controllers einfacher als die Nutzung von Metriken. Bei Metriken kann man nicht aus einer vorgefertigten Auswahl an Alerts wählen, sondern muss sich auf Basis der vorhandenen Metriken frei überlegen, welche Alerts sinnvoll sind. Dazu muss man dann passende Queries schreiben, was komplex, fehleranfällig und aufwendig sein kann.
Trotzdem kann es insgesamt Sinn ergeben, das Alerting über Metriken zu nutzen. Ein Vorteil davon ist, dass wir damit unser gesamtes Alerting zentral in einem Tool abbilden können. Abb. 4–7 auf Seite 83 zeigt hierfür beispielsweise Grafana oder Prometheus Alertmanager. Und am Ende dieses Kapitels in Abschnitt 8.3 auf Seite 245 gehen wir auf noch ganzheitlichere Herangehensweisen ein.
Im Folgenden nehmen wir jedoch vor allem die Funktionsweise der Notification-Controllers von Flux und Argo CD in den Fokus.
Flux bietet Alerts und Providers.
Flux hat für Benachrichtigungen einen zusätzlichen Ressourcentyp im Gepäck: den Alert12. Mithilfe des Alert bestimmt man, welche Ressourcen man überwachen will und ab welchem Schweregrad eine Benachrichtigung verschickt wird. Zusätzlich zum Alert wird eine weitere Custom Resource definiert, um das Benachrichtigungsziel anzugeben: einen Provider13.
Im Beispiel in Listing 8–4 sehen wir ein Setup, in dem Benachrichtigungen an einen Slack-Kanal verschickt werden. Benachrichtigungen werden nur dann verschickt,
Wenn eine Kustomization aktiv wartet auf alle oder bestimmte Subressourcen (siehe Abschnitt 8.1.3 auf Seite 235), dann wird ein Überschreiten des Timeouts ebenfalls als Error geloggt und als Benachrichtigung verschickt.
Listing 8–4
Ein Alert und ein Provider in Flux
1
apiVersion: notification.toolkit.fluxcd.io/v1beta2
2
kind: Provider
3
metadata:
4
name: slack-bot
5
namespace: flux-system
6
spec:
7
type: slack
8
channel: general
9
address: https://slack.com/api/chat.postMessage
10
secretRef:
11
name: slack-bot-token
12
---
13
apiVersion: notification.toolkit.fluxcd.io/v1beta2
14
kind: Alert
15
metadata:
16
name: slack
17
namespace: flux-system
18
spec:
19
summary: "Cluster addons impacted in us-east-2"
providerRef:
21
name: slack-bot
22
eventSeverity: error
23
eventSources:
24
- kind: GitRepository
25
name: '*'
26
- kind: Kustomization
27
name: '*'
Nur wenige Möglichkeiten zur Filterung
Im Alert haben wir folgende Möglichkeiten der Filterung:
Wir können beliebig viele Alert-Ressourcen erstellen, um beispielsweise pro Ressourcentyp und pro Namespace unterschiedliche Severities zu konfigurieren und unterschiedliche Regexes auszuschließen. Jeder Alert kann allerdings nur an einen Provider gebunden werden. Um einen Alert an mehrere Provider zu verschicken, muss man mehrere Alerts erstellen.
In der Praxis haben sich die Filtermöglichkeiten in Flux-Alerts oft als sehr begrenzt erwiesen, sodass es zumindest anfänglich zu einem hohen Aufkommen an verschickten Alerts kommt. Ein Hintergrund mag sicherlich sein, dass Flux-Alerts einfach Kubernetes-native Events der Flux-Ressourcen abgreifen und nur auf deren Message filtern, die ein freier Text inklusive variabler Fehler-Logs sein kann, nicht aber auf deren Reason, die ein nicht variabler Kurzcode für den Event-Typ ist.
Wir stellen auf GitLab einen bewährten Flux-Alert bereit, der auf Errors filtert und bereits einige irrelevante Messages ignoriert14.
Vielfältige Benachrichtigungsdienste
Die knapp 20 Provider-Typen, die Flux anbietet15, lassen sich grob in folgende Kategorien einsortieren:
Argo CD Notifications nutzt Trigger, Templates und Subscriptions.
Früher gab es einen separaten Controller namens »Argo CD Notifications«; dieser hat mittlerweile eine Heimat in Argo CD selbst gefunden und ist somit Teil der Kernfunktionalität geworden. Das Grundprinzip besteht aus Triggern, Templates, Notification Services und Subscriptions17 (siehe Listing 8–5 für ein Beispiel):
Listing 8–5 zeigt ein Beispiel mit mehreren Manifesten, das Folgendes enthält:
Listing 8–5
Trigger, Template, Secret und Application mit Subscription Annotation in Argo CD
1
apiVersion: v1
2
kind: ConfigMap
3
metadata:
4
name: argocd-notifications-cm
5
data:
6
template.app-sync-failed: |
7
email:
8
subject: >-
9
Failed to sync application
10
{{.app.metadata.name}}.
11
message: >-
12
{{if eq .serviceType "slack"}}:exclamation:{{end}}
13
The sync operation of application
14
{{.app.metadata.name}} has failed!
15
trigger.on-sync-failed: |
16
- description: App sync has failed
17
send:
18
- app-sync-failed
19
when: >-
20
app.status.operationState.phase
21
in ['Error', 'Failed']
22
service.email.gmail:
23
username: $email-username
24
password: $email-password
25
host: smtp.gmail.com
subscriptions: |
27
- recipients:
28
- email:gmail
29
triggers:
30
- on-sync-failed
31
---
32
apiVersion: v1
33
kind: Secret
34
metadata:
35
name: argocd-notifications-secret
36
stringData:
37
email-username: EMAIL_USER
38
email-password: PASSWORD
39
---
40
apiVersion: argoproj.io/v1alpha1
41
kind: Application
42
metadata:
43
# ...
44
annotations:
45
notifications.argoproj.io/subscribe.on-sync-failed.slack:
46
channel-name-1;channel-name-2
47
name: backend
48
namespace: argocd
49
spec:
50
# ...
Argo CD ermöglicht komplexe Benachrichtigungen.
Mit Argo CD können wir vielfältigste Anforderungen hinsichtlich Alerting erfüllen, aber wir haben auch eine entsprechende Komplexität zu verwalten. Argo CD liefert nämlich keine Trigger oder Templates in der Standardinstallation aus. Um dennoch zügig starten zu können, bietet Argo CD einen vorkonfigurierten Katalog an Triggers und Templates an18.
Ein praxisnahes Beispiel für den Start mit Notifications in Argo CD bietet der GitOps Playground19. Hier findet die Konfiguration in der values.yaml des Helm-Charts statt, woraus dann die oben erwähnte ConfigMap generiert wird.
Das Beispiel sendet Alerts per E-Mail nur bei einer kleinen, praxiserprobten Auswahl von defaultTriggers. Die Subscription erfolgt pro Team/Mandant mittels Annotation am jeweiligen AppProject20.
Benachrichtigungsdienste vergleichbar mit Flux
Argo CD bietet ähnlich wie Flux knapp 20 Dienste an, die in die gleichen Kategorien wie bei Flux passen. Zehn der Dienste überschneiden sich zwischen beiden Tools. Bei Messenger-Diensten bietet Argo CD etwas mehr, dafür gibt es weniger Auswahl bei Automatisierungszielen und Git-Commit-Status-Updates. Allerdings sind beide letzteren Kategorien fast immer auch über generische Webhooks abdeckbar.
In Abb. 8–1 zeigen wir beispielhaft eine Benachrichtigung aus Argo CD in Mattermost.
Abb. 8–1
Benachrichtigung aus Argo CD nach Mattermost über einen erfolgreichen Application Sync
Wir sind nun in der Lage, mit den Bordmitteln unserer GitOps-Operators den Gesundheitszustand unserer Applications, Kustomizations und HelmReleases zu überwachen und Benachrichtigungen zu erhalten, wenn Ressourcen in einen abnormalen Zustand geraten. Das allein kann aber nur ein erster Baustein sein für eine ganzheitliche Strategie zum Betrieb unserer Anwendungen.
Wir können viele Fragen in diesem Zustand noch nicht beantworten. Dazu gehören unter anderem folgende Themenfelder: