GitOps in der Praxis

Den Lebenszyklus einer Software über Git abzubilden, hat zahlreiche Vorteile für Softwareentwickler.

In Pocket speichern vorlesen Druckansicht 11 Kommentare lesen

(Bild: bearsky23/shutterstock.com)

Lesezeit: 13 Min.
Von
  • Jan Gertgens
Inhaltsverzeichnis

Typische Softwareprojekte nutzen zahlreiche Werkzeuge zum Bau und zur Installation von Software, die zudem über viele Server in der Infrastruktur verteilt sind. Eine Pipeline besteht in der Regel aus einem CI-Server, einem Sourcecode-Repository, einem Artefakt-Server und gegebenenfalls einem Server zur Unterstützung beim Ausrollen.

Meist sind der Code der Build Jobs, die Deployment-Konfigurationen der Anwendungen und die Beschreibung der Infrastruktur unversioniert abgelegt. Das verhindert eine durchgängige Versionierung aller Artefakte des Softwareprojektes. Daraus ergibt sich ein höherer manueller Aufwand beim Verteilen und Testen der Software.

An der Stelle kommt GitOps ins Spiel. Das Verfahren sorgt dafür, dass der gesamte Inhalt eines Projektes als sogenannte Single Source of Truth (SSOT) in der Versionsverwaltung Git liegt. Ein Softwareentwicklungsprojekt dient im Folgenden als Beispiel für das Vorgehen.

GitOps beschreibt ein Vorgehen, bei der das Source-Code-Verwaltungswerkzeug Git als zentrale Komponente dient, um den gesamten Lebenszyklus einer Software abzubilden. Das geht von der Entwicklung und dem Bau der Software über das Erzeugen der lauffähigen Artefakte bis zum Ausrollen und Warten. Die Beschreibung der Infrastruktur und der Konfiguration der Jobs zum Bauen der Software liegen ebenfalls als Source Code in Git. Dieses Vorgehen erhöht das Maß der Automatisierung der Deployments und der Installation der Infrastruktur.

Ein weiteres wichtiges Grundprinzip von GitOps ist das automatische Erkennen von Änderungen in der Beschreibung des Deployment oder des Sollzustands der Anwendung. Die Grundlage hierfür bildet die deklarative Beschreibung des Ausrollprozesses. Auf die Weise versucht beispielsweise Kubernetes anhand der Deklaration den beschriebenen Zustand des Deployment herzustellen. Das System überwacht ein zugehöriges Repository in Git und stellt bei jeder Änderung wie dem Hinzufügen weiterer Instanzen den neuen Zustand automatisch her.

Der ausschlaggebende Unterschied zwischen GitOps und dem Continuous-Integration-Verfahren CIOps ist die Art, wie Deployments angestoßen werden. GitOps setzt auf eine Überwachung des Infrastruktur-Repository und reagiert auf Änderungen des dort abgelegten Sourcecodes. Bei CIOps stoßen dagegen beispielsweise Trigger- oder Schedule-Jobs explizit das Ausrollen des Infrastruktur-Repository an.

Das Demoprojekt für diesen Artikel setzt sich aus gängigen Werkzeugen für die Softwareentwicklung zusammen. Als Zielplattform dient ein Kubernetes-Cluster. Das Beispiel richtet einen Spring-Microservice mit einer MongoDB im Cluster ein. Darüber hinaus dient die Webvariante von GitLab als Versionsverwaltung und die Docker-Registry zum Erstellen des Microservice, das GitOps-Werkzeug zum Überwachen des Repository und für das Deployment ist ArgoCD zuständig.

Architektur und Ablauf eines Deployments des Projekts

GitLab kommen im Projekt vielseitige Aufgaben zu. Es ist zunächst das Sourcecode-Repository und für das Erstellen der Anwendung verantwortlich. Zum Bau der Anwendung dienen Basis-Images von Docker Hub. Das Erstellen der Java-Archive als Executable JAR erfolgt mit einem maven:3.3.9-jdk-8-Image. Für das Docker Image greift ein docker:latest, das die benötigte Docker Executable enthält. Damit ergibt sich folgender Build Job:

stages:
  - build
  - docker
.docker: &docker
   image: docker:latest
   stage: docker
   services:
     - docker:dind
   only:
     - master
.build-maven: &build-maven
   image: maven:3.3.9-jdk-8
   stage: build

build-master:
  <<: *build-maven
  stage: build
  script:
    - 'mvn install'
  only:
    - master
  artifacts:
  paths:
    - target/*.jar

docker-build-and-push:
  <<: *docker
  dependencies:
    - build-master
  script:
    - docker login -u "$CI_REGISTRY_USER"\
       -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY

    - docker build -t\
  registry.gitlab.com/artikel-gitops/refimpl:0.0.1-SNAPSHOT .

    - docker push \
  registry.gitlab.com/artikel-gitops/refimpl:0.0.1-SNAPSHOT

Nach dem Bau der Anwendung steht das Hochladen des Docker-Image in die private Docker-Registry des GitLab-Projekts an. Die Zugangsdaten für den Docker-Log-in stellt GitLab als Umgebungsvariablen zur Verfügung. Zum Ausrollen kommt ein eigens erstelltes Image zum Einsatz, das die CLIs (Command Line Interfaces) von Kubernetes und ArgoCD mitbringt. Des Weiteren müssen Entwickler die passende kubeconfig in das Image kopieren, um den Zugang zum Kubernetes-Cluster zu ermöglichen:

FROM ubuntu:18.04
COPY files/kubeconfig kubeconfig
ENV KUBECONFIG="kubeconfig"

# Install kubectl
RUN apt-get update && \
    apt-get install -y apt-transport-https curl gnupg2

RUN curl -s \
  https://packages.cloud.google.com/apt/doc/apt-key.gpg \
  | apt-key add -
RUN echo \
  "deb https://apt.kubernetes.io/
kubernetes-xenial main" \
  | tee -a /etc/apt/sources.list.d/kubernetes.list

RUN apt-get update && \
    apt-get install -y kubectl

RUN export VERSION=$(curl --silent \
  "https://api.github.com/repos/argoproj/argo-cd/releases/latest"\
  | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/') && \
  curl -sSL -o /usr/local/bin/argocd \
  https://github.com/argoproj/argocd/releases/download/\
$VERSION/argocd-linux-amd64 && \
  chmod +x /usr/local/bin/argocd

COPY scripts/* /usr/local/bin/
RUN chmod +x /usr/local/bin/prepareEnv

Das Aufsetzen des Clusters erfolgt mit der schlanken Kubernetes-Distribution k3s, die sich durch eine einfache Installation auszeichnet. Zusätzliche Konfigurationen oder Werkzeuge sind nicht erforderlich. Folgende Befehlszeile installiert den Cluster:

curl -sfL https://get.k3s.io | sh -.

Als Dashboard dient k8dash:

kubectl apply -f \
  https://raw.githubusercontent.com/indeedeng/k8dash/\
master/kubernetes-k8dash.yaml

Ein zentrales Werkzeug des GitOps-Konzepts im Beispielprojekt ist der ArgoCD-Server. Er überwacht ein definiertes Git-Repository als Single Source of Truth, in dem der herzustellende Zustand der Anwendung als Sourcecode liegt. Helm ist im Projekt die Grundlage für die Deployments nach Kubernetes. Zunächst gilt es, die Repositories über die Oberfläche des ArgoCD zu konfigurieren.

Konfigurierte Repositories in ArgoCD

Die Helm-Konfiguration für die Anwendung liegt direkt in einem Unterordner des Repository der jeweiligen Anwendung. Hinzu kommen zwei öffentliche Helm-Repositories für das Deployment der MongoDB. Die installierten Anwendungen lassen sich über ArgoCD-Projekte organisieren. Für die Verteilung der Anwendungen kommt ausschließlich das Default-Projekt von ArgoCD zum Einsatz. In der Oberfläche des ArgoCD-Servers sind die Zustände der installierten Anwendungen einsehbar, und die Projektübersicht lässt sich nach Namespaces, Labels, Clustern und ArgoCD-Projekten filtern.

Projektübersicht ArgoCD Server

In der Detailansicht lässt sich der Status jeder installierten Kubernetes-Ressource darstellen. Nutzer können aus der Übersicht zudem eine manuelle Synchronisation anstoßen und einzelne Kubernetes-Ressourcen löschen.

Übersicht Kubernetes-Ressourcen

Um die Überwachung eines Repository und das automatische Ausrollen zu konfigurieren, gilt es zunächst eine Anwendung mit dem passenden Sourcecode-Repository anzulegen. Es gibt zwei Wege, eine Anwendung in ArgoCD zu erstellen. Da sich das Erstellen über die Oberfläche schwer automatisieren lässt, nutzt das Beispielprojekt die zweite Variante, die eine Automatisierung über das ArgoCD-CLI ermöglicht. Die Anwendung erhält die Konfigurationen als Parameter. Der Zugriff über die Kommandozeile erfolgt im Projekt automatisiert mit einem Skript, um die Anwendung über Umgebungsvariablen im Kubernetes-Cluster zu installieren.