adesso Blog

Chaos in Kubernetes durch manuelle Änderungen und Konfigurationsabweichungen? Flux CI und GitOps-Prinzipien schaffen Ordnung: In diesem Blog-Beitrag zeige ich euch, wie die Open-Source-Lösung Produktionsumgebungen automatisch synchronisiert und Continuous Delivery zuverlässig macht.

Die Leistungsfähigkeit und Flexibilität einer Kubernetes-Architektur kann im Betrieb leicht durch das Chaos von Konfigurationsabweichungen und eine manuell veränderte Infrastruktur beeinträchtigt werden. Gerade in regulierten Branchen, wie beispielsweise bei Banken, ist es entscheidend, dass die Einhaltung von Regulationen und Standards gewährleistet bleibt. Wie kann man also sicherstellen, dass der Zustand des Produktionsclusters nicht unmerklich von der gewünschten Vorlage abweicht, sodass eine zuverlässige Continuous Delivery (CD) nicht zu einem Glücksspiel wird? Eine effektive Lösung bietet die Automatisierung von Infratruktur mit GitOps-Prinzipien, bei denen Git als Single Source of Truth fungiert. Genau dieses Problem löst Flux CI: Es ist die offene Lösung für Kubernetes, die innerhalb des Clusters arbeitet, kontinuierlich die Konfiguration aus Git-Repositories abruft und die Umgebung automatisch abgleicht. So ermöglicht Flux CI eine robuste Verwaltung für Applikations-Deployments sowie für die für Infrastruktur. Das ist ein entscheidender Vorteil, insbesondere für Banken, die auf Compliance und Regulation angewiesen sind.

Was ist Flux CI?

Flux ist eine Open-Source-Continuous-Delivery-Lösung, die explizit für Kubernetes entwickelt wurde. Im Kern stellt Flux sicher, dass der Zustand des Kubernetes-Clusters dauerhaft mit den definierten Konfigurationsquellen synchron bleibt. Hauptsächlich handelt es sich um Git -, OCI- und Helm-Repositories sowie Flux-Kustomizations, aber auch um einfache Kubernetes-Ressourcen. Flux verwaltet und deployt diese Ressourcen und bietet GitOps-Funktionen sowohl für die Infrastrukturkonfiguration als auch für Applikations-Workloads. Dabei nutz Flux das native API-Interface von Kubernetes und integriert sich nahtlos in andere zentrale Komponenten des Ökosystems. So unterstützt es Multi-Tenancy und die Synchronisierung mehrerer Git-Repositories gleichzeitig.

Flux nutzt eine Reihe von Kubernetes-API-Erweiterungen, die als Custom Resources (CRD – Custom Resource Definition in Flux) bekannt sind. Diese definieren, wie externe Konfigurationsquellen – etwa Git-Repositories – auf den Cluster angewendet werden. Beispielsweise wird ein GitRepository-Objekt verwendet, um die Konfiguration aus einem Git-Repository als sogenannte Quelle zu spiegeln. Zudem wird ein nachfolgendes Flux-Kustomization-Objekt (dies ist eine CRD und nicht mit Kustomize zu verwechseln) genutzt, um diese Konfiguration mit dem Cluster zu synchronisieren. Dieser systematische Ansatz ermöglicht es Flux, die Applikationsbereitstellung (CD) sowie die Progressive Delivery (PD) durch vollständig automatisches Reconciliation zu realisieren.

Was macht Flux einzigartig?

Flux ermöglicht nahtlose Continuous Delivery, indem es strikt GitOps-Prinzipien umsetzt: Git als Single Source of Truth. Die Lösung konzentriert sich auf automatische Synchronisierung. Anstatt auf externe CI-Pipelines zu setzen, die Änderungen in den Cluster pushen (was erfordert, externen Systemen Schreibzugriff zu gewähren und Anmeldedaten zu verwalten), zieht Flux Konfigurationen direkt aus Git. Konfigurationsänderungen (Manifeste, Flux-Kustomize-Dateien oder Helm-Definitionen) werden in ein Git-Repository gepusht und Flux übernimmt den Rest. Die Kernkomponenten von Flux – der Source Controller, Kustomize Controller und Helm Controller – laufen innerhalb des Clusters, überwachen kontinuierlich das angegebene Git-Repository auf neue Commits, ziehen die Daten und wenden den gewünschten Zustand mithilfe von Server-Side Apply an.

Ein Beispielprojekt: Multi-Umgebung mit externen Applikationsrepositories

Das Beispielprojekt, das wir erstellen, demonstriert ein Flux-Setup für mehrere Umgebungen. Das fertige Beispiel findet ihr auf GitHub. Die Struktur des Git-Repositories trennt die Verwaltung der Cluster-Einrichtung (Infrastruktur) von der Bereitstellung von Applikationen. Man definieret zwei separate Umgebungen: staging und production, zusammen mit allen notwendigen Infrastrukturkomponenten. Konkret deployt das Beispiel die Podinfo-Anwendung und enthält die Konfiguration, die erforderlich ist, um ingress-nginx als zentralen Clusterdienst zu installieren. Die Wurzel-kustomization unserer Cluster-Konfiguration, clusters/my-cluster/kustomization.yaml, orchestriert die gesamte Bereitstellung, indem sie die Flux-System-Manifeste, Namespaces, Infrastrukturkomponenten, RBAC-Definitionen und schließlich den Applikationsordner zusammenführt. Dieses Setup stellt sicher, dass Abhängigkeiten effektiv verwaltet werden, sodass kritische Ressourcen wie Namespaces und der Ingress-Controller verfügbar sind, bevor Anwendungen, die von ihnen abhängen, bereitgestellt werden.

	
		├── apps/
		│   ├── kustomization.yaml
		│   └── podinfo/
		│       ├── overlays/
		│       │   ├── production/
		│       │   └── staging/
		│       └── sources/
		│           └── flux-system/
		└── clusters/    
		└── my-cluster/        
		├── kustomization.yaml        
		├── flux-system/        
		├── infrastructure/        
		├── namespaces/        
		└── rbac/
	
Vorbereitungen

Um ein Flux-Setup wie in diesem Beispiel lokal nachzuvollziehen, wird Folgendes benötigt:

  • ein lokaler Kubernetes-Cluster (Kubernetes kind empfohlen),
  • die lokal installierte Flux-CLI, die für das Bootstrapping und die Interaktion mit Flux unerlässlich ist,
  • ein Git-Repository gehostet auf GitHub als Quelle für Konfiguration und
  • und ein persönlicher Git-Zugriffstoken mit Repository-Berechtigungen, idealerweise als Umgebungsvariable exportiert (hier: GITHUB_TOKEN, GITHUB_USER).
Zuerst: Bootstrap Flux

Das Bootstrapping ist der erste Schritt bei der Nutzung von Flux und die offiziell unterstützte Methode zur Installation. Dabei wird Flux auf einem Kubernetes-Cluster installiert, sodass Flux selbst durch GitOps verwaltet wird.

Der folgende Befehl erstellt ein persönliches Git-Repository mit den Flux-Systemressourcen auf GitHub und installiert das Flux-System im Kubernetes-Cluster.

	
		CODE BOX START
		export GITHUB_TOKEN=<Your GitHub Token>
		export GITHUB_USER=<Your GitHub Username> 
		flux bootstrap github \  
		--owner=$GITHUB_USER \  
		--repository=<your repository name> \  
		--branch=main \  
		--path=./clusters/my-cluster \  
		--personal
		CODE BOX END
	

Wenn ihr den Befehl flux bootstrap ausführt, werden mehrere Schritte durchgeführt:

  • 1. Flux generiert und pusht die Kernkomponenten-Manifeste von Flux (Source Controller, Kustomize Controller usw.) in das angegebene Git-Repository.
  • 2. Es deployt diese Komponenten sowie die erforderlichen Custom Resource Definitions (CRDs) in den Kubernetes-Cluster.
  • 3. Anschließend erstellt Flux seine eigenen Synchronisierungsressourcen: eine GitRepository-Ressource, die auf das Konfigurations-Repository verweist und eine Kustomization-Ressource (in unserem Beispiel sichtbar als flux-system Kustomization), die so konfiguriert ist, dass sie den Pfad zur flux-system-Konfiguration innerhalb des Repositories überwacht.

Das bedeutet, dass das gesamte Continuous-Delivery-System – also Flux selbst – in Git definiert, verwaltet und versioniert wird. Wenn die Einstellungen von Flux geändert werden müssen, reicht ein Commit in Git, und Flux gleicht seinen eigenen Zustand entsprechend ab.


KI-Automatisierung

Aus Routine wird Intelligenz

Automatisierung ist mehr als nur Technik: Sie ist der Schlüssel zu Agilität, Effizienz und Qualität. Wir unterstützen euch dabei, Prozesse grundlegend neu zu denken. So werden Routineaufgaben eliminiert, Daten werden zum Motor von Entscheidungen und IT sowie Geschäftsabläufe verschmelzen zu strategischen Wertschöpfungsketten.

Entdeckt Use Cases und Tools wie DORA.KI oder RPA und erfahrt, wie euer Unternehmen von intelligenter Automatisierung profitieren kann.

Mehr erfahren und Automatisierungsprojekt starten


Aufsetzen der Infrastruktur

Die Infrastruktur wird unter dem Pfad clusters/my-cluster verwaltet. Dadurch wird sichergestellt, dass diese Komponenten eingerichtet sind, bevor Anwendungen bereitgestellt werden.

1. Namespaces

Der grundlegende Schritt besteht darin, die logischen Grenzen zu schaffen. Man definieret die Namespaces staging, production und ingress-nginx mithilfe von standard YAML-Manifesten, die im Verzeichnis clusters/my-cluster/namespaces abgelegt sind.

	
		YAML CODE START
		apiVersion: v1
		kind: Namespace
		metadata:  
		  name: staging  
		  labels:    
		    workspace: staging
		YAML CODE END
	
2. Role Based Access Controll (RBAC)

Sicherheit hat in Multi-Umgebungs-Setups oberste Priorität. Man definiert spezifische Service Accounts (wie staging-flux und production-flux im Namespace flux-system) und verwendet anschließend RoleBindings, um diesen Service Accounts die erforderlichen Berechtigungen zu gewähren - ausschließlich innerhalb ihrer jeweiligen Ziel-Namespaces. Zum Beispiel das Binden des production-flux-Accounts an cluster-admin im Namespace production. Dies gewährleistet Isolation. Wenn man das Prinzip der minimalen Berechtigungen (Least-Privilege-Prinzip) für die Berechtigungen der Service Accounts umsetzen will, kann man auch benutzerdefinierte Rollen definieren. Für dieses Beispiel wählt man jedoch den einfachen Weg.

3. Ingress-Nginx

Der Ingress-Controller wird mithilfe eines HelmRelease bereitgestellt (definiert in clusters/my-cluster/infrastructure), das das Chart direkt aus seinem offiziellen Git-Repository bezieht. Für diese Bereitstellung definiert man ebenfalls einen spezifischen Service Account (ingress-nginx-flux).

HelmChart als GitResource für Flux

Um eine Helmchart-Source aus einem Git-Repository zu definieren, muss man lediglich das Verzeichnis angeben, das die Charts enthält.

	
		YAML CODE START
		apiVersion: source.toolkit.fluxcd.io/v1
		kind: GitRepository
		metadata:  
		  name: ingress-nginx-controller-source  
		  namespace: flux-system
		spec:  
		  interval: 60m0s  
		  ref:    
		    branch: main  
		  url: https://github.com/kubernetes/ingress-nginx  
		  ignore: |    
		    # exclude all    
		    /*    
		    # include charts directory only!    
		    !/charts/
		YAML CODE END
	

Helmchart als HelmRelease Custom Resource

Es ist wichtig, das Verzeichnis des Charts in spec.chart.spec.chart innerhalb der HelmRelease-Custom-Resource anzugeben, damit Flux weiß, wo es das Chart finden kann.

	
		YAML CODE START
		apiVersion: helm.toolkit.fluxcd.io/v2
		kind: HelmRelease
		metadata:  
		  name: ingress-nginx  
		  namespace: flux-system
		spec:  
		serviceAccountName: ingress-nginx-flux  
		targetNamespace: ingress-nginx  
		storageNamespace: ingress-nginx  
		interval: 10m  
		chart:    
		  spec:      
		    chart: charts/ingress-nginx   # path to the chart within the repo      
		    version: 4.11.2      
		    sourceRef:
		      kind: GitRepository     
		      name: ingress-nginx-controller-source        
		      namespace: flux-system      
		    reconcileStrategy: Revision   # good default for Git sources  
		install:    
		  createNamespace: true    
		  remediation:      
		    retries: 3  
		upgrade:    
		  remediation:      
		    retries: 3  
		values:    
		  controller:      
		    replicaCount: 1      
		    service:        
		      type: LoadBalancer    
		  fullnameOverride: ingress-nginx
		YAML CODE END
	

Trennung von Applikationskonfiguration und Infrastruktur

Die Trennung zwischen dem clusters-Ordner (Infrastruktur) und dem apps-Ordner (Applikationskonfiguration) ist ein zentrales Merkmal unseres Setups. Dies folgt einer standardmäßigen GitOps-Struktur, die häufig in "Repo-per-Team"- oder Monorepo-Ansätzen zu finden ist.

  • Cluster-Setup (clusters/my-cluster): Dieser Bereich definiert die Plattform – Namespaces, RBAC, gemeinsame Dienste (wie ingress-nginx) und das grundlegende Flux-Setup. Dieser Bereich wird typischerweise von einem Platform-Engineering- oder Administrationsteam verwaltet.
  • Anwendungsentwicklung (apps): Dieses Verzeichnis ist vollständig den Workloads gewidmet, die auf der Plattform bereitgestellt werden.
  • Für die Podinfo-Applikation enthält es die notwendige GitRepository-Quellendefinition und separate Overlays für staging und production. Diese Overlays ermöglichen es, umgebungsspezifische Konfigurationen wie unterschiedliche Ingress-Hosts (zum Beispiel fluxv2infrademo.io vs. fluxv2infrademo.staging.io) anzuwenden – ohne die Kern-Manifeste der Anwendung zu koppeln. Diese Trennung der Verantwortlichkeiten erlaubt es verschiedenen Teams, ihre jeweiligen Konfigurationsbereiche unabhängig voneinander zu verwalten.
  • Das Plattform-Team gewährleistet die Stabilität der Cluster-Infrastruktur, während die Entwicklungsteams sich darauf konzentrieren können, im apps-Verzeichnis schnell zu iterieren. Dies vereinfacht das Änderungsmanagement und reduziert das Risiko, clusterweite Ressourcen unbeabsichtigt zu beeinträchtigen.

Repository Struktur für Applikationen

Für unser Beispiel verwenden wir die Podinfo-Applikation, die aus einem Git-Repository bereitgestellt wird.Wir speichern sie als Flux-Source im Flux-Namespace flux-system, sodass jede Flux-Kustomization im selben Namespace darauf zugreifen kann.

Hinweis: Das funktioniert nur, weil wir zuvor cross-namespace-refs erlaubt haben. Andernfalls müsste jedes Overlay die Quelle in seinem eigenen Namespace angeben.

Podinfo Source in apps/sources/flux-system

	
		YAML CODE START
		apiVersion: source.toolkit.fluxcd.io/v1
		kind: GitRepository
		metadata:  
		     name: podinfo
		    namespace: flux-system
		spec:  
		   interval: 1m0s  
		 ref:
		   branch: master  
		url: https://github.com/stefanprodan/podinfo
		YAML CODE END
	
Podinfo-CRD in apps/podinfo/overlays/(staging,production)
	
		YAML CODE START
		apiVersion: kustomize.toolkit.fluxcd.io/v1
		kind: Kustomization
		metadata:  
		  name: podinfo-staging  
		 namespace: flux-system
	
	
		spec:  
		    serviceAccountName: staging-flux  
		  interval: 1m0s  
		  path: ./kustomize  
		  prune: true  
		  retryInterval: 2m0s  
		   sourceRef:    
		 kind: GitRepository    
		 name: podinfo
		  namespace: flux-system  
		 targetNamespace: staging  
		 timeout: 3m0s  
		 wait: true  
		 patches:    
		 - patch: |-        
		 apiVersion: autoscaling/v2        
		 kind: HorizontalPodAutoscaler        
		 metadata:          
		 name: podinfo        
		 spec:          
		 minReplicas: 2      
		 target:        
		 name: podinfo        
		kind: HorizontalPodAutoscaler
		YAML CODE END
	
Standard Kubernetes Ingress in apps/podinfo/overlays/(staging,production)
	
		YAML CODE START
		apiVersion: networking.k8s.io/v1
		kind: Ingress
		metadata:  
		 name: podinfo-ingress  
		 namespace: staging  # Ensure this matches the namespace of the podinfo service
		 labels:    
		 app.kubernetes.io/name: podinfo-ingress-staging  
		 annotations:    
		 kubernetes.io/ingress.class: "nginx"
		 spec:  
		 ingressClassName: nginx  
		 rules:    
		 - host: fluxv2infrademo.staging.io      
		 http:        
		 paths:          
		 - path: /            
		 pathType: Prefix
		  backend:              
		 service:                
		 name: podinfo  # Ensure this matches the podinfo service name                
		 port:                  
		 number: 9898
		 YAML CODE END
	
Setup Testen

Nun, da der Cluster konfiguriert, die Podinfo-Anwendung bereitgestellt und ein Ingress eingerichtet ist, kann man das Setup fast testen. Zuvor muss man jedoch die folgenden Einträge in die Datei /etc/hosts (Windows: C:\windows\system32\drivers\etc\hosts) hinzufügen, damit man die Pods über fluxv2infrademo.staging.io und fluxv2infrademo.io erreichen kann.

	
		SHELL SCRIPT START
		## Add this to the hosts file
		127.0.0.1       fluxv2infrademo.io
		127.0.0.1       fluxv2infrademo.staging.io
		SHELL SCRIPT END
	

Ruft man in einem Browser fluxv2infrademo.staging.io auf sieht man die Podinfo Statusseite.

Fazit

Durch die Nutzung von Flux und die Einführung eines strukturierten Repository-Ansatzes trennt man die Verwaltung von Infrastruktur und Anwendungen über verschiedene Umgebungen hinweg. Diese Automatisierung sorgt für die dringend benötigte Konsistenz und Zuverlässigkeit in der Continuous-Delivery-Pipeline. Besonders für Banken ist dies ein entscheidender Vorteil, da sie strengen Regulationen unterliegen und eine fehlerfreie Bereitstellung von Anwendungen und Infrastruktur sicherstellen müssen.

adesso begleitet euer Unternehmen mit umfassender Java-Expertise bei der Entwicklung und Integration moderner Java-Portale, die sich nahtlos in automatisierte und skalierbare Systemlandschaften einfügen. So entsteht eine zukunftssichere Architektur, die Stabilität, Performance und Compliance vereint.


Wir unterstützen euch!

Möchtet ihr Continuous Delivery in eurer Kubernetes-Umgebung sicher, effizient und regelkonform umsetzen? Wir unterstützen euch dabei, GitOps-Prinzipien mit Flux CI in Ihre DevOps-Prozesse zu integrieren – von der Architektur bis zur Implementierung.

Jetzt unverbindlich Kontakt aufnehmen

Bild Johannes Dienst

Autor Johannes Dienst

Johannes Dienst ist Senior Software Engineer bei adesso. Sein Fokus liegt auf Automatisierung, Dokumentation und Softwarequalität.


asdf

Unsere Blog-Beiträge im Überblick

In unserem Tech-Blog nehmen wir Sie mit auf eine spannende Reise durch die adesso-Welt. Weitere interessante Themen finden Sie in unseren bisherigen Blog-Beiträgen.

Zu allen Blog-Beiträgen

asdf

Unser Newsletter zum adesso Blog

Sie möchten regelmäßig unser adesso Blogging Update erhalten? Dann abonnieren Sie doch einfach unseren Newsletter und Sie erhalten die aktuellsten Beiträge unseres Tech-Blogs bequem per E-Mail.

Jetzt anmelden