Flux CD Flux CD

Ein Repository mit Kustomize-Overlays pro Umgebung strukturieren

Organisiere ein Repository für Dev und Produktion und vermeide die ConfigMap-Rollout-Falle.

15 min Fortgeschritten

Echte Anwendungen laufen in mehreren Umgebungen, die sich in Kleinigkeiten unterscheiden: Replikazahlen, Hostnamen, Konfigurationswerte. Flux wendet reines YAML oder Kustomize-Overlays an und erkennt, welches davon ein Ordner verwendet. Diese Anleitung zeigt, wie du ein Repository für mehrere Umgebungen mit Kustomize strukturierst, wie du Flux jede davon mitteilst, und behandelt eine Falle, in die man bei Konfigurationsänderungen gerne tappt. Sie baut auf dem webapp-Beispiel aus den früheren Anleitungen auf.

Ein Layout wählen: Ordner statt Branches

Du kannst Umgebungen als langlebige Branches abbilden (dev, staging, main), aber dann wird die Promotion zur Merge-Übung, und die Umgebungen driften auseinander. Ein einzelner Branch mit einem Ordner pro Umgebung ist leichter zu durchschauen: Jede Umgebung ist nebeneinander sichtbar, und eine Änderung an einer ist ein normaler Diff.

Fluxs Dokumentation beschreibt drei gängige Repository-Strategien:

  • Monorepo. Alle Cluster, Apps und Infrastruktur in einem Repository. Am einfachsten zum Einstieg und das hier verwendete.
  • Repository pro Umgebung. Zum Beispiel eines für Staging und eines für Produktion, mit getrennten Zugriffsregeln.
  • Repository pro Team oder pro Anwendung. Starke Isolation, mit einem Plattform-Repository, das das Repository jedes Teams registriert.

Ein typisches Monorepo sieht so aus:

fleet-infra/
├── clusters/
│   ├── dev/                 # Flux-Kustomizations für den Dev-Cluster
│   └── production/          # Flux-Kustomizations für den Produktions-Cluster
├── infrastructure/          # Ingress-Controller, cert-manager, Monitoring
└── apps/
    ├── base/webapp/         # gemeinsame Manifeste
    ├── dev/                 # Overlay für Dev
    └── production/          # Overlay für Produktion

Eine Kustomize-Base und Overlays bauen

apps/base/webapp/kustomization.yaml listet die gemeinsamen Ressourcen auf:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

Lass den Container in apps/base/webapp/deployment.yaml seine Einstellungen aus einer ConfigMap lesen, die jedes Overlay erzeugt (lass das Feld namespace in der Base weg, da Overlays es setzen):

          envFrom:
            - configMapRef:
                name: webapp-config

apps/dev/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: webapp-dev
resources:
  - namespace.yaml
  - ../base/webapp
replicas:
  - name: webapp
    count: 2
configMapGenerator:
  - name: webapp-config
    literals:
      - HEADER=Hello from dev

mit einer namespace.yaml, die webapp-dev erstellt. apps/production/kustomization.yaml sieht genauso aus, mit namespace: webapp-prod, count: 4, einem eigenen Namespace-Manifest und einem eigenen HEADER-Wert. Du kannst vor dem Committen prüfen, was ein Overlay rendert:

kustomize build apps/dev
# oder, ohne kustomize separat zu installieren:
kubectl kustomize apps/dev

Eine Flux-Kustomization auf jedes Overlay richten

Flux erkennt die kustomization.yaml im Pfad und baut sie für dich. Füge im Ordner jedes Clusters eine Flux-Kustomization pro Umgebung hinzu. clusters/dev/apps.yaml:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/dev
  prune: true
  wait: true
  timeout: 3m

Für den Produktions-Cluster nutzt clusters/production/apps.yaml path: ./apps/production. Weil jeder Cluster mit seinem eigenen --path gebootstrapt wurde, sieht jeder Cluster nur seinen eigenen Ordner.

Die Produktion bewusst halten

Anders als Werkzeuge mit einem manuellen Sync-Knopf wendet Flux automatisch an, daher sicherst du die Produktion über Git ab. Ein starkes Muster ist, Dev einem Branch folgen zu lassen und die Produktion veröffentlichten Tags. In der Source des Produktions-Clusters:

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: fleet-releases
  namespace: flux-system
spec:
  interval: 5m
  url: https://github.com/your-org/fleet-infra
  ref:
    semver: ">=1.0.0"

Die Produktion ändert sich dann nur, wenn du ein Release taggst. Die Freigabe per Pull Request auf dem Haupt-Branch ist die andere gängige Absicherung.

Konfigurationsänderungen bewusst behandeln

Ändere den HEADER-Wert in einer Umgebung und sieh, was passiert. Kustomize hängt einen Hash des Inhalts an die Namen generierter ConfigMaps an. Ein neuer Wert erzeugt eine neue ConfigMap (webapp-config-<hash>) und aktualisiert die Referenz des Deployments, was einen Pod-Rollout auslöst. Die alte ConfigMap ist nun verwaist, und mit prune: true löscht Flux sie für dich. Dieses Verhalten ist genau das, was du willst: Konfigurationsänderungen rollen die Pods aus.

Einfache, von Hand geschriebene ConfigMaps sind anders. Wenn du eine ConfigMap bearbeitest, die ein Deployment über envFrom liest, ändert sich die Deployment-Spec nicht, sodass laufende Pods die alten Werte behalten. Nutze configMapGenerator für alles, was Workloads neu starten soll, wenn es sich ändert. Helm-Charts haben eine entsprechende Technik, die die Helm-Anleitung behandelt.

Werte pro Cluster einsetzen

Manchmal unterscheidet sich ein Wert pro Cluster, aber du willst kein ganzes Overlay dafür, zum Beispiel einen Domainnamen. Flux-Kustomizations können Variablen nach dem Build einsetzen:

spec:
  postBuild:
    substitute:
      cluster_domain: dev.example.com
    substituteFrom:
      - kind: ConfigMap
        name: cluster-vars

Jedes ${cluster_domain} in deinen Manifesten wird beim Anwenden ersetzt. Nutze das sparsam, da Overlays leichter zu prüfen sind.

Änderungen durch die Umgebungen befördern

Mit diesem Layout ist Promotion eine Folge gewöhnlicher Commits. Ändere zuerst das Dev-Overlay (zum Beispiel ein Image-Bump mit kustomize edit set image nginx=nginx:1.26, ausgeführt in apps/dev), lass Flux es anwenden und prüfe das Ergebnis. Mache dann dieselbe Änderung in apps/production, über einen Pull Request, der eine Freigabe verlangt. Eine CI-Pipeline kann den Dev-Commit automatisieren, und ein Reviewer sichert den Produktions-Commit ab. Auch Fluxs Image-Automatisierung kann den Dev-Schritt für dich übernehmen, was die Anleitung zur Image-Automatisierung behandelt.

Beliebte Anleitungen