24 ConfigMaps und Secrets

ConfigMaps und Secrets implementieren externe Konfigurationsverwaltung für Container-Anwendungen in OpenShift und ermöglichen strikte Trennung zwischen Anwendungscode und umgebungsspezifischen Konfigurationsdaten. Diese Abstraktionskonzepte fördern Twelve-Factor-App-Prinzipien und unterstützen portable, konfigurierbare Anwendungsdeployments.

24.1 Grundlegende Unterscheidung: ConfigMaps vs. Secrets

ConfigMaps und Secrets lösen dasselbe Problem – externe Konfiguration von Anwendungen – aber für unterschiedliche Datentypen. Die Wahl zwischen beiden hängt von der Sensitivität der Daten ab.

24.1.1 ConfigMaps: Nicht-sensitive Konfigurationsdaten

ConfigMaps verwalten nicht-sensitive Konfigurationsdaten wie Anwendungsparameter, Feature Flags und Umgebungsvariablen in Klartext-Format. Diese Transparenz ermöglicht einfache Inspektion und Debugging von Konfigurationswerten durch Entwickler und Administratoren.

Typische ConfigMap-Inhalte: - Anwendungskonfiguration (Ports, URLs, Feature-Flags) - Logging-Konfiguration - Datenbank-Hostnamen (ohne Passwörter) - Konfigurationsdateien (nginx.conf, application.properties)

24.1.2 Secrets: Sensitive Daten

Secrets handhaben sensitive Daten wie Passwörter, API-Tokens und TLS-Zertifikate mit Base64-Kodierung und zusätzlichen Sicherheitsmaßnahmen. Diese Separation gewährleistet angemessene Zugriffskontrolle und Audit-Trails für kritische Sicherheitsinformationen.

Typische Secret-Inhalte: - Datenbank-Passwörter - API-Schlüssel und Tokens - TLS-Zertifikate und private Schlüssel - Registry-Zugangsdaten

Die konzeptionelle Trennung zwischen öffentlichen und privaten Konfigurationsdaten ermöglicht differenzierte Zugriffsrichtlinien und Governance-Strategien. Diese Klassifizierung unterstützt Compliance-Anforderungen und Least-Privilege-Prinzipien.

24.2 ConfigMaps erstellen und verwenden

ConfigMaps speichern Key-Value-Paare, komplexe Konfigurationsdateien oder binäre Daten als eigenständige Cluster-Ressourcen. Diese Externalisierung ermöglicht Konfigurationsänderungen ohne Container-Neuerstellung oder Anwendungsneuplatzierung.

24.2.1 ConfigMap-Erstellung

Über YAML-Definition:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: production
data:
  database_host: "postgres.company.com"
  database_port: "5432"
  log_level: "INFO"
  feature_new_ui: "true"
  # Komplexe Konfigurationsdatei
  nginx.conf: |
    server {
        listen 80;
        server_name example.com;
        location / {
            proxy_pass http://backend;
        }
    }

Über CLI-Befehle:

# Aus Key-Value-Paaren
oc create configmap app-config \
  --from-literal=database_host=postgres.company.com \
  --from-literal=database_port=5432

# Aus Datei
oc create configmap nginx-config --from-file=nginx.conf

# Aus Verzeichnis (alle Dateien werden zu Keys)
oc create configmap app-configs --from-file=./configs/

24.2.2 Umgebungsspezifische ConfigMaps

Umgebungsspezifische ConfigMaps ermöglichen identische Anwendungsdeployments mit verschiedenen Konfigurationen für Development, Staging und Production-Umgebungen:

# development-config
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: development
data:
  database_host: "postgres-dev.internal"
  log_level: "DEBUG"
  replicas: "1"

---
# production-config
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config  # Gleicher Name, anderer Namespace
  namespace: production
data:
  database_host: "postgres-prod.internal"
  log_level: "WARN"
  replicas: "3"

24.3 Secret-Typen und Verwendung

OpenShift unterstützt verschiedene Secret-Typen für unterschiedliche Anwendungsfälle. Jeder Typ hat spezielle Validierungen und Verwendungsszenarien.

24.3.1 Generic Secrets

Generic Secrets verwalten beliebige Benutzerdaten mit Base64-Kodierung für Obfuscation und konsistente Datenhandhabung:

apiVersion: v1
kind: Secret
metadata:
  name: database-credentials
type: Opaque
data:
  username: YWRtaW4=        # Base64 für "admin"
  password: cGFzc3dvcmQ=    # Base64 für "password"
stringData:  # Alternative: Klartext wird automatisch kodiert
  api_key: "sk-1234567890abcdef"

Erstellung über CLI:

# Generic Secret erstellen
oc create secret generic database-credentials \
  --from-literal=username=admin \
  --from-literal=password=secretpassword

# Aus Datei erstellen
oc create secret generic app-secrets --from-file=.env

24.3.2 TLS Secrets

TLS Secrets kapseln X.509-Zertifikate und private Schlüssel für HTTPS-Konnektivität:

apiVersion: v1
kind: Secret
metadata:
  name: webapp-tls
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTi... # Base64-kodiertes Zertifikat
  tls.key: LS0tLS1CRUdJTi... # Base64-kodierter privater Schlüssel

CLI-Erstellung:

oc create secret tls webapp-tls \
  --cert=path/to/cert.crt \
  --key=path/to/private.key

24.3.3 Docker Registry Secrets

Docker Registry Secrets ermöglichen Pull-Access zu privaten Container-Registries:

apiVersion: v1
kind: Secret
metadata:
  name: private-registry
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS... # Base64-kodierte Docker-Config

CLI-Erstellung:

oc create secret docker-registry private-registry \
  --docker-server=registry.company.com \
  --docker-username=serviceaccount \
  --docker-password=token123 \
  --docker-email=devops@company.com

24.3.4 Service Account Tokens

Service Account Tokens werden automatisch erstellt und verwalten Pod-zu-API-Server-Authentifizierung:

# Service Account Token anzeigen
oc get secret $(oc get sa default -o jsonpath='{.secrets[0].name}') -o yaml

24.4 Konfiguration in Pods konsumieren

ConfigMaps und Secrets können auf verschiedene Weise in Pods konsumiert werden. Die Wahl der Methode hängt von Anwendungsanforderungen und Update-Verhalten ab.

24.4.1 Environment Variable-Injection

Environment Variable-Injection überträgt ConfigMap- und Secret-Werte als Container-Umgebungsvariablen:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  template:
    spec:
      containers:
      - name: webapp
        image: nginx
        env:
        # Einzelne Values aus ConfigMap
        - name: DATABASE_HOST
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: database_host
        # Alle Keys aus ConfigMap
        envFrom:
        - configMapRef:
            name: app-config
        # Secret-Values
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: database-credentials
              key: password
        # Alle Keys aus Secret
        envFrom:
        - secretRef:
            name: database-credentials

Vorteil: Einfache Integration für Anwendungen, die Umgebungsvariablen erwarten. Nachteil: Updates erfordern Pod-Restart.

24.4.2 Volume Mounts

Volume Mount-Integration stellt ConfigMap- und Secret-Daten als Dateisystem-Inhalte zur Verfügung:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: webapp
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
      volumes:
      - name: config-volume
        configMap:
          name: app-config
      - name: secret-volume
        secret:
          secretName: database-credentials
          defaultMode: 0400  # Restriktive Dateiberechtigungen

Resultat im Container:

/etc/config/database_host      # Inhalt: postgres.company.com
/etc/config/nginx.conf         # Inhalt: Nginx-Konfiguration
/etc/secrets/username          # Inhalt: admin
/etc/secrets/password          # Inhalt: secretpassword

Vorteil: Updates werden automatisch propagiert (nach kurzer Verzögerung). Nachteil: Anwendung muss Dateisystem-basierte Konfiguration unterstützen.

24.4.3 Projected Volumes

Projected Volumes ermöglichen Kombination mehrerer ConfigMaps und Secrets in einzelnen Volume-Mounts:

volumes:
- name: combined-config
  projected:
    sources:
    - configMap:
        name: app-config
    - secret:
        name: database-credentials
    - secret:
        name: api-credentials
        items:
        - key: api_key
          path: api/key.txt  # Custom-Pfad

24.4.4 Subpath-Mounts

Einzelne Keys als spezifische Dateien mounten:

volumeMounts:
- name: config-volume
  mountPath: /etc/nginx/nginx.conf
  subPath: nginx.conf  # Nur diese Datei mounten

24.5 Update-Verhalten und Lifecycle

ConfigMap- und Secret-Updates haben unterschiedliche Auswirkungen je nach Consumption-Methode:

24.5.1 Update-Szenarien

Consumption-Methode Update-Propagation Restart-Erforderlich
Environment Variables Nein Ja (Pod-Restart)
Volume Mounts Ja (nach ~1 Minute) Nein (App-abhängig)
Projected Volumes Ja (nach ~1 Minute) Nein (App-abhängig)

24.5.2 Immutable ConfigMaps/Secrets

Immutable ConfigMaps und Secrets verhindern Änderungen nach Erstellung:

apiVersion: v1
kind: ConfigMap
metadata:
  name: immutable-config
data:
  key: value
immutable: true  # Kann nicht mehr geändert werden

Vorteile: - Schutz vor versehentlichen Änderungen - Performance-Verbesserung (weniger API-Watches) - Bessere Cache-Nutzung

24.5.3 Versionierung für Rolling Updates

Version-Suffixes ermöglichen Blue-Green-Deployment-Strategien:

# Alte Version
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v1
data:
  version: "1.0"

---
# Neue Version
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v2
data:
  version: "2.0"

Deployment kann schrittweise auf neue Version umgestellt werden:

# Deployment Update
spec:
  template:
    spec:
      volumes:
      - name: config-volume
        configMap:
          name: app-config-v2  # Von v1 auf v2 umstellen

24.6 Sicherheitsüberlegungen

Secret-Handling erfordert besondere Aufmerksamkeit für Sicherheit und Compliance.

24.6.1 Encryption at Rest

Secret Encryption-at-Rest gewährleistet Verschlüsselung sensibler Daten im etcd-Cluster-Store:

# OpenShift-Konfiguration (Cluster-Administrator)
apiVersion: config.openshift.io/v1
kind: APIServer
metadata:
  name: cluster
spec:
  encryption:
    type: aescbc  # Verschlüsselungsalgorithmus

24.6.2 RBAC-Integration

Granulare Zugriffskontrolle auf ConfigMap- und Secret-Ressourcen:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: config-reader
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]  # Nur Lese-Zugriff auf Secrets

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developers-config-access
subjects:
- kind: User
  name: developer@company.com
roleRef:
  kind: Role
  name: config-reader

24.6.3 Secret-Rotation

Secret-Rotation-Strategien für regelmäßige Passwort-Updates:

# 1. Neues Secret erstellen
oc create secret generic database-credentials-new \
  --from-literal=username=admin \
  --from-literal=password=new-password

# 2. Deployment auf neues Secret umstellen
oc patch deployment webapp -p '{
  "spec": {
    "template": {
      "spec": {
        "volumes": [{
          "name": "secret-volume",
          "secret": {
            "secretName": "database-credentials-new"
          }
        }]
      }
    }
  }
}'

# 3. Nach erfolgreicher Rotation altes Secret löschen
oc delete secret database-credentials

24.6.4 Pod Security Context

Beschränkung des Secret-Zugriffs auf autorisierte Container:

spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: webapp
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true

24.7 Integration mit externen Systemen

24.7.1 External Secrets Operator

Integration mit Enterprise Key Management Systems:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: vault-secret
spec:
  refreshInterval: 5m
  secretStoreRef:
    name: vault-backend
    kind: SecretStore
  target:
    name: database-credentials
    creationPolicy: Owner
  data:
  - secretKey: password
    remoteRef:
      key: database/prod
      property: password

24.7.2 GitOps-Integration

ConfigMaps und Secrets als Code mit Versionskontrolle:

# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

configMapGenerator:
- name: app-config
  files:
  - config/application.properties
  - config/nginx.conf

secretGenerator:
- name: app-secrets
  files:
  - secrets/.env
  type: Opaque

24.8 Performance und Skalierung

24.8.1 Size-Limits beachten

ConfigMaps und Secrets sind auf 1MB begrenzt. Für größere Konfigurationen:

# Aufteilen großer Konfigurationen
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-base
data:
  # Grundkonfiguration
  
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-features
data:
  # Feature-spezifische Konfiguration

24.8.2 Caching und Performance

# ConfigMap-/Secret-Usage prüfen
oc get events --field-selector reason=FailedMount

# Kubelet-Logs für Volume-Mount-Probleme
oc adm node-logs <node-name> -u kubelet

24.9 Troubleshooting häufiger Probleme

24.9.1 ConfigMap/Secret nicht gefunden

# Verfügbare ConfigMaps/Secrets prüfen
oc get configmaps,secrets

# Details anzeigen
oc describe configmap app-config
oc describe secret database-credentials

# Pod-Events prüfen
oc describe pod <pod-name>

24.9.2 Environment Variables nicht gesetzt

# Container-Umgebungsvariablen prüfen
oc exec <pod-name> -- env | grep DATABASE

# ConfigMap-Keys validieren
oc get configmap app-config -o yaml

24.9.3 Volume-Mount-Probleme

# Mounted Volumes prüfen
oc exec <pod-name> -- ls -la /etc/config

# Mount-Details validieren
oc exec <pod-name> -- cat /proc/mounts | grep config

24.9.4 Base64-Dekodierung

# Secret-Inhalt dekodieren
oc get secret database-credentials -o jsonpath='{.data.password}' | base64 -d

24.10 Best Practices für ConfigMaps und Secrets

24.10.1 Strukturierung und Organisation

Naming Conventions:

# Umgebungsspezifische Namen
metadata:
  name: webapp-config-prod
  name: webapp-secrets-prod

# Oder Namespace-basierte Trennung
metadata:
  name: webapp-config
  namespace: production

Granularität: - Separate ConfigMaps für verschiedene Komponenten - Secrets nur für tatsächlich sensitive Daten verwenden - Immutable für kritische Konfigurationen

24.10.2 Security Best Practices

24.10.3 Deployment-Strategien