GitOps mit Argo CD im Einsatz

10.12.2020 Raffael Schneider
DevOps Cloud CI/CD Infrastructure-as-Code Kubernetes Hands-on

Argo ist ein Open Source-Projekt in aktiver Entwicklung das mehrere Kubernetes-native-Applikationen bereitstellt. Argo ist in der Cloud Native Computing Foundation als Incubating-Projekt aufgelistet und hat sich dementsprechend bereits in der Cloud etablieren können. Argo-Applikationen kümmern sich um Workflows, Events und CI/CD in einem Kubernetes-Cluster. Eines dieser Applikationen heisst Argo CD.

Argo CD ist ein Tool für deklarative Continous Delivery für Kubernetes, dass das GitOps-Pattern nutzt. Wie in einem unserer älteren Blogbeitrag bereits beschrieben, gilt es bei GitOps durch Git-Repos als 'single source of truth' zu nutzen um einen Cluster deklarativ per 'Infrastructure-as-Code' zu beschreiben. Per Merge-Request wird ein neue Änderung an der Infrastruktur vorgenommen und sobald der Change akzeptiert wird, wird eine CD-Pipeline angestossen, die die Infrastruktur auf den Zielzustand bringt. Argo CD übernimmt genau diese Funktion in einem Kubernetes-Cluster. Somit ist Argo CD eine mögliche Implementation von GitOps in einem Cluster-Umfeld. Argo CD nutzt dafür Kubernetes-nativen Features wie Controllern und CRDs.

Die End-to-End CI/CD Architektur

Konkret stellt Argo CD eine GitOps-driven CI/CD-Pipeline(s) zur Verfügung. Diese CI/CD-Pipeline führt in einer klassischen Ausführung folgende Schritte aus:

  1. Der Entwickler führt einen Commit in einem Git-Repo (bspw. GitHub, BitBucket, GitLab, usw.) aus.
  2. Ein CI-Workflow wird angestossen. (Linting, Testing, usw.)
  3. Ein Docker-Container wird erstellt und in eine Container-Registry (bspw. DockerHub, GCR, Amazon ECR, usw.) hochgeladen.
  4. Kubernetes-Manifest(s) werden generiert und ein durch Argo CD-geführtes, separates Repo commited.
  5. Argo CD erkennt eine Änderung am Zielzustand und deployed eine neue Infrastruktur oder Applikation in den vorkonfigurierten Kubernetes-Cluster.

Genau diesen Vorgang kann man ganz schön am offiziellen Architekturdiagramm (Quelle: Argo CD) von Argo CD wie unten ersichtlich sehen:

argo-cd-architecture

Im Diagram fallen auch gleich die verschiedenen Features von Argo CD auf. Der Nutzer greift per CLI oder Web-UI auf Argo CD zu oder kann programmatisch per gRPC oder REST-Schnittstelle Argo CD ansprechen. Argo CD kann dabei auch auf andere Kubernetes-Cluster als die eigene deployen. Dies geschieht auch über gRPC oder die REST-Schnittstelle.

Webhooks-Integration für unterschiedliche Aktionen für externe Consumer, wie beispielsweise eine Benachrichtigung bei erfolgreichen oder eben nicht erfolgreichen Deployments in einem relevanten Slack-Channel zu verschicken, werden mit Argo CD möglich. Auch komplexere Rollouts mit zusätzlichen Aktionen bei PreSync-, Sync-, oder PostSync-Zuständen sind möglich.

Argo CD ist zudem komplett Enterprise-fähig und unterstützt gängige Infrastruktur-Bausteine wie SSO, RBAC, Monitoring (mit Prometheus) oder Security-Protokolle.

Die Argo-Magic

Die Idee bei Argo CD ist dass ein Zielzustand einer Infrastruktur, genannt target system, durch ein Manifest beschrieben wird. Argo CD überprüft, ob der Zielzustand im laufendem Betrieb, genannt live system, vorhanden ist. Falls nicht, hebt Argo CD den Zustand an und deployed in der Regel das Delta zwischen Target- und Live-Sytem.

Da das Delta zwischen Target und Live immer nur auf einen Change ins Git-Repo zurückzuführen sein sollte –das Git-Repo gilt als single source of truth–, ist der Git-Prozess für das Triggern eines Sync-Prozess (sprich Deployment) entscheidend. Die Entscheidungsträger sind somit Leute, die das Git-Repo auch managen und Merge-Requests akzeptieren. Somit liegt die Kontrolle des Ops bei den Entwickern, genau wie DevOps es vorsieht.

Argo CD ist sehr flexibel in Bezug auf das Manifest. Dieses kann wahlweise in folgenden Formaten geschrieben sein:

  • Plain YAML
  • Ksonnet
  • Jsonnet
  • Helm
  • Kustomize

