Blog · 12. August 2025 · Aktualisiert am 7. September 2026 · 12 Min. Lesezeit

Kustomize vs Helm: was wann?

Mehrere transparente Glasscheiben, die hintereinander aufgereiht ein zusammenhängendes Bild mit türkisem Lichtschimmer ergeben
Foto: Noah D Wilke / Pexels

Die kurze Antwort auf Kustomize vs Helm: Nimm Kustomize, wenn du deine eigenen Manifeste für mehrere Umgebungen anpassen willst und dabei bei reinem YAML bleiben möchtest. Nimm Helm, wenn du eine Anwendung als Paket ausliefern, versionieren, mit Abhängigkeiten versehen oder fertige Software von Dritten installieren willst. In den meisten Clustern, die ich betreue, laufen beide nebeneinander, und das ist kein Kompromiss, sondern die richtige Arbeitsteilung.

Falsch wird die Wahl vor allem dann, wenn ein Team ein Werkzeug für eine Aufgabe nimmt, für die das andere gebaut ist: ein Chart mit Dutzenden Platzhaltern für zwei Umgebungen derselben App, oder ein Berg von Overlays für Software, die eigentlich als Paket zu anderen Teams gehen soll.

Ich betreibe Kubernetes-Cluster in Produktion und habe das Kubernetes-Praxisbuch bei Rheinwerk geschrieben (2024). Dort habe ich Kustomize im Kapitel zu Everything as Code und Helm in einem eigenen Kapitel beschrieben. Hier steht die Kurzfassung mit der Entscheidungshilfe, die ich mir damals selbst gewünscht hätte. Alle meine Beiträge zu Kubernetes findest du gesammelt auf der Seite Kubernetes.

Das Problem, das beide Tools lösen: kopierte Manifeste

Fast jedes Team landet früher oder später an derselben Stelle. Das Deployment für die Entwicklungsumgebung braucht ein Replica und ein Image mit dem neuesten Build, die Produktion braucht drei Replicas, ein freigegebenes Image, höhere Ressourcen-Requests und andere Labels. Der erste Reflex ist, die Datei zu kopieren: deployment-dev.yaml und deployment-prod.yaml.

Ich habe das in mehreren Unternehmen gesehen und es geht jedes Mal gleich aus. Ein Entwickler ergänzt eine Umgebungsvariable in der einen Datei und vergisst die andere. Nach drei Monaten weiß niemand mehr, welche Unterschiede zwischen den Dateien Absicht sind und welche Versehen. Manifeste müssen deshalb parametrisiert werden, und zwar mit einem etablierten Werkzeug, nicht mit einem selbstgebauten sed-Skript in der Pipeline.

Genau hier trennen sich die Wege. Kustomize und Helm lösen dasselbe Problem mit zwei grundverschiedenen Ansätzen, und aus diesem Unterschied folgt fast alles, was du für die Entscheidung wissen musst. Wenn dir die Grundlagen zu Manifesten noch fehlen, lies vorher Kubernetes YAML: Manifeste verstehen.

Kustomize vs Helm: Overlays gegen Templates

Kustomize verändert fertige Manifeste. Du schreibst eine Basis aus ganz normalem YAML, das du jederzeit mit kubectl apply -f ausrollen könntest, und legst je Umgebung ein Overlay daneben, das nur die Felder enthält, die abweichen. Kustomize legt beides übereinander und gibt das Ergebnis aus. Es gibt keine Platzhalter, keine Template-Sprache und nichts, was du erst lernen musst. Weil Kustomize in kubectl eingebaut ist, brauchst du auch kein zusätzliches Programm.

Helm erzeugt Manifeste. Ein Helm Chart enthält Templates in der Go-Template-Sprache, in denen Werte wie {{ .Values.replicaCount }} stehen. Erst beim Rendern setzt Helm die Werte aus einer oder mehreren values.yaml ein und macht aus den Templates gültige Manifeste. Die Templates selbst sind kein gültiges YAML mehr, dafür können sie Bedingungen, Schleifen und Hilfsfunktionen enthalten.

Dazu kommt, dass Helm mehr ist als ein Templating-Werkzeug. Es ist ein Paketmanager, vergleichbar mit Homebrew auf dem Mac: Du wählst ein Paket, sagst, woher es kommt, und installierst es in den Cluster. Diese Paket-Ebene hat Kustomize nicht und will sie auch nicht haben.

Mit einem Satz: Kustomize passt an, Helm verpackt. Wer diesen Satz im Kopf behält, trifft die Entscheidung meistens richtig.

Kustomize Patches: Base und Overlays in der Praxis

Ein Kustomize-Projekt besteht aus einer Base und beliebig vielen Overlays. Die Base enthält die Manifeste, wie du sie ohnehin schreiben würdest, plus eine kustomization.yaml, die sie auflistet. Für ein Deployment web mit einem Service sieht die Base so aus:

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

Das Overlay für die Produktion verweist auf die Base und bringt einen Patch mit. Der Patch ist ein unvollständiges Manifest, das nur die Felder enthält, die sich ändern sollen. Das target sagt Kustomize, auf welche Ressource der Patch angewendet wird:

# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
namePrefix: prod-
commonAnnotations:
  owner: platform-team
patches:
  - path: replicas.yaml
    target:
      kind: Deployment
      name: web
# overlays/prod/replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: web
          image: registry.example.com/web:stable
          resources:
            requests:
              cpu: 100m
              memory: 128Mi

Mit kubectl kustomize overlays/prod siehst du das fertige Ergebnis auf der Konsole, mit kubectl apply -k overlays/prod rollst du es aus. Das Deployment heißt jetzt prod-web, trägt die Annotation, hat drei Replicas und die Ressourcen-Requests, der Service ist bis auf Präfix und Annotation unverändert. Diese Vorschau ist einer der größten Vorteile von Kustomize: Das Ergebnis ist gewöhnliches YAML, das du mit jedem Validator prüfen und im Code-Review lesen kannst.

Diese Form heißt Strategic Merge Patch, und sie deckt in meinen Projekten neun von zehn Fällen ab. Für Felder in Listen, die sich damit nicht sauber treffen lassen, gibt es zusätzlich JSON-Patches nach RFC 6902, in denen du eine Operation und einen Pfad angibst:

patches:
  - target:
      kind: Deployment
      name: web
    patch: |-
      - op: replace
        path: /spec/replicas
        value: 3

Über die Patches hinaus bringt Kustomize eingebaute Generatoren und Transformer mit. Der configMapGenerator baut eine ConfigMap direkt aus vorhandenen Konfigurationsdateien, statt dass du ihren Inhalt in ein Manifest kopierst, und hängt einen Hash an den Namen, sodass ein geänderter Inhalt automatisch einen neuen Rollout auslöst. commonAnnotations, namePrefix und nameSuffix hast du oben gesehen; damit erfüllst du Compliance-Vorgaben wie eine Kostenstelle an jeder Ressource, ohne sie einzeln zu pflegen. Die vollständige Liste steht in der Kustomize-Referenz auf kubernetes.io.

Helm: Chart, Release und Values

Bei Helm musst du drei Begriffe kennen. Ein Chart ist das Paket: alle Templates und Standardwerte, die eine Anwendung zum Laufen braucht. Ein Release ist eine installierte Instanz eines Charts im Cluster, und dasselbe Chart kann mehrfach als eigenes Release laufen. Ein Repository ist der Ort, an dem Charts abgelegt und verteilt werden, ähnlich wie eine Container-Registry für Images.

Die Anpassung an Umgebungen läuft über Values. Jedes Chart liefert eine values.yaml mit Standardwerten mit, und du überschreibst nur, was abweicht:

# values.yaml (Standardwerte im Chart)
replicaCount: 1
image:
  repository: registry.example.com/web
  tag: latest
ingress:
  enabled: false
# values-prod.yaml
replicaCount: 3
image:
  tag: stable
ingress:
  enabled: true
  host: shop.example.com

Ausgerollt wird mit helm upgrade --install web ./charts/web -f values-prod.yaml. Die Option --install sorgt dafür, dass derselbe Befehl beim ersten Mal installiert und danach aktualisiert; in einer Pipeline musst du so nicht unterscheiden, ob das Release schon existiert. Die values.yaml im Chart ist dabei immer die Grundlage, jede Datei mit -f überschreibt sie, und bei mehreren gewinnt die letzte. Bei mir liegen deshalb Firmen-Standards, Umgebungswerte und Cluster-Besonderheiten in getrennten Dateien.

Im Template steht dann zum Beispiel, dass der Ingress nur erzeugt wird, wenn er eingeschaltet ist. So etwas geht mit Kustomize nur, indem du die Ingress-Datei ausschließlich in das Prod-Overlay legst:

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}
spec:
  rules:
    - host: {{ .Values.ingress.host }}
{{- end }}

Helm merkt sich außerdem jede Revision eines Releases. helm history web zeigt sie an, helm rollback web 3 stellt eine frühere her, und helm uninstall web entfernt alle Ressourcen, die zum Release gehören, in einem Rutsch. Diese Buchführung im Cluster ist der Preis und zugleich der Nutzen von Helm: mehr Komfort, aber auch ein Zustand außerhalb von Git, den du kennen musst. Wie ein Chart im Detail aufgebaut ist, steht in Helm Charts erklärt: Pakete für Kubernetes.

Wann Kustomize, wann Helm: die Entscheidungstabelle

Die folgende Tabelle fasst zusammen, wie ich in Projekten entscheide. Sie ist eine Erfahrungsregel, keine Norm, und in Grenzfällen gewinnt das Tool, das dein Team schon kennt. Die erste Zeile ist in der Praxis die schnellste Wahlhilfe: Fremdsoftware kommt fast immer als Chart, eigene Manifeste kommen fast immer ohne Templates aus.

Situation Kustomize Helm
Fremdsoftware oder eigene Anwendung? eigene Anwendung, deren Manifeste du selbst schreibst Fremdsoftware, die als Chart geliefert wird
Eigene Anwendung, zwei bis vier Umgebungen erste Wahl, reines YAML funktioniert, aber mehr Aufwand
Software für andere Teams oder Kunden paketieren nicht vorgesehen erste Wahl, Chart plus Repository
Fertige Software installieren (Prometheus, cert-manager, ArgoCD) nur zum Nachpatchen fremder Manifeste erste Wahl, die Projekte liefern Charts
Optionale Ressourcen je Umgebung Datei nur im passenden Overlay Bedingung im Template
Gleiche App mehrfach im selben Cluster namePrefix und nameSuffix eigenes Release je Instanz
Abhängigkeiten (App braucht Datenbank-Chart) manuell zusammenstellen Dependencies in Chart.yaml
Rollback über Git-Historie Release-Revisionen und Git
Ergebnis vor dem Ausrollen prüfen kubectl kustomize liefert YAML helm template liefert YAML
Lernkurve flach, nur YAML und Patches Go-Templates und Helper-Funktionen
Zustand im Cluster keiner, nur die Ressourcen Release-Secrets mit Historie

Drei Muster sehe ich am häufigsten. Ein Team mit einer eigenen Anwendung und den Umgebungen dev, staging und prod fährt mit Kustomize schneller und mit weniger Fehlern, weil jeder das Ergebnis lesen kann. Eine Agentur, die dieselbe Software für mehrere Kunden mit leicht unterschiedlicher Konfiguration betreibt, braucht Helm, weil ein Chart mit Values genau dieses Problem beschreibt. Und jeder Cluster, der Prometheus, cert-manager oder ArgoCD selbst betreibt, nutzt Helm, weil die Projekte ihre Software als Charts ausliefern und niemand diese Manifeste von Hand pflegen will.

Ein ehrlicher Hinweis zu fremden Charts: Sie sind bequem, aber groß, schwer zu lesen und nicht auf deinen Fall zugeschnitten. Vor dem Produktivbetrieb schaue ich in die Templates hinein und prüfe, ob das Chart gepflegt wird. Für die eigene Anwendung ist ein kleines, selbst geschriebenes Chart oft besser als ein aufgeblasenes Vorlagen-Chart.

Kustomize vs Helm mit ArgoCD: was der GitOps-Fluss ändert

Sobald ArgoCD ins Spiel kommt, verschiebt sich die Frage. ArgoCD kann beides nativ: Es erkennt eine kustomization.yaml im Pfad und rendert mit Kustomize, es erkennt eine Chart.yaml und rendert mit Helm. Die Application-Ressource für ein Kustomize-Overlay ist entsprechend kurz:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-prod
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/infra.git
    targetRevision: main
    path: kustomize/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: web
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Für Helm tauschst du den Quellblock aus und gibst die Values-Dateien an:

  source:
    repoURL: https://github.com/example/infra.git
    targetRevision: main
    path: charts/web
    helm:
      valueFiles:
        - values.yaml
        - values-prod.yaml

Die wichtigste Stolperfalle, über die ich selbst gestolpert bin: ArgoCD installiert Helm Charts nicht mit helm install, sondern rendert sie mit helm template und wendet das Ergebnis wie gewöhnliche Manifeste an. Es gibt also kein Helm Release im Cluster, helm ls zeigt nichts an, und helm rollback funktioniert nicht. Rollback heißt in diesem Fall: den Commit in Git zurückdrehen, ArgoCD synchronisiert den alten Stand. Auch Template-Funktionen, die zur Laufzeit in den Cluster schauen, liefern beim Rendern keine Daten. Wer diese Grenzen kennt, kommt gut zurecht; wer sie nicht kennt, sucht lange nach dem Fehler. Die Details stehen in der ArgoCD-Dokumentation zu Helm.

Damit verliert Helm im GitOps-Betrieb seinen größten Komfortvorteil, die Release-Buchführung, und Kustomize verliert seinen größten Nachteil, das fehlende Paketformat. Denn ArgoCD versioniert ohnehin über Git, und ein Chart aus einem Repository kann Kustomize über den Eintrag helmCharts in der kustomization.yaml einbinden und mit Patches nachbearbeiten. ArgoCD muss dafür mit der Build-Option --enable-helm laufen, was in der ArgoCD-Dokumentation zu Kustomize beschrieben ist.

So laufen meine Cluster heute: Die Infrastruktur-Komponenten kommen als Helm Charts aus den Repositories der Projekte, mit Values-Dateien in Git. Eigene Anwendungen bekommen ein kleines Chart, wenn sie mehrfach oder bei mehreren Kunden laufen, und Kustomize, wenn es nur um dev und prod derselben Installation geht. Wo ein fremdes Chart eine Kleinigkeit nicht anbietet, patcht Kustomize das gerenderte Ergebnis nach, statt dass ich das Chart forke. Den kompletten Aufbau beschreibe ich in GitOps mit ArgoCD: Deployments aus Git.

Häufige Fragen

Kann ich Kustomize und Helm kombinieren?

Ja, und das ist in der Praxis der häufigste Aufbau. Helm liefert das Paket, Kustomize passt das gerenderte Ergebnis an: entweder über helm template in der Pipeline mit anschließendem kubectl apply -k, oder über den Eintrag helmCharts in der kustomization.yaml, den Kustomize mit der Option --enable-helm auswertet. So bekommst du fertige Charts und trotzdem reines YAML als letzten Schritt.

Muss ich Kustomize extra installieren?

Nein. Kustomize ist in kubectl eingebaut und läuft über kubectl kustomize für die Vorschau und kubectl apply -k für das Ausrollen. Die eigenständige kustomize-CLI ist meist neuer als die in kubectl eingebaute Version und bietet ein paar Funktionen früher; für den Anfang brauchst du sie nicht.

Was sind Kustomize Patches genau?

Ein Patch ist ein unvollständiges Manifest oder eine Liste von Operationen, die Kustomize auf eine Ressource der Base anwendet. Strategic Merge Patches sehen aus wie ein gekürztes Deployment und werden mit dem Original verschmolzen. JSON-Patches nach RFC 6902 beschreiben einzelne Operationen wie replace oder add an einem Pfad und helfen bei Listenelementen, die sich anders schwer treffen lassen.

Ist Kustomize einfacher zu lernen als Helm?

Für ein Team, das Kubernetes-Manifeste schreiben kann, ja. Kustomize verlangt nur das Konzept Base plus Overlay und eine Handvoll Felder in der kustomization.yaml. Helm verlangt zusätzlich die Go-Template-Sprache mit Bedingungen, Schleifen, Helper-Dateien und den Umgang mit Whitespace im Template. Der Aufwand lohnt sich, sobald du Charts für andere baust; für zwei Umgebungen einer eigenen App lohnt er sich selten.

Brauche ich Helm überhaupt noch, wenn ich ArgoCD nutze?

Für eigene Anwendungen nicht zwingend, weil ArgoCD Versionierung und Rollback über Git übernimmt. Für Infrastruktur-Software wie Prometheus, cert-manager oder ArgoCD selbst bleibt Helm der Standard, weil die Projekte ihre Manifeste als Charts pflegen. ArgoCD rendert diese Charts, ohne dass du die Helm-CLI im Betrieb brauchst.

Wie du weitermachst

Wenn du gerade vor der Entscheidung stehst, leg deine Manifeste als Kustomize-Base mit einem Overlay je Umgebung an und schau, ob du damit auskommst. Sobald du ein Paket für andere brauchst oder eine Bedingung im Manifest, die sich mit Overlays nicht sauber abbilden lässt, wechsle für genau diese Anwendung auf ein Chart. Wie ein Chart aufgebaut ist, zeigt Helm Charts erklärt: Pakete für Kubernetes, und wie beide Tools mit ArgoCD zusammenarbeiten, steht in GitOps mit ArgoCD: Deployments aus Git.

Ausführlich mit allen Beispielen, den Generatoren und dem vollständigen Aufbau eines Charts steht das in den Kapiteln 4 und 9 meines Kubernetes-Praxisbuchs bei Rheinwerk.

Kevin Welter

Kevin Welter

Entwickler, IT-Architekt, Fachbuchautor (Kubernetes, Cloud-Infrastrukturen) und Speaker. Betreibt sein Business mit einer KI-Belegschaft aus acht KI-Mitarbeitern und zeigt Selbstständigen in seiner Community, wie sie ihren ersten KI-Mitarbeiter einstellen.

Mehr über KI-Mitarbeiter

Kubernetes von den Grundlagen bis zum produktionsreifen Cluster

Zum Buch