27 Deployment-Konfigurationen

Deployment-Konfigurationen in OpenShift definieren deklarative Spezifikationen für Anwendungsbereitstellung und -verwaltung durch strukturierte Metadaten und Konfigurationsparameter. Diese Konfigurationsobjekte abstrahieren komplexe Orchestrierungsdetails und ermöglichen konsistente, reproduzierbare Deployments über verschiedene Umgebungen und Cluster hinweg.

27.1 Deklarative Konfiguration verstehen

OpenShift Deployment-Konfigurationen implementieren Infrastructure-as-Code-Prinzipien durch YAML- oder JSON-basierte Ressourcendefinitionen, die gewünschte Anwendungszustände beschreiben. Diese deklarative Herangehensweise entkoppelt Deployment-Intent von imperativen Ausführungsschritten und ermöglicht GitOps-Workflows.

[Diagramm: Deployment-Konfigurationshierarchie mit Templates, Kustomize und Environment-Overlays]

Der grundlegende Unterschied zwischen deklarativer und imperativer Konfiguration zeigt sich in der Praxis:

Imperativ (was zu tun ist):

oc create deployment webapp --image=nginx:1.20
oc scale deployment webapp --replicas=3
oc expose deployment webapp --port=80

Deklarativ (was erreicht werden soll):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: nginx:1.20
        ports:
        - containerPort: 80

27.1.1 Template-basierte Konfigurationen

Template-basierte Konfigurationen ermöglichen Parametrisierung wiederkehrender Deployment-Patterns durch variable Substitution. Diese Abstraktionsebene unterstützt umgebungsspezifische Anpassungen ohne Duplikation von Basis-Konfigurationen.

apiVersion: template.openshift.io/v1
kind: Template
metadata:
  name: webapp-template
parameters:
- name: APP_NAME
  description: "Name der Anwendung"
  required: true
- name: IMAGE_TAG
  description: "Container Image Tag"
  value: "latest"
- name: REPLICAS
  description: "Anzahl der Pod-Replicas"
  value: "2"
objects:
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: ${APP_NAME}
  spec:
    replicas: ${{REPLICAS}}
    selector:
      matchLabels:
        app: ${APP_NAME}
    template:
      metadata:
        labels:
          app: ${APP_NAME}
      spec:
        containers:
        - name: ${APP_NAME}
          image: nginx:${IMAGE_TAG}

Template verwenden:

# Template mit Parametern instanziieren
oc process -f webapp-template.yaml \
  -p APP_NAME=frontend \
  -p IMAGE_TAG=1.20 \
  -p REPLICAS=3 | oc apply -f -

27.1.2 Kustomize-Integration

Kustomize erweitert native Kubernetes-Konfigurationsmanagement um Overlay-Mechanismen für umgebungsspezifische Modifikationen:

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

resources:
- deployment.yaml
- service.yaml

commonLabels:
  app: webapp
  
---
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../../base

replicas:
- name: webapp
  count: 5

images:
- name: nginx
  newTag: 1.20-alpine

patchesStrategicMerge:
- production-resources.yaml

27.2 Container-Spezifikationen im Detail

Container-Definitionen spezifizieren Image-References, Resource-Requirements und Environment-Variablen für individuelle Container innerhalb von Pod-Templates. Diese granularen Konfigurationen ermöglichen optimale Ressourcenallokation und Anwendungstuning.

27.2.1 Basis-Container-Konfiguration

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: webapp
        image: nginx:1.20
        # Port-Exposition
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
        - name: metrics
          containerPort: 9090
          protocol: TCP
        # Ressourcen-Management
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        # Environment-Variablen
        env:
        - name: NODE_ENV
          value: "production"
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
        # Volume-Mounts
        volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/conf.d
        - name: data-volume
          mountPath: /var/www/html

27.2.2 Init Container-Konfigurationen

Init Container definieren Vorbereitungsschritte für Hauptcontainer-Start:

spec:
  template:
    spec:
      initContainers:
      # Database Migration Init Container
      - name: db-migration
        image: webapp:latest
        command: ['npm', 'run', 'migrate']
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
      # File Download Init Container  
      - name: file-downloader
        image: busybox
        command: ['wget', '-O', '/shared/config.json', 'https://api.company.com/config']
        volumeMounts:
        - name: shared-data
          mountPath: /shared
      # Hauptcontainer starten erst nach Init Container
      containers:
      - name: webapp
        image: webapp:latest
        volumeMounts:
        - name: shared-data
          mountPath: /app/config

27.2.3 Multi-Container Pods (Sidecar Pattern)

Sidecar-Container-Pattern werden über Multi-Container-Pod-Spezifikationen implementiert:

spec:
  template:
    spec:
      containers:
      # Hauptanwendung
      - name: webapp
        image: webapp:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: logs
          mountPath: /var/log/app
      # Logging Sidecar
      - name: log-shipper
        image: fluentd:latest
        volumeMounts:
        - name: logs
          mountPath: /var/log/app
          readOnly: true
        env:
        - name: LOG_OUTPUT
          value: "elasticsearch:9200"
      # Monitoring Sidecar
      - name: metrics-exporter
        image: prometheus/node-exporter:latest
        ports:
        - containerPort: 9100
          name: metrics
      volumes:
      - name: logs
        emptyDir: {}

27.3 Security Context und Service Accounts

Service Account-Zuweisungen definieren Identity-Context für Pod-Ausführung und ermöglichen RBAC-basierte Zugriffskontrolle auf Cluster-Ressourcen.

27.3.1 Service Account-Konfiguration

# Service Account definieren
apiVersion: v1
kind: ServiceAccount
metadata:
  name: webapp-sa
imagePullSecrets:
- name: private-registry
secrets:
- name: webapp-secrets

---
# In Deployment verwenden
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      serviceAccountName: webapp-sa
      containers:
      - name: webapp
        image: private-registry.company.com/webapp:latest

27.3.2 Security Context-Einstellungen

Security Context Constraints (SCC) spezifizieren Sicherheitsrichtlinien für Container-Ausführung:

spec:
  template:
    spec:
      # Pod-weite Security-Einstellungen
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 3000
        fsGroup: 2000
        supplementalGroups: [4000]
        seLinuxOptions:
          level: "s0:c123,c456"
      containers:
      - name: webapp
        # Container-spezifische Security-Einstellungen
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE  # Für Port < 1024
        volumeMounts:
        - name: tmp-volume
          mountPath: /tmp
        - name: var-cache
          mountPath: /var/cache
      volumes:
      - name: tmp-volume
        emptyDir: {}
      - name: var-cache
        emptyDir: {}

27.3.3 Pod Security Standards

# Namespace mit Pod Security Standard
apiVersion: v1
kind: Namespace
metadata:
  name: secure-app
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

27.4 Environment-spezifische Konfiguration

ConfigMap- und Secret-Integration externalisiert Konfigurationsdaten und sensitive Informationen von Container-Images. Diese Separation ermöglicht identische Container-Images über verschiedene Umgebungen mit umgebungsspezifischen Konfigurationen.

27.4.1 ConfigMap-Integration

spec:
  template:
    spec:
      containers:
      - name: webapp
        # Einzelne Environment-Variablen aus ConfigMap
        env:
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: log_level
        # Alle Keys aus ConfigMap als Environment-Variablen
        envFrom:
        - configMapRef:
            name: app-config
        # ConfigMap als Volume mounten
        volumeMounts:
        - name: config-files
          mountPath: /etc/config
      volumes:
      - name: config-files
        configMap:
          name: app-config
          items:
          - key: nginx.conf
            path: nginx.conf
          - key: app.properties
            path: application.properties

27.4.2 Projected Volumes

Projected Volume-Konfigurationen aggregieren mehrere Konfigurationsquellen:

volumes:
- name: combined-config
  projected:
    sources:
    # ConfigMap-Quelle
    - configMap:
        name: app-config
        items:
        - key: config.yaml
          path: config/app.yaml
    # Secret-Quelle
    - secret:
        name: app-secrets
        items:
        - key: database-password
          path: secrets/db-password
    # Downward API (Pod-Metadaten)
    - downwardAPI:
        items:
        - path: labels/pod-labels
          fieldRef:
            fieldPath: metadata.labels
        - path: cpu-limit
          resourceFieldRef:
            resource: limits.cpu

27.4.3 Downward API-Integration

Downward API ermöglicht Pod-Metadaten-Exposition als Environment-Variablen oder Files:

containers:
- name: webapp
  env:
  # Pod-Informationen als Environment-Variablen
  - name: POD_NAME
    valueFrom:
      fieldRef:
        fieldPath: metadata.name
  - name: POD_IP
    valueFrom:
      fieldRef:
        fieldPath: status.podIP
  - name: NODE_NAME
    valueFrom:
      fieldRef:
        fieldPath: spec.nodeName
  # Resource-Informationen
  - name: CPU_LIMIT
    valueFrom:
      resourceFieldRef:
        resource: limits.cpu
  - name: MEMORY_REQUEST
    valueFrom:
      resourceFieldRef:
        resource: requests.memory

27.5 Health Checks und Probes

Probe-Konfigurationen sind essentiell für zuverlässige Anwendungsbereitstellung und automatisierte Fehlerbehebung.

27.5.1 Probe-Konfiguration im Detail

containers:
- name: webapp
  # Startup Probe (für langsam startende Apps)
  startupProbe:
    httpGet:
      path: /health/startup
      port: 8080
    initialDelaySeconds: 10
    periodSeconds: 5
    timeoutSeconds: 3
    failureThreshold: 12  # Max 60 Sekunden Startup-Zeit
    successThreshold: 1
  
  # Readiness Probe (Traffic-Ready?)
  readinessProbe:
    httpGet:
      path: /health/ready
      port: 8080
      httpHeaders:
      - name: Accept
        value: application/json
    initialDelaySeconds: 5
    periodSeconds: 10
    timeoutSeconds: 2
    failureThreshold: 3
    successThreshold: 1
  
  # Liveness Probe (Container healthy?)
  livenessProbe:
    httpGet:
      path: /health/live
      port: 8080
    initialDelaySeconds: 30
    periodSeconds: 20
    timeoutSeconds: 5
    failureThreshold: 3
    successThreshold: 1

27.5.2 Verschiedene Probe-Typen

HTTP Probe:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
    scheme: HTTPS  # Für TLS-Endpoints

TCP Probe:

readinessProbe:
  tcpSocket:
    port: 5432  # Für Datenbank-Connectivity

Command Probe:

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy

27.6 Resource Management und Scheduling

Resource Request-Spezifikationen definieren minimale CPU- und Memory-Anforderungen für Container-Scheduling und gewährleisten angemessene Ressourcenallokation.

27.6.1 Erweiterte Resource-Konfiguration

containers:
- name: webapp
  resources:
    requests:
      cpu: "100m"        # 0.1 CPU-Kerne
      memory: "128Mi"     # 128 MiB Memory
      ephemeral-storage: "1Gi"  # Lokaler Storage
    limits:
      cpu: "1"           # Max 1 CPU-Kern
      memory: "1Gi"      # Max 1 GiB Memory
      ephemeral-storage: "2Gi"  # Max lokaler Storage

27.6.2 Node Affinity und Pod Placement

Node Affinity-Rules definieren bevorzugte oder erforderliche Node-Charakteristika:

spec:
  template:
    spec:
      # Node Affinity
      affinity:
        nodeAffinity:
          # Harte Anforderung
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/arch
                operator: In
                values: ["amd64"]
              - key: node.kubernetes.io/instance-type
                operator: NotIn
                values: ["t2.micro", "t3.nano"]
          # Weiche Präferenz
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            preference:
              matchExpressions:
              - key: zone
                operator: In
                values: ["us-east-1a"]
        
        # Pod Anti-Affinity (Pods verteilen)
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values: ["webapp"]
              topologyKey: kubernetes.io/hostname

      # Tolerations für Taints
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "webapp"
        effect: "NoSchedule"

27.7 Lifecycle Hooks

PostStart und PreStop Hook-Konfigurationen ermöglichen Anwendungscode-Ausführung bei Container-Lifecycle-Events.

27.7.1 Lifecycle Hook-Beispiele

containers:
- name: webapp
  lifecycle:
    # Nach Container-Start
    postStart:
      exec:
        command:
        - /bin/sh
        - -c
        - |
          echo "Container started at $(date)" >> /var/log/lifecycle.log
          # Warm-up requests
          sleep 10
          curl -s http://localhost:8080/warmup
    
    # Vor Container-Stop
    preStop:
      httpGet:
        path: /shutdown
        port: 8080
        scheme: HTTP
      # Alternative: Command-basiert
      # exec:
      #   command:
      #   - /bin/sh
      #   - -c
      #   - nginx -s quit; sleep 15

  # Termination Grace Period
  terminationGracePeriodSeconds: 60  # Max 60s für graceful shutdown

27.8 Advanced Deployment-Konfigurationen

27.8.1 Rolling Update-Strategien

Rolling Update-Parameter kontrollieren Update-Geschwindigkeit und Verfügbarkeits-Requirements:

apiVersion: apps/v1
kind: Deployment
spec:
  # Update-Strategie
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1      # Max 1 Pod gleichzeitig unavailable
      maxSurge: 2           # Max 2 zusätzliche Pods während Update
  
  # Revision-Historie
  revisionHistoryLimit: 10  # 10 alte ReplicaSets für Rollback behalten
  
  # Update-Fortschritt
  progressDeadlineSeconds: 600  # Max 10 Minuten für Update
  
  template:
    # Pod-Template wie gewohnt

27.8.2 Recreate-Strategie

spec:
  strategy:
    type: Recreate  # Alle Pods stoppen, dann neue starten
  # Geeignet für:
  # - Single-Instance-Anwendungen
  # - Persistent Volumes mit ReadWriteOnce
  # - Anwendungen die keine parallelen Instanzen unterstützen

27.8.3 Deployment-Annotations für Metadata

metadata:
  name: webapp
  annotations:
    deployment.kubernetes.io/revision: "3"
    kubernetes.io/change-cause: "Update to nginx 1.20 with security fixes"
    app.company.com/version: "v2.1.0"
    app.company.com/owner: "team-frontend"
    app.company.com/cost-center: "engineering"
  labels:
    app: webapp
    tier: frontend
    environment: production
    version: v2.1.0

27.9 Erweiterte Konfigurationspatterns

27.9.1 Blue-Green Deployment Setup

# Blue Deployment (current)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-blue
  labels:
    app: webapp
    version: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
      version: blue

---
# Green Deployment (new)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-green
  labels:
    app: webapp
    version: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
      version: green

---
# Service (switch between blue/green)
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
spec:
  selector:
    app: webapp
    version: blue  # Switch to 'green' for cutover

27.9.2 Canary Deployment mit Traffic-Splitting

# Stable Deployment (90% Traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-stable
spec:
  replicas: 9  # 90% der gewünschten Kapazität

---
# Canary Deployment (10% Traffic)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-canary
spec:
  replicas: 1  # 10% der gewünschten Kapazität
  template:
    metadata:
      labels:
        version: canary
    spec:
      containers:
      - name: webapp
        image: webapp:v2.0.0  # Neue Version

27.10 Troubleshooting Deployment-Konfigurationen

27.10.1 Deployment-Status prüfen

# Deployment-Status anzeigen
oc get deployment webapp -o wide

# Rollout-Status verfolgen
oc rollout status deployment/webapp

# Deployment-Details inspizieren
oc describe deployment webapp

# Pod-Status und Events
oc get pods -l app=webapp
oc describe pod webapp-xyz

27.10.2 Häufige Konfigurationsprobleme

Image Pull-Fehler:

# Pod-Events prüfen
oc describe pod webapp-xyz | grep -A 10 Events

# Pull Secrets validieren
oc get secret private-registry -o yaml
oc get sa default -o yaml | grep imagePullSecrets

Resource-Probleme:

# Resource-Quotas prüfen
oc describe resourcequota

# Node-Kapazität prüfen
oc describe nodes | grep -A 5 "Allocated resources"

# Pod-Resource-Requests/-Limits validieren
oc get pods -o custom-columns=NAME:.metadata.name,CPU-REQ:.spec.containers[0].resources.requests.cpu,MEM-REQ:.spec.containers[0].resources.requests.memory

Probe-Probleme:

# Probe-Failures in Pod-Events suchen
oc describe pod webapp-xyz | grep -i probe

# Health-Endpoints manuell testen
oc port-forward pod/webapp-xyz 8080:8080
curl http://localhost:8080/health

27.10.3 Konfigurationsvalidierung

# YAML-Syntax validieren
oc apply --dry-run=client -f deployment.yaml

# Server-side Validation
oc apply --dry-run=server -f deployment.yaml

# Konfiguration gegen Policies prüfen
oc auth can-i create deployments --as=system:serviceaccount:myproject:webapp-sa