Genau diese Flexibilität macht Argo CD zu einem Schweizer Messer für CI/CD-Pipelines im Kubernetes-Umfeld.

In einem späteren Schritt, werden wir eine Applikation in einer 'Argo CD'-Pipeline in einem lokalen Kubernetes-Cluster laufen lassen. Dabei benutzt die Applikation auch ein Manifest zur Beschreibung dessen Target-Zielzustands. Ein solches Manifest kann beispielsweise in plain YAML wie folgt aussehen:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook-ui
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: guestbook-ui
  template:
    metadata:
      labels:
        app: guestbook-ui
    spec:
      containers:
      - image: gcr.io/heptio-images/ks-guestbook-demo:0.2
        name: guestbook-ui
        ports:
        - containerPort: 80
kind: Service
metadata:
  name: guestbook-ui
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: guestbook-ui        

Das obige yaml-File entspricht dem guestbook-ui-deployment.yaml und dem guestbook-ui-svc.yaml des argocd-example-apps-Repo, die wir im gleich im Anschluss nochmals nutzen werden.

Aufsetzen von Argo CD

Auf der offiziellen Argo CD-Webseite wird das Aufsetzen eines Hello-World Beispielprojekts hier beschrieben. Für unseres Beispieles nehmen wir das gleiche Git-Repo mit denselben Manifests zur Hand und passen dieses leicht an.

Voraussetzungen

Folgende Voraussetzungen müssen im Vorfeld bereits vorhanden sein um das Aufsetzen von Argo CD vornehmen zu können:

  • der Guide ist für das lokale Aufsetzen auf Mac OS ausgelegt
  • kubectl installiert
  • eine kubeconfig-File soll vorhanden sein (Default-Verzeichnis ist ~/.kube/config)

Lokale Installation von Argo CD

Argo CD wird mit einer CustomResourceDefinition auf einem Kubernetes-Namespace installiert. Dafür erstellen Sie zuerst neuen Namespace mit dem Namen argocd wie folgt:

$ kubectl create namespace argocd

Anschliessend installieren Sie Argo CD mit dem offiziellen Manifest (CustomResourceDefinition) auf dem neu erstellten Namespace:

$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Jetzt sollte in Ihrem lokalen Kubernetes-Cluster einen Namespace argocd mit Argo CD laufen. Jetzt installieren wir noch die Argo CD CLI. Dies kann wahlweise mit manuell oder mit Homebrew installiert werden. Aus phlegmatischen Gründen verwenden wir Homebrew. Falls Sie Homebrew installiert haben, führen sie einfach folgenden Befehl mit brew aus:

$ brew install argocd

Anmelden Argo CD

Bevor wir Argo CD nutzen können, müssen wir noch den Argo CD API-Server IP-technisch exponieren. Dafür können wir ein klassisches Port-Forwarding nutzen und binden den Cluster-internen Port 443 auf den externen Port 8080. Führen Sie dazu folgenden Befehl wie folgt aus:

$ kubectl port-forward svc/argocd-server -n argocd 8080:443

Das initiale Passwort für den Login wird automatisch generiert und entspricht stets dem Pod-namen des Argo CD API-Servers. Der Pod-Name kann wie folgt herausgefunden werden:

$ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2

Melden Sie sich zuerst mit dem admin-Nutzer an. Nutzen Sie die IP als Zielcluster <ARGOCD_SERVER> und das obig eruierte Passwort für den Admin-User.

$ argocd login <ARGOCD_SERVER>

Das Passwort kann wie folgt geändert werden:

$ argocd account update-password

Erstellen einer App anhand eines Git-Repo

Argo CD stellt exemplarische Applikationen bereit, die wir in der hiesigen Beispielinfrastruktur nutzen können. Das Repo ist unter https://github.com/argoproj/argocd-example-apps einsehbar. Wir werden eine Applikation mit dem Namen guestbook erstellen, die das Repo verwenden wird.

Man kann die Applikation wahlweise per CLI oder per Web-UI erstellen lassen. Wir werden hier beide Möglichkeiten beschreiben.

Erstellen der App mit der CLI

Um die Applikation per CLI zu erstellen, nutzen Sie die argocd-CLI wie folgt:

$ argocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default

Dabei wird das Repo als Parameter mit dem Flag --repo mitgegeben. Das zu verwendende Projekt wird mit dem Flag --path angegeben.

Erstellen der App mit der Web-Oberfläche

Nehmen Sie ihren Browser der Wahl zur Hand und rufen Sie https://localhost:8080/ auf. Sie werden ein Login-Fenster sehen. Nutzen sie den admin-User mit dem Passwort das wir vorhin im obigen Schritt eruieren konnten.

Nach erfolgreichem Login sollten Sie folgende Web-Oberfläche sehen. Hier ist noch keine Applikation vorhanden.

