Über unsMediaKontaktImpressum
Tobias Babin 21. September 2021

Kubernetes Deployments cross Cloud skalieren mit Azure Arc und GitOps

Unternehmen, die Kubernetes einsetzen, betreiben oft sehr viele Cluster. Nicht alle sind bequem in einer (Cloud-)Umgebung beheimatet, sondern verteilt über Cloud Provider, das eigene Rechenzentrum oder geographisch verteilte on-premise Locations. In dieser Hybrid- oder Multi-Cloud muss ich Application Deployments und Updates sicher, einfach und skaliert kontrollieren können – auch, wenn ein Cluster nicht immer online und erreichbar ist. Azure Arc-enabled Kubernetes führt heterogene Cluster standortübergreifend auf einer Kontrollebene zusammen. Gepaart mit einem einfach zu verwaltenden GitOps-Deployment-Modell können beliebig viele Cluster zielgenau mit einheitlichen Applikationsständen versorgt werden.

GitOps für Kubernetes

GitOps ist ein seit 2017 propagierter Ansatz für das fortlaufende Management und Deployment von Cloud-native-Anwendungen [1]. Die zentrale Idee: DevOps-Teams beschreiben die gewünschte Konfiguration eines Systems (desired state configuration) deklarativ in einem Git Repository. Da die Konfiguration eines Kubernetes Clusters und seiner Workloads vollständig deklarativ beschrieben werden kann, nutzen dies viele Teams heute für einen Infrastructure-as-Code-Ansatz.

Typischerweise wird die Konfiguration durch ein CI/CD-Tool über Pipelines oder IaC-Tools wie Terraform angewendet [2]. Dieses push-Verfahren wandelt GitOps in ein pull-Verfahren. Nun überwacht eine aktive Komponente (operator) auf dem Cluster den Inhalt des Repos und passt den Zustand des Clusters bei jeder Aktualisierung auf die aktuelle Konfiguration an.

Ein GitOps-Ansatz besitzt einige Vorteile gegenüber push-basierten Verfahren:

  • GitOps nutzt vertraute Tools und Prozesse aus dem Git-Universum (commit, push, merge, pull requests etc.).
  • Rollbacks sind sehr einfach durch Git-Befehle möglich.
  • Cluster Credentials müssen nicht außerhalb der eigenen Infrastruktur hinterlegt werden. Dies ist ein möglicher Angriffsvektor auf Produktivsysteme.
  • In einem push-Ansatz müssen alle zu versorgenden Cluster vom eingesetzten Deployment-Tool aus netzwerktechnisch erreichbar sein. Dies kann eine Öffnung von Firewalls auf eingehenden Ports notwendig machen. Im GitOps-pull-Ansatz werden nur ausgehende Ports benötigt, was sicherheitstechnisch leichter vertretbar ist.
  • Jeder Cluster agiert autark, was eine hohe Skalierung unterstützt. Lange Laufzeiten von Pipelines oder Deployment-Prozessen entfallen.
  • Cluster müssen nicht zeitgleich erreichbar sein. Eine sporadische connectivity eines Clusters zum Git-Repo genügt, um bei nächster Gelegenheit die neueste Konfiguration anzuziehen.

Auf die Herausforderungen des Ansatzes gehe ich zum Ende des Artikels ein.

GitOps mit Azure Arc-enabled Kubernetes

Mit dem seit März 2021 auf Microsoft Azure verfügbaren Azure Arc-enabled Kubernetes lassen sich Kubernetes Cluster innerhalb oder außerhalb von Azure in einer einheitlichen Kontrollebene zusammenführen [3]. Aufbauend darauf sind verschiedene Szenarien abbildbar [4], darunter einheitliches Monitoring, Security, das Deployment spezieller Azure-Dienste sowie ein GitOps basiertes Konfigurationsmanagement.

Der erste Schritt im Setup des oben gezeigten Aufbaus ist das Azure Arc-enablement des Clusters. Das Vorgehen ist in der Azure-Dokumentation ausführlich beschrieben [5]. Sind alle dort genannten Voraussetzungen erfüllt, dauert die Ausführung ca. zehn Minuten. Sie setzt eine Owner- oder Contributor-Rolle auf der Azure Subscription voraus.

Die eigentliche Azure-Arc-Kopplung erfolgt sehr einfach über einen einzigen Azure CLI- oder PowerShell-Befehl von einem Ort aus, an dem Zugriff auf den Cluster via kubectl besteht. Durch die Kopplung entstehen:

  • Azure Arc Kubernetes Agents auf dem Cluster in Form mehrerer Deployments/Pods im Namespace azure-arc [6].
  • Eine Azure-Ressource vom Typ "Kubernetes – Azure Arc" in der während der Einrichtung benannten Resource Group und Location, sichtbar im Azure-Portal (s. Abb. 2).

Ein Kubernetes Cluster verwandelt sich durch das Azure Arc enablement nicht in einen durch Azure gemanageten Cluster. Die in Azure sichtbare Ressource ist nur Abbild des gekoppelten Clusters und keine "Kubernetes service"-Ressource (AKS).

Der Cluster ist nun mit Azure verbunden und bereit für Erweiterungen. Im zweiten Schritt ergänzt eine GitOps Configuration die Cluster Ressource. Auch diese wird wieder mit einem Azure-CLI-Befehl erstellt, der in der Azure-Dokumentation beschrieben ist [7].
Die GitOps Configuration definiert den Zugang zu einem Git Repository, d. h. Location, Zugangsdaten sowie der Git Branch und das Verzeichnis darin, in welchem der Agent nach Ressourcen suchen soll. Nach Ausführung des CLI-Befehls entstehen abermals zwei Dinge:

  • Die GitOps Agents, die einem zweiten, selbst wählbaren Namespace (z. B. cluster-config) auf dem Cluster deployed sind.
  • Ein im Azure-Portal sichtbarer Eintrag im Bereich "GitOps" innerhalb der zuvor erstellten "Kubernetes – Azure Arc"-Ressource (s. Abb. 3).

Ein Azure Arc-enabled Kubernetes Cluster kann über weitere GitOps Configurations an mehrere Git-Repos angeschlossen werden, die jeweils eine desired state configuration enthalten und auf einen namespace beschränkt sind. Dadurch entsteht eine Art Baukastensystem für Configurations, mit dem sich mandantenfähige Deployments entwerfen lassen.

Im folgenden Beispiel sind zwei Configurations zu sehen: diejenige mit cluster scope ist für das Setup der Cluster-Strukturen (u. a. namespaces) zuständig, wohingegen diejenige mit namespace scope Ressourcen nur in einem dedizierten namespace verwaltet.

GitOps in der Praxis

Die GitOps-Umsetzung für Azure Arc-enabled Kubernetes verwendet intern das Open-Source-Framework Flux[8]. Der Flux-Operator ist für die Überwachung des Git-Repos und die Anwendung der dort gefundenen Konfiguration zuständig. Sehen wir uns GitOps in Aktion an mit einem einfachen Beispiel: In dem durch die GitOps Configuration überwachten Git-Repo fügen wir einige Kubernetes Manifest Files hinzu:

my-gitops-repo/
├─ department-foo/
│  ├─ dept-foo-sample-deployment.yaml
├─ namespaces/
│  ├─ department-foo.yaml

Das File department-foo.yaml beschreibt einen Namespace, das File dept-foo-sample-deployment.yaml eine Deployment/Service/Ingress-Kombination.

Nach kurzem Warten – das Polling-Intervall ist über die GitOps Configuration steuerbar – erzeugt der Flux-Operator selbsttätig alle so definierten Ressourcen auf dem Cluster:

$ kubectl get pods,services,ingress -n department-foo -o name
deployment.apps/sample-foo
pod/sample-foo-684f46fbdd-hpqxm
service/sample-foo
ingress.networking.k8s.io/sample-foo

Neben Kubernetes-Manifests unterstützt Flux auch Helm Chart Deployments[9]. Hierzu bringt es die Custom Resource Definition (CRD) des HelmRelease mit. Ein HelmRelease ist das deklarative Pendant zu einen helm upgrade --install-Befehl, den ich ansonsten in einer CI/CD-Pipeline ausführen würde. Um ein Helm-Chart zu installieren, platziere ich eine HelmRelease-Definition in meinem überwachten Git-Repo. Sie enthält den Verweis auf ein Git- oder Helm-Repository, in dem der eigentliche Helm-Chart zu finden ist.

Nach Hinzufügen einer weiteren Namespace-Definition sowie eines HelmRelease zu unserem überwachten GitOps Repo…

my-gitops-repo/
├─ department-foo/
│  ├─ dept-foo-sample-deployment.yaml
├─ helmreleases/           <--
│  ├─ department-bar.yaml  <--
├─ namespaces/
│  ├─ department-foo.yaml
│  ├─ department-bar.yaml  <--

… entstehen wiederum selbsttätig die gewünschten Ressourcen auf dem Cluster:

$ kubectl get pods,services,ingress -n department-bar -o name
pod/sample-bar-ccb58cd85-znnrc
service/sample-bar
ingress.networking.k8s.io/sample-bar

Damit besitze ich diese Möglichkeiten für das GitOps-Setup, die ich beliebig kombinieren kann:

Über welchen Entwicklungsprozess die desired state configuration in das überwachte Git-Repo gelangt und gepflegt wird, ist beispielhaft in der Azure-Dokumentation beschrieben [10].

On-Premise, Multi-Cloud, Hybrid-Cloud

Jeder Cluster einer CNCF-zertifizierten Kubernetes-Distribution kann Azure Arc-enabled werden. Microsoft hat eine Menge von Distributionen explizit validiert und in der Azure-Dokumentation benannt [11]. Dazu gehören EKS (AWS) und GKE (Google Cloud).
Kubernetes ist bereits distributions- und betreiber-agnostisch. Azure Arc erzeugt zusätzlich eine vereinheitliche Lösung für die Verteilung von Workloads. Dies spricht explizit Unternehmen mit einer Multi-Cloud oder Hybrid-Cloud-Strategie an. Es spielt keine Rolle, wo der Cluster läuft – ob in einer Cloud, on-premise oder on the edge, solange die netzwerktechnischen Voraussetzungen gegeben sind.

Nur ausgehende Firewall-Öffnung notwendig

Die Agents auf dem Cluster initiieren alle nötigen Verbindungen, so dass nur eine ausgehende Firewall-Öffnung notwendig ist. Sie benötigen Zugriff via TCP/443 (HTTPS) zu einer Menge von Azure Endpoints [12] sowie – ebenfalls nur ausgehenden – Zugriff auf das überwachte Git-Repo plus ggf. weitere Git- oder Helm-Repos, die ich in HelmReleases referenziere.

Gelegentlich online sein genügt

Es ist ausreichend, eine sporadische Verbindung zu Azure zu haben. Dies ist interessant für Szenarien, in denen ein Cluster on-premise oder in einer edge location nicht durchgehend online sein darf (aus Sicherheitsgründen, z. B. Kopplung an eine Produktionsanlage) oder kann (aus logistischen Gründen, z. B. Cluster-Umgebung ist mobil). Die GitOps Agents ziehen dann bei der nächsten Möglichkeit die aktuell gültige Konfiguration aus dem überwachten Git-Repo. Microsoft nennt dies semi-connected Connectivity Mode [13].

Spätestens alle 90 Tage muss ein Cluster via Heartbeat für Azure sichtbar werden. Danach wird die Kopplung ungültig und muss mitsamt aller Erweiterungen neu aufgebaut werden [14]. Für aus Sicherheitsgründen abgetrennte Cluster kann es vertretbar sein, diese zu kontrollierten Zeitpunkten temporär von ihrem internen Netzwerk ab- und an die nötigen Azure und GitOps Endpoints anzukoppeln, um die Konfiguration zu aktualisieren.

Für einen Cluster, der niemals mit Azure verbunden ist (disconnected mode), wird Azure Arc-enabled Kubernetes aktuell nicht unterstützt [15].

Hoch skalieren mit Azure Policies

Mehrere Cluster mit der gleichen Zielkonfiguration zu versorgen, bedeutet, sie mit der gleichen GitOps Configuration auszustatten. Hierzu eignen sich Azure Policies [16]. Mit diesem Azure-Governance-Tool kann ich Azure Ressourcen (hier: die Connected Cluster Ressourcen) automatisch mit einheitlichen Zusatzelementen (hier: eine GitOps Configuration) versehen.

Für einen definierten Scope (Management Group, Subscription oder Resource Group) und abhängig von Attributen meiner Cluster (z.B. bestimmte Tags) kann ich verschiedene Policies zuweisen und somit eine jeweils andere desired state configuration anwenden. Wähle ich die DeployIfNotExists-Einstellung in der Policy, erhält jeder neu an Azure Arc gekoppelte Cluster im Scope der Policy automatisch die jeweilige(n) GitOps Configuration(s) zugewiesen und versorgt sich von dort an mit den definierten Workloads. Die Verwaltung der GitOps Configurations wird so durch Policies zentralisiert und ist hoch skalierend.

Weitere Szenarien mit Azure Arc

Das Azure Arc-enablement eines Kubernetes Clusters ermöglicht neben der GitOps Configuration auch Monitoring, Security oder das Deployment spezieller für Azure Arc vorbereiteter Services (mehr dazu im Überblick in der Azure-Dokumentation [17]). Allen Szenarien gemein ist, dass ihre Verwaltung für die Kubernetes-Landschaft zentral über die Azure-Ebene erfolgt.

Was brauche ich und was kostet das?

Um Azure Arc-enabled Kubernetes mit GitOps Configurations zu nutzen, benötige ich:

  • Einen Azure Account.
  • Die nötigen Berechtigungen in einer Subscription.
  • Einen oder mehrere CNCF konforme Kubernetes Cluster.
  • Cluster Admin Access für die Installation der Azure Arc Agents.
  • Mindestens sporadische Connectivity der Cluster zu den zuvor genannten Endpoints.

Hinsichtlich des Pricings gelten diese Regelungen (Stand September 2021) [18]:

  • Das Azure Arc-enablement einer beliebigen Menge von Kubernetes Clustern ist kostenlos.
  • GitOps Configurations sind nach den vCPUs der Cluster bepreist mit derzeit 1,6866€/vCPU/Monat, bei 5-Minuten-genauer Abrechnung und den ersten sechs vCPUs frei.

Eine Beispielrechnung (ohne Gewähr) für die Region West Europe: um eine Kubernetes-Landschaft mit insgesamt 100 vCPUs mit GitOps Configurations auszustatten, zahle ich monatlich (100 – 6)vCPU x 1,6866€/vCPU = 158,54€. Dienste für die anderen Azure-Arc-Szenarien besitzen ihre eigene Preisgestaltung.

Zusammenfassung

Ist das was für mich und mein Unternehmen? Es kommt mal wieder drauf an.

Irgendwie muss ich die Aufgabe der Workload-Verteilung lösen. GitOps mit Azure Arc-enabled Kubernetes ist gegenüber einem push-basierten Verfahren umso interessanter, je mehr dieser Umstände gegeben sind:

  • Ich betreibe KubernetesCluster in mehreren Clouds (Multi-Cloud).
  • Ich betreibe Cluster on-premise oder gemischt (Hybrid-Cloud/Edge).
  • Ich betreibe eine große Anzahl von Clustern, auch mit heterogenen Workloads.
  • Cluster können oder dürfen nicht durchgehend mit dem Internet verbunden sein.
  • Ich möchte oder darf keine eingehenden Verbindungen zu Clustern auf der Firewall zulassen.
  • Ich möchte Spezialwissen zu DevOps-Tooling oder einer Kubernetes-Management-Suite in meinen DevOps-Teams vermeiden oder möglichst klein halten.
  • Ich bin bereit, Azure als Bindeglied für meine Cluster-Landschaft einzusetzen.

Kritisch zu prüfen sind diese Aspekte:

  • DevOps-Teams verwenden in einem GitOps-Ansatz vertraute Git-Mechanismen. Dennoch muss ein produktiv eingesetzter GitOps-Prozess wie jeder andere CI/CD-Prozess solide entworfen und mit angemessenen Sicherheitsmechanismen ausgestattet sein. Dies erfordert eine hohe Reife in der Git-Beherrschung seitens der teilnehmenden Teams.
  • Die Autarkie des pull-Verfahrens für jeden Cluster bedeutet eine zunächst fehlende Rückmeldung über den Deployment-Erfolg, den ich bei einer klassischen Pipeline habe. Den configuration state meiner Cluster muss ich über eine eigene Governance überwachen, was in jeder größeren Landschaft ohnehin eine gute Idee ist.
  • Wie migriere ich von einer Non-GitOps- auf eine GitOps-Lösung? Habe ich Spezialaspekte in Pipelines enthalten, die nicht deklarativ abbildbar sind?
  • Begebe ich mich in eine zu große Abhängigkeit zu Microsoft Azure?

GitOps mit Azure Arc-enabled Kubernetes kann eine bestehende Cluster-Management-Lösung auch sinnvoll ergänzen, um die spezielle Aufgabe der Verteilung von Workloads zu übernehmen. Wie für jede interessante Technologie gilt: im kleinen Stil ausprobieren und die relevanten Szenarien durchspielen, erst danach über einen weiteren Einsatz entscheiden. Der Azure Arc Jumpstart bietet eine gute praktische Hilfestellung zum Einstieg [19].

Autor

Tobias Babin

Tobias Babin ist Digital Engineer bei MaibornWolff. Er unterstützt seit über 20 Jahren Kunden verschiedenster Branchen beim Einsatz von Methoden und Technologien der IT.
>> Weiterlesen
Das könnte Sie auch interessieren
Kommentare (0)

Neuen Kommentar schreiben