lars
webmobiledatenbankendevopsarchitektur
hello (at) larskoelpin.de

GitOps Ebenen und Tooling

October 16, 2022
opskubernetes

In einem voherigen Beitrag habe ich das Grundkonzept von GitOps erklärt. Dieses sieht es vor den Zustand von Infrastruktur und Konfigurationen als Code abzubilden und diesen Zustand immer wieder herzustellen. Das Problem ist, dass dieses Modell nicht immer angewandt werden kann. Um zu verstehen, wo das der Fall ist, müssen erst die Ebenen erklärt werden, die durch Code abgebildet werden könnnten.

Ich habe dafür vier Ebenen identifiziert, die jeweils eine API für die darunterliegende Ebene anbieten.

  • Hardware-Ebene
  • Betriebsystem-Ebene
  • Orchestrations-Ebene
  • Laufzeit-Ebene / Container-Ebene

Dabei sind die Grenzen zwischen diesen Ebenen natürlich fließend. Gewisse Ebenen können sogar vollkommen ausgelassen werden. Möchte ich einen Softwaredienst anbieten, benötige ich zunächst die Hardware (CPU, RAM), sowie Netzwerk-Komponenten um diese Hardware zu vernetzen. Auf dieser Hardware wird ein Betriebssystem, meistens Linux, installiert. Dieses stellt eine Schnittstelle zur Hardware bereit, um diese programmatisch Nutzen zu können.

Auf dem Betriebssystem wird in einigen Fällen die Applikation direkt selbst, nativ in ihrer Laufzeitumgebung oder als Container, ausgeführt.

Bei hochskalierbaren Systemen kommt eine zusätzliche Software, der Orchestrator (z.B. Kubernetes), ins Spiel. Dieser übernimmt die Verwaltung der betrieben Applikationen und dessen Konfigurationsmanagement.

Bei GitOps bzw. Infrastructure-As-Code (IaC) ist zunächst die Idee, dass die IT-Landschaft per Code abgebildet werden kann.

Es ist natürlich schwer selbst betriebene Hardware per Code abzubilden, denn wie würde das in der Praxis aussehen? Eventuell ist theoretisch ein Skript denkbar, das Hardwarekomponenten bei einem Hardware Versandhandel bestellt, wenn diese im eigenen Datenzentrum noch nicht verfügbar sind, und diese beim Abbau von bei Lasten, diese bei einem Drittanbieter Markt wieder verkauft.

Da solche Szenarien eher unüblich sind, ist sind für IaC Cloud-Computing und Hosted Solutions die sehr viel angenehmere Alternative. Diese bieten das oben genannte Szenario üblicherweise als API an, ohne dass physisch Dinge gekauft und verkauft werden. Und genau für dieses Hardware kaufen/Verkaufen bieten sich Wekrzeuge an, die auf dieser Ebene ihre Stärken ausspielen.

Bild 1: Ebenen
Bild 1: Ebenen

Dazu gehören beispielsweise Werkzeuge wie Terraform oder CloudFormation. Diese ermöglichen abstrakt betrachtet das Codifizieren von Bestellprozessen von Hardware. Häufig wird bei diesem Prozess bereits ein Betriebssystem gewählt, das für die folgende Ebene bereitgestellt wird.

Da Betriebsysteme konfiguriert werden, um Software lauffähig zu machen, kommen Werkzeuge wie Cloud-Init oder Ansible zum Einsatz. Diese sind für diesen Anwendungsfall ausgelegt Betriebssysteme zu konfigurieren. Diese Ebene übernimmt weiterhin die Grundlage für die nächste Ebene. Das bedeutet in der Praxis, dass hier die für die Applikationen benötigte Laufzeitumgebung/Containerumgebung installiert wird, oder, wenn es ihn gibt, der Orchestrator installiert wird.

Wird ein Orchestrator wie Kubernetes oder Docker(-Swarm) eingesetzt, übernimmt dieser das Konfigurationsmanagement für die Applikationen selbst. Er bietet Schnittstellen für Geheimnisverwaltung oder Konfigurations-Management selbst. Werkzeuge wie FluxCD, docker-compose oder in gewisser Art auch Helm und kustomize sind hier anzusiedeln.

Die letzte Ebene, die Laufzeitebene wird häufig durch Containerisierung, bzw. Dockerfile abgebildet. Sowohl die Laufzeitumgebung, als auch die Containerumgebung, wird dabei von der Betriebssystemebene mit installiert.

Natürlich ist es so, dass verwaltete Dienste einzelne Ebenen wegabstrahieren und somit Ebenen für den Endanwender übersprungen werden. Beispielsweise können komplett verwaltete Kubernetes-Cluster angemietet werden, ohne die entsprechende Hardware oder dessen Operating-System zu kennen.

Der Schritt zu GitOps

Es existieren also verschiedene Ebenen im Stack, der durch die verschiedenen Werkzeuge durch Code abgebildet werden können. Jetzt ist es so, dass das klassische GitOps eher ein “Pull”-Modell bevorzugt. Das heißt also, dass es Operatoren gibt, die einen IST-Zustand mit einem SOLL-Zustand aus einem VCS-Repository abgleichen und die Änderungen vornehmen.

Dieser Mechanismus ist mit ansible-pull und FluxCD für Kubernetes gegeben. Schwieriger wird es bei den Ebenen, die diese bedingen. Das GitOps Konzept hat deshalb immer einen imperativen Aspekt, den IaC Aspekt (PUSH-Modell), der einen Installation Prozess abbilden muss.

Das kann in der Praxis also so aussehen, dass folgende imperative Schritte ausgeführt werden:

  • Mit Terraform wird Rechenkraft angemietet
  • Mit CloudInit werden diese Rechner mit einem ansible-pull -Job versehen

Es folgt dann der GitOps-basierte Teil, mit der mit einer PULL-Stratgie abgebildet wird:

  • Im Ansible Repository wird der aktuelle Konfiguration der Betriebssysteme widergespiegelt
  • Im Kubernetes Repository wird der aktuelle SOLL-Zustand des Kubernetes Cluster widergespielt

Ab hier ist es auch möglich, jegliche weitere Hardware mittels anderer Layer abzubilden. Beispielsweise bietet Crossplane die Möglichkeit Hardware per Kubernetes CRD (Orchestration ebene) anzumieten. Da es aber auch Kubernetes basiert, gibt es ein Henne-Ei-Problem (Woher soll das Cluster kommen, wo die CRDs deployed werden?).

Auch Ansible besitzt Module , um eher Hardwareorientierte Operationen auszuführen.

Zusammenfassung

In einer Traumwelt ist alles reaktiv. Das heißt: Es wird im git-Code was verändert und die reelle welt gleicht sich diesem Zustand an. In der Praxis ist es aufgrund unterschiedlicher Lebenszyklen der Ebenen nicht möglich, alles mit dem PULL-Modell abzubilden. Deshalb gibt es immer gewisse Infrastruktur Aspekte, die durch einen Installationsprozess durch einen imperativen Protess ausgeführt werden müssen. Dazu gehört z.B. das Bootstrappen der Infrastruktur durch Tools wie Cloud Init und Terraform. Tools wie Ansible übernehmen die Konfiguration des Betriesystems, während FluxCD auf der Orchestrator-Ebene agiert.