argo-cd-ui-blank

Um die Applikation zu erstellen, klicken auf + NEW APP. Im folgenden Modal, nutzen Sie guestbook als Applikation Name, default für Project und Manual für die Sync Policy.

Weiter unten im gleichen Modal, verwenden Sie https://github.com/argoproj/argocd-example-apps.git für die Repository URL, HEAD für Revision und guestbook für Path.

Im Destination-Tab, verwenden Sie https://kubernetes.default.svc für Cluster und default für den Namespace. All diese Optionen entsprechen den Parametern, die obig für den einzeiligen CLI-Ausdruck verwendet worden sind.

Bestätigen Sie die Erstellung der Applikation mit dem CREATE-Button (ganz oben im Modal).

In der Web-Oberfläche ist die Applikation guestbook im Dashboard ersichtlich.

argo-cd-ui-guestbook-app

Sync der Applikation

Der Sync entspricht dem Abstimmen zwischen dem laufendem Zustand (live state) und dem erwünschten Zielzustand (target system). Unsere Applikation wurde zwar von Argo CD geladen, entspricht aber noch nicht dem Zielzustand, da die Applikation noch nicht läuft, bzw. deployed wurde. Das heisst, dass das Anstossen des Sync-Prozesses die Applikation deployed wird um den Zielzustand erreichen zu können.

Der Sync kann genau wie das Erstellen einer Applikation per CLI oder per Web-UI gemacht werden. Wir werden –genau wie vorhin– beide Varianten durchlaufen.

Syncen der App mit der CLI

Zuerst überprüfen wir, ob die guestbook-Applikation korrekt erstellt wurde. Dazu nutzen wir den argocd app get-Befehl der CLI wie folgt:

$ argocd app get guestbook
Name:               guestbook
Project:            default
Server:             https://kubernetes.default.svc
Namespace:          default
URL:                https://localhost:8080/applications/guestbook
Repo:               https://github.com/argoproj/argocd-example-apps.git
Target:             
Path:               guestbook
SyncWindow:         Sync Allowed
Sync Policy:        <none>
Sync Status:        OutOfSync from  (1ff8a67)
Health Status:      Missing

GROUP  KIND        NAMESPACE  NAME          STATUS  HEALTH   HOOK  MESSAGE
       Service     default    guestbook-ui  OutOfSync  Missing      
apps   Deployment  default    guestbook-ui  OutOfSync  Missing      

Der Status ist hierbei noch OutOfSync. Das heisst noch nicht deployed, und keine Kubernetes-Resources wurden erstellt. Um den Sync-Prozess anzustossen, führen Sie ganz einfach den folgenden Befehl aus:

$ argocd app sync guestbook

Überprüfen Sie nochmals den Status von der Applikation. Jetzt sollte der Status Synced und die Health Healthy sein.

Syncen der App mit der Web-Oberfläche

In der Web-Oberfläche kann der Sync-Prozess genauso leicht angestossen werden. Der SYNC-Button auf der guestbook-Applikation stösst genau den gleichnamigen Prozess an. Bestätigen Sie noch im nachfolgenden Modal mit Synchronize.

Beim Aufruf der Applikation wird nach erfolgreichem Sync der Status sowie die Health wie unten angezeigt.

argo-cd-ui-synced

Herzlichen Glückwunsch! Jetzt haben Sie ihre erste GitOps-fähige CI/CD-Pipeline erstellt. Es war doch nicht so schwer wie ursprünglich vermutet.

Zum Schluss kann man noch die eigentliche guestbook-Applikation aufrufen. Dafür muss der Port noch entsprechend exponiert werden. Führen Sie den nachstehenden Befehl aus und rufen Sie im Browser im Anschluss http://localhost:8000/ auf:

$ kubectl port-forward svc/guestbook-ui 8000:80

guestbook-ui

Fazit

Der Weg von der hier aufgeführten lokalen Instanz von Argo CD in ihr Daily-Business erfordert doch ein wenig mehr Know-how über CI/CD und Argo CD. In der realen Welt stellen sich noch weitere Fragen wie man am besten einen GitOps-Prozess designen und ausrollen sollte.

Argo CD schlägt hierbei den richtigen Weg ein und macht auf den ersten Blick einen guten Eindruck. Eine Kubernetes-native CI/CD-Lösung, die das GitOps-Pattern gekonnt implementiert, sucht zurzeit seinesgleichen. Wir bei b-nova werden uns vermehrt noch mit dem DevOps-Thema auseinandersetzen und die Best-Breeds für genau Ihren Use-Case anwenden zu wissen.

Raffael Schneider – Crafter, Disruptor, Freigeist. Als begeisteter GitOps-Enthusiast schreibt Raffael gerne über Programmiersprachen, Themen rund um DevOps und hat ein Faible für die neusten IT-Hypes aller Art.