Veröffentlicht am

Helm Charts Tutorial: Eigene Charts erstellen und nutzen

Teilen:
Authors

TL;DR

  • Helm ist der Paketmanager fuer Kubernetes -- er loest das Problem von verstreuten YAML-Dateien durch Templates mit Variablen und Versionierung
  • Drei Schritte zum Start: Repository hinzufuegen (helm repo add), Chart installieren (helm install), Werte anpassen (-f values.yaml)
  • Eigene Charts erstellen mit helm create myapp -- Templates nutzen Go-Syntax fuer Variablen, Conditionals und Loops
  • Best Practices: Sinnvolle Resource Defaults setzen, umgebungsspezifische values-Dateien verwenden, --atomic fuer automatisches Rollback bei Fehlern
  • CI/CD Integration mit GitLab CI oder GitHub Actions macht Helm Deployments vollstaendig automatisierbar

Helm Charts für Kubernetes: Das komplette Tutorial

Helm ist der Paketmanager für Kubernetes - wie apt für Ubuntu oder npm für Node.js. In diesem Tutorial lernen Sie Helm von Grund auf und erstellen Ihr erstes eigenes Chart.

Was ist Helm und warum brauche ich es?

Das Problem ohne Helm

Für eine typische Anwendung brauchen Sie mehrere YAML-Dateien:

myapp/
├── deployment.yaml
├── service.yaml
├── configmap.yaml
├── secret.yaml
├── ingress.yaml
├── hpa.yaml
└── pdb.yaml

Probleme:

  • Werte wie Image-Version, Replicas überall verstreut
  • Verschiedene Umgebungen (dev, staging, prod) = doppelte Dateien
  • Keine Versionierung der Deployments
  • Rollback schwierig

Die Lösung: Helm Charts

myapp-chart/
├── Chart.yaml          # Metadaten
├── values.yaml         # Konfiguration
└── templates/          # YAML mit Variablen
    ├── deployment.yaml
    ├── service.yaml
    └── ...

Vorteile:

  • Eine Konfigurationsdatei für alle Umgebungen
  • Versionierung und Rollback eingebaut
  • Wiederverwendbare Bausteine
  • Tausende fertige Charts verfügbar

Teil 1: Helm installieren

macOS

brew install helm

Linux

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

Windows

choco install kubernetes-helm

Installation prüfen

helm version
# version.BuildInfo{Version:"v3.14.0", ...}

Teil 2: Erste Schritte mit Helm

Repositories hinzufügen

Helm Charts werden in Repositories gehostet:

# Offizielles Bitnami Repository
helm repo add bitnami https://charts.bitnami.com/bitnami

# Repository-Liste aktualisieren
helm repo update

Charts suchen

# Nach nginx suchen
helm search repo nginx

# Mit Beschreibungen
helm search repo nginx --max-col-width=80

Chart installieren

# nginx installieren
helm install my-nginx bitnami/nginx

# Mit eigenem Namespace
helm install my-nginx bitnami/nginx --namespace web --create-namespace

Installationen anzeigen

# Alle Releases
helm list

# Alle Namespaces
helm list -A

Chart aktualisieren

# Werte ändern
helm upgrade my-nginx bitnami/nginx --set replicaCount=3

Chart deinstallieren

helm uninstall my-nginx

Teil 3: Charts konfigurieren

Standard-Werte anzeigen

# Alle konfigurierbaren Werte
helm show values bitnami/nginx | head -100

# Chart-Infos
helm show chart bitnami/nginx

Mit --set konfigurieren

helm install my-nginx bitnami/nginx \
  --set replicaCount=2 \
  --set service.type=ClusterIP \
  --set resources.requests.memory=128Mi

Mit values.yaml konfigurieren

Erstellen Sie my-values.yaml:

replicaCount: 3

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 200m
    memory: 256Mi

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  hostname: nginx.example.de
  tls: true
helm install my-nginx bitnami/nginx -f my-values.yaml

Mehrere Values-Dateien kombinieren

# Basis + Umgebungs-spezifisch
helm install my-nginx bitnami/nginx \
  -f values-base.yaml \
  -f values-production.yaml

Teil 4: Eigenes Helm Chart erstellen

Chart-Grundstruktur erstellen

helm create myapp

Dies erstellt:

myapp/
├── Chart.yaml          # Chart-Metadaten
├── values.yaml         # Standard-Werte
├── charts/             # Dependencies
├── templates/          # Kubernetes Manifests
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   ├── ingress.yaml
│   ├── hpa.yaml
│   ├── _helpers.tpl    # Template-Funktionen
│   ├── NOTES.txt       # Post-Install Nachricht
│   └── tests/
│       └── test-connection.yaml
└── .helmignore

Chart.yaml verstehen

apiVersion: v2
name: myapp
description: Meine Kubernetes-Anwendung
type: application
version: 0.1.0        # Chart-Version
appVersion: "1.0.0"   # App-Version
keywords:
  - example
  - webapp
maintainers:
  - name: DevOps Team
    email: devops@example.de

values.yaml anpassen

# values.yaml
replicaCount: 1

image:
  repository: myregistry/myapp
  pullPolicy: IfNotPresent
  tag: "1.0.0"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  create: true
  automount: true
  annotations: {}
  name: ""

podAnnotations: {}
podLabels: {}

podSecurityContext: {}

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  className: "nginx"
  annotations: {}
  hosts:
    - host: myapp.local
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls: []

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

livenessProbe:
  httpGet:
    path: /health
    port: http
readinessProbe:
  httpGet:
    path: /ready
    port: http

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

nodeSelector: {}
tolerations: []
affinity: {}

Templates verstehen

templates/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "myapp.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "myapp.selectorLabels" . | nindent 8 }}
    spec:
      serviceAccountName: {{ include "myapp.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.port }}
              protocol: TCP
          livenessProbe:
            {{- toYaml .Values.livenessProbe | nindent 12 }}
          readinessProbe:
            {{- toYaml .Values.readinessProbe | nindent 12 }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

Template-Syntax

Variablen:

# Einfache Variable
{{ .Values.replicaCount }}

# Mit Default-Wert
{{ .Values.replicaCount | default 1 }}

# Chart-Metadaten
{{ .Chart.Name }}
{{ .Chart.Version }}

# Release-Info
{{ .Release.Name }}
{{ .Release.Namespace }}

Kontrollstrukturen:

# If-Else
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}

# Range (Loop)
{{- range .Values.ingress.hosts }}
  - host: {{ .host }}
{{- end }}

Funktionen:

# String-Funktionen
{{ .Values.name | upper }}
{{ .Values.name | quote }}

# YAML einbetten
{{- toYaml .Values.resources | nindent 12 }}

# Include Templates
{{- include "myapp.labels" . | nindent 4 }}

Teil 5: Chart testen und debuggen

Template rendern (ohne Installation)

# Alle Templates anzeigen
helm template myapp ./myapp

# Mit Custom-Values
helm template myapp ./myapp -f values-prod.yaml

# Nur bestimmte Templates
helm template myapp ./myapp -s templates/deployment.yaml

Dry-Run

# Simulation der Installation
helm install myapp ./myapp --dry-run --debug

Chart validieren

# Syntax prüfen
helm lint ./myapp

# Mit strikter Prüfung
helm lint ./myapp --strict

Installation debuggen

# Detaillierte Ausgabe
helm install myapp ./myapp --debug

# Installation prüfen
helm get manifest myapp
helm get values myapp
helm get notes myapp

Teil 6: Helm Best Practices

1. Sinnvolle Defaults

# values.yaml
resources:
  limits:
    cpu: 100m       # Immer setzen
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

securityContext:
  runAsNonRoot: true    # Security by Default
  readOnlyRootFilesystem: true

2. Umgebungs-spezifische Values

myapp/
├── values.yaml           # Defaults
├── values-dev.yaml       # Development
├── values-staging.yaml   # Staging
└── values-prod.yaml      # Production
# values-prod.yaml
replicaCount: 3
resources:
  limits:
    cpu: 500m
    memory: 512Mi
autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
helm install myapp ./myapp -f values-prod.yaml

3. Versionierung

# Chart.yaml
version: 0.2.0      # Erhöhen bei Chart-Änderungen
appVersion: "1.2.3" # Erhöhen bei App-Änderungen

4. Dependencies

# Chart.yaml
dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled
# Dependencies installieren
helm dependency update ./myapp

Teil 7: Helm in CI/CD

GitLab CI Beispiel

# .gitlab-ci.yml
stages:
  - lint
  - deploy

helm-lint:
  stage: lint
  image: alpine/helm:3.14.0
  script:
    - helm lint ./myapp

deploy-staging:
  stage: deploy
  image: alpine/helm:3.14.0
  script:
    - helm upgrade --install myapp ./myapp
        -f values-staging.yaml
        --namespace staging
        --create-namespace
        --wait
        --timeout 5m
  environment:
    name: staging
  only:
    - develop

deploy-production:
  stage: deploy
  image: alpine/helm:3.14.0
  script:
    - helm upgrade --install myapp ./myapp
        -f values-prod.yaml
        --namespace production
        --wait
        --timeout 10m
        --atomic
  environment:
    name: production
  only:
    - main
  when: manual

GitHub Actions Beispiel

# .github/workflows/helm-deploy.yaml
name: Helm Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Helm
        uses: azure/setup-helm@v4

      - name: Configure kubectl
        uses: azure/k8s-set-context@v4
        with:
          kubeconfig: ${{ secrets.KUBECONFIG }}

      - name: Helm Lint
        run: helm lint ./myapp

      - name: Helm Deploy
        run: |
          helm upgrade --install myapp ./myapp \
            -f values-prod.yaml \
            --namespace production \
            --wait \
            --atomic

Teil 8: Nützliche Helm Commands

Release-Management

# Alle Releases
helm list -A

# Release-Historie
helm history myapp

# Rollback zur vorherigen Version
helm rollback myapp

# Rollback zu bestimmter Revision
helm rollback myapp 2

Troubleshooting

# Installierte Manifests
helm get manifest myapp

# Verwendete Values
helm get values myapp

# Alles (values, hooks, manifest, notes)
helm get all myapp

# Status
helm status myapp

Repository-Verwaltung

# Repos anzeigen
helm repo list

# Repo entfernen
helm repo remove bitnami

# Lokales Repo
helm repo index ./my-charts --url https://charts.example.de

Häufige Probleme und Lösungen

Problem: Template-Fehler

Error: parse error at (myapp/templates/deployment.yaml:10)

Lösung:

# Template einzeln rendern
helm template myapp ./myapp -s templates/deployment.yaml --debug

Problem: Values werden nicht übernommen

Lösung:

# Effektive Values prüfen
helm get values myapp -a

# Mit Debug
helm install myapp ./myapp --dry-run --debug | grep -A 20 "USER-SUPPLIED VALUES"

Problem: Upgrade schlägt fehl

# Mit --atomic: automatischer Rollback bei Fehler
helm upgrade myapp ./myapp --atomic --timeout 5m

# Force-Update
helm upgrade myapp ./myapp --force

Zusammenfassung

AufgabeBefehl
Chart erstellenhelm create myapp
Chart installierenhelm install myapp ./myapp
Chart upgradenhelm upgrade myapp ./myapp
Mit Values-f values-prod.yaml
Dry-Run--dry-run --debug
Rollbackhelm rollback myapp
Deinstallierenhelm uninstall myapp

Nächste Schritte

  1. Heute: Helm installieren und erstes Chart aus Repository deployen
  2. Diese Woche: Eigenes Chart für Ihre Anwendung erstellen
  3. Dieser Monat: Helm in CI/CD Pipeline integrieren

Weiterführende Artikel:


Sie wollen Helm professionell einsetzen, aber keine Zeit für die Lernkurve? Als Managed Service Partner übernehmen wir das Helm-Management für Sie - inklusive Chart-Entwicklung, CI/CD Integration und laufender Wartung.

Kubernetes-Beratung gesucht?

Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.

📖 Verwandte Artikel

Weitere interessante Beiträge zu ähnlichen Themen