Veröffentlicht am

ConfigMaps richtig nutzen: Kubernetes Best Practices

Teilen:
Authors

TL;DR

  • ConfigMaps speichern Konfigurationsdaten als Key-Value-Paare oder ganze Dateien getrennt vom Container-Image
  • Drei Erstellungsmethoden: --from-literal, --from-file und --from-env-file decken alle Anwendungsfälle ab
  • Volume Mounts ermöglichen Hot-Reload, Environment Variables sind statisch nach Pod-Start
  • Immutable ConfigMaps (Kubernetes 1.21+) reduzieren API-Server-Last und verhindern versehentliche Änderungen
  • Tools wie Reloader lösen automatische Pod-Neustarts bei ConfigMap-Änderungen aus

ConfigMaps in Kubernetes richtig einsetzen

Konfiguration gehört nicht ins Container-Image. Kubernetes ConfigMaps trennen Anwendungskonfiguration von der Laufzeitumgebung. Damit lässt sich dieselbe Anwendung in Dev, Staging und Production mit unterschiedlichen Einstellungen betreiben - ohne neues Image.

ConfigMaps erstellen: Drei Wege

# 1. Aus Literalen - für einzelne Werte
kubectl create configmap app-config \
  --from-literal=DATABASE_HOST=postgres.default.svc \
  --from-literal=LOG_LEVEL=info \
  --from-literal=MAX_CONNECTIONS=100

# 2. Aus einer Datei - für komplexe Konfiguration
kubectl create configmap nginx-config \
  --from-file=nginx.conf=/etc/nginx/nginx.conf

# 3. Aus einer Env-Datei - für .env-Formate
kubectl create configmap env-config \
  --from-env-file=production.env

Alle drei Varianten erzeugen dasselbe Kubernetes-Objekt, unterscheiden sich aber in der Datenstruktur. --from-literal speichert einzelne Strings, --from-file den gesamten Dateiinhalt unter dem Dateinamen als Key, --from-env-file parsed Key=Value-Paare.


Deklarativ per YAML

Für GitOps und reproduzierbare Deployments ist die deklarative Variante Standard:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
  labels:
    app: backend
    environment: production
data:
  # Einfache Key-Value-Paare
  DATABASE_HOST: "postgres.production.svc"
  LOG_LEVEL: "warn"
  MAX_CONNECTIONS: "200"

  # Mehrzeilige Konfigurationsdatei
  application.yaml: |
    server:
      port: 8080
      shutdown: graceful
    spring:
      datasource:
        hikari:
          maximum-pool-size: 20
          minimum-idle: 5
    management:
      endpoints:
        web:
          exposure:
            include: health,metrics,prometheus

Der Vorteil: Die ConfigMap liegt im Git-Repository und wird über CI/CD ausgerollt. Änderungen sind nachvollziehbar und reviewbar.

Volume Mount vs. Environment Variables

Die beiden Wege, ConfigMap-Daten in einen Pod zu bringen, haben grundlegend verschiedene Eigenschaften.

Als Environment Variables

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: registry.company.de/backend:2.1.0
          envFrom:
            - configMapRef:
                name: app-config
          # Oder selektiv einzelne Keys:
          env:
            - name: DB_HOST
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: DATABASE_HOST

Environment Variables werden beim Pod-Start gesetzt und ändern sich nicht, wenn die ConfigMap aktualisiert wird. Der Pod muss neu gestartet werden.

Als Volume Mount

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          volumeMounts:
            - name: config-volume
              mountPath: /etc/nginx/conf.d
              readOnly: true
          # Optional: SubPath für einzelne Dateien
          # Achtung: SubPath verhindert automatische Updates!
            - name: config-volume
              mountPath: /etc/nginx/nginx.conf
              subPath: nginx.conf
      volumes:
        - name: config-volume
          configMap:
            name: nginx-config
            # Optional: Berechtigungen setzen
            defaultMode: 0644

Volume Mounts aktualisieren sich automatisch, wenn die ConfigMap geändert wird (Kubelet Sync, Standard ca. 60 Sekunden). Ausnahme: Bei subPath findet kein automatisches Update statt.

Vergleich auf einen Blick

EigenschaftEnvironment VariableVolume Mount
Auto-UpdateNeinJa (ohne subPath)
Zugriffos.Getenv()Datei lesen
AnwendungsfallEinzelne WerteConfig-Dateien
Sichtbarkeitkubectl exec envDateisystem
SubPath-Update-Nein

Immutable ConfigMaps

Seit Kubernetes 1.21 können ConfigMaps als immutable markiert werden. Das hat zwei Vorteile: Der API-Server muss keine Watches mehr für diese ConfigMaps verwalten (Performance-Gewinn bei vielen ConfigMaps), und versehentliche Änderungen werden verhindert.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v3
  labels:
    app: backend
    version: "3"
immutable: true
data:
  DATABASE_HOST: "postgres.production.svc"
  LOG_LEVEL: "warn"
  FEATURE_NEW_UI: "true"

Eine immutable ConfigMap kann nicht mehr editiert werden. Der Workflow für Änderungen: Neue ConfigMap mit neuem Namen (z.B. Versionssuffix) erstellen und das Deployment darauf umstellen.

# Alte ConfigMap kann nicht geändert werden:
# kubectl edit configmap app-config-v3
# -> Fehler: "configmap is immutable"

# Stattdessen: Neue Version erstellen
kubectl create configmap app-config-v4 \
  --from-literal=DATABASE_HOST=postgres.production.svc \
  --from-literal=LOG_LEVEL=debug \
  --from-literal=FEATURE_NEW_UI=true \
  --dry-run=client -o yaml | \
  kubectl apply -f -

# Deployment auf neue Version umstellen
kubectl set env deployment/backend --from=configmap/app-config-v4

Hot-Reload mit Reloader

Volume Mounts aktualisieren zwar die Dateien, aber viele Anwendungen lesen ihre Config nur beim Start. Der Stakater Reloader überwacht ConfigMaps und startet Pods automatisch neu.

# Reloader installieren
helm repo add stakater https://stakater.github.io/stakater-charts
helm install reloader stakater/reloader -n kube-system

Danach reicht eine Annotation am Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  annotations:
    # Option 1: Bei JEDER ConfigMap-Änderung neu starten
    reloader.stakater.com/auto: "true"

    # Option 2: Nur bei bestimmten ConfigMaps
    configmap.reloader.stakater.com/reload: "app-config"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: registry.company.de/backend:2.1.0
          envFrom:
            - configMapRef:
                name: app-config

Wenn app-config geändert wird, triggert Reloader ein Rolling Update. Damit funktioniert Hot-Reload auch bei Environment Variables.

ConfigMap vs. Secret vs. External Config

Nicht jede Konfiguration gehört in eine ConfigMap. Die Abgrenzung:

DatentypLösungGrund
App-Einstellungen (Ports, Log-Level)ConfigMapNicht sensibel, einfach
Passwörter, API-Keys, ZertifikateSecretBase64-kodiert, RBAC-geschützt
Dynamische Feature FlagsExternal (LaunchDarkly, ConfigCat)Änderungen ohne Deployment
Infrastruktur-CredentialsExternal (Vault, AWS SM)Rotation, Audit, Verschlüsselung
Große Konfigurationen (>1 MB)Volume/Init-ContainerConfigMap-Limit: 1 MiB

ConfigMaps haben ein Größenlimit von 1 MiB. Für größere Konfigurationen eignen sich Init-Container, die Dateien aus S3 oder einem Config-Server laden.

Häufige Fehler vermeiden

Drei Probleme tauchen in der Praxis regelmäßig auf:

1. SubPath blockiert Updates: Wer einzelne Dateien mit subPath mountet, verliert das automatische Update. Alternative: Das gesamte Verzeichnis mounten oder Reloader nutzen.

2. ConfigMap vor dem Deployment erstellen: Referenziert ein Pod eine nicht existierende ConfigMap, startet der Container nicht. In CI/CD-Pipelines die ConfigMap immer vor dem Deployment anwenden.

3. Zu viele kleine ConfigMaps: Jede ConfigMap erzeugt einen Watch am API-Server. Bei Hunderten von ConfigMaps pro Namespace steigt die Last. Zusammengehörige Werte in einer ConfigMap bündeln oder immutable ConfigMaps verwenden.


FAQ

Wie groß darf eine ConfigMap maximal sein?

Eine ConfigMap ist auf 1 MiB (1.048.576 Bytes) begrenzt. Das betrifft die Gesamtgröße aller Keys und Values zusammen. Für größere Datenmengen eignen sich Volumes oder Init-Container.

Werden Pods automatisch neu gestartet, wenn sich eine ConfigMap ändert?

Nein, nicht standardmäßig. Volume Mounts aktualisieren die Dateien im Pod (ca. 60s Verzögerung), aber die Anwendung muss die Änderung selbst erkennen. Environment Variables ändern sich gar nicht. Für automatische Neustarts eignet sich der Stakater Reloader.

Was ist der Unterschied zwischen ConfigMap und Secret?

Technisch sind beide ähnlich - Secrets speichern Daten Base64-kodiert und können über RBAC separat geschützt werden. ConfigMaps sind für nicht-sensible Konfiguration gedacht, Secrets für Passwörter, Tokens und Zertifikate.

Kann ich eine immutable ConfigMap nachträglich ändern?

Nein. Eine als immutable: true markierte ConfigMap kann nicht mehr editiert werden. Die einzige Option ist, eine neue ConfigMap mit anderem Namen zu erstellen und die Referenzen im Deployment zu aktualisieren.

Funktioniert Hot-Reload mit subPath Volume Mounts?

Nein. Bei Verwendung von subPath aktualisiert Kubernetes die gemountete Datei nicht automatisch. Entweder das gesamte Verzeichnis mounten oder einen Sidecar/Reloader verwenden.

Kubernetes-Expertise gesucht?

Managed Services, Beratung, Training oder Security – wir unterstützen deutsche Unternehmen bei allen Kubernetes-Themen.

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