Veröffentlicht am

PodDisruptionBudgets: Verfügbarkeit bei Updates sichern

Teilen:
Authors

TL;DR

  • PodDisruptionBudgets (PDBs) begrenzen, wie viele Pods einer Anwendung gleichzeitig durch freiwillige Disruptions offline gehen dürfen
  • minAvailable garantiert eine Mindestanzahl laufender Pods, maxUnavailable erlaubt eine maximale Anzahl gleichzeitig nicht verfügbarer Pods
  • PDBs schützen bei kubectl drain, Cluster Autoscaler Scale-Down und Rolling Updates - nicht bei Node-Ausfällen
  • Falsch konfigurierte PDBs blockieren Node-Drains und verhindern Cluster-Upgrades
  • Für jedes produktive Deployment mit mehr als einem Replica sollte ein PDB existieren

PodDisruptionBudgets verstehen und einsetzen

Kubernetes unterscheidet zwischen freiwilligen und unfreiwilligen Disruptions. Unfreiwillig sind Hardware-Ausfälle oder Kernel-Panics. Freiwillig sind geplante Wartungen wie Node-Drains, Cluster-Upgrades oder Autoscaler-Entscheidungen. PodDisruptionBudgets kontrollieren ausschließlich freiwillige Disruptions.

Freiwillige Disruptions          Unfreiwillige Disruptions
(PDB schützt)                    (PDB schützt NICHT)
─────────────────                ─────────────────────────
kubectl drain                    Node-Hardware-Ausfall
Cluster Autoscaler Scale-Down    OOM Kill durch Kernel
Node-OS-Upgrade                  VM-Absturz (Cloud-Provider)
Deployment Rolling Update        Netzwerk-Partition
Pod-Eviction (Preemption)        Storage-Ausfall

Ohne PDB kann kubectl drain alle Pods einer Anwendung gleichzeitig terminieren. Bei einem Deployment mit drei Replicas heißt das: kurzzeitig null verfügbare Instanzen.

minAvailable vs. maxUnavailable

PDBs kennen zwei sich gegenseitig ausschließende Parameter.

minAvailable: Minimum garantieren

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: backend-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: backend

Bei einem Deployment mit 3 Replicas und minAvailable: 2 darf Kubernetes maximal 1 Pod gleichzeitig entfernen. Solange weniger als 2 Pods laufen, blockiert der PDB weitere Evictions.

maxUnavailable: Toleranz definieren

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: worker-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: worker

maxUnavailable: 1 erlaubt, dass höchstens 1 Pod gleichzeitig nicht verfügbar ist. Das Ergebnis ist bei 3 Replicas identisch zu minAvailable: 2, reagiert aber flexibler auf Skalierung.

Prozentuale Angaben

Beide Parameter akzeptieren auch Prozentwerte:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  maxUnavailable: "25%"
  selector:
    matchLabels:
      app: api-gateway

Bei 8 Replicas bedeutet maxUnavailable: "25%" = maximal 2 Pods gleichzeitig offline. Kubernetes rundet bei Prozenten immer ab (bei minAvailable) bzw. auf (bei maxUnavailable).

ReplicasmaxUnavailable: 25%minAvailable: 75%
4max 1 offlinemin 3 online
8max 2 offlinemin 6 online
10max 3 offlinemin 8 online
1max 1 offlinemin 1 online

Empfehlung: maxUnavailable ist in den meisten Fällen die bessere Wahl. Es skaliert automatisch mit der Replica-Anzahl und blockiert weniger wahrscheinlich Cluster-Operationen.


PDB mit Deployments und StatefulSets

Deployment-Beispiel: Web-API

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: production
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      # Anti-Affinity: Pods auf verschiedene Nodes verteilen
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: api
                topologyKey: kubernetes.io/hostname
      containers:
        - name: api
          image: registry.company.de/api:3.2.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: api

Die Kombination aus Pod Anti-Affinity und PDB stellt sicher: Pods laufen auf verschiedenen Nodes, und beim Drain eines Nodes geht maximal 1 Pod offline.

StatefulSet-Beispiel: Datenbank-Cluster

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  namespace: production
spec:
  replicas: 3
  serviceName: postgres
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          ports:
            - containerPort: 5432
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: postgres-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: postgres

Bei StatefulSets ist minAvailable oft sinnvoller. Ein PostgreSQL-Cluster mit 3 Nodes braucht mindestens 2 für Quorum. Der PDB verhindert, dass ein Drain zwei Datenbank-Pods gleichzeitig entfernt.

Zusammenspiel mit kubectl drain

kubectl drain respektiert PDBs und wartet, bis Evictions erlaubt sind:

# Node für Wartung vorbereiten
kubectl drain node-3 --ignore-daemonsets --delete-emptydir-data

# Output bei PDB-Blockade:
# evicting pod production/api-7d8f9b6c4-x2k9p
# error when evicting pods "api-7d8f9b6c4-x2k9p" (will retry):
# Cannot evict pod as it would violate the pod's disruption budget.

# Timeout setzen (verhindert ewiges Warten)
kubectl drain node-3 \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --timeout=300s

# PDB-Status prüfen
kubectl get pdb -n production
# NAME          MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
# api-pdb       N/A             1                 1                     30d
# postgres-pdb  2               N/A               1                     30d

Die Spalte ALLOWED DISRUPTIONS zeigt, wie viele Pods aktuell entfernt werden dürfen. Steht dort 0, blockiert der PDB jede Eviction.

Cluster Autoscaler und PDBs

Der Cluster Autoscaler prüft PDBs, bevor er einen Node herunterskaliert. Wenn ein Scale-Down einen PDB verletzen würde, bleibt der Node aktiv.

Typisches Szenario: Nachts sinkt der Traffic, der Autoscaler will Nodes abbauen. Auf Node-5 laufen 2 von 3 API-Pods. Der PDB erlaubt nur 1 gleichzeitig offline. Der Autoscaler kann Node-5 nur herunterfahren, wenn er die Pods vorher erfolgreich auf andere Nodes verschiebt.

# Autoscaler-Entscheidungen nachvollziehen
kubectl -n kube-system logs -l app=cluster-autoscaler \
  --tail=50 | grep -i "pdb"

# Typische Log-Meldung bei Blockade:
# Pod production/api-xxx can't be moved: violates PDB

Typische Fallstricke

1. PDB blockiert Cluster-Upgrade

Der häufigste Fehler: minAvailable gleich der Replica-Anzahl.

# FALSCH: Blockiert jeden Drain
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: broken-pdb
spec:
  minAvailable: 3  # Bei 3 Replicas = 0 Disruptions erlaubt
  selector:
    matchLabels:
      app: backend

Dieses PDB erlaubt null Disruptions. Kein Node kann gedraint werden, kein Cluster-Upgrade durchgeführt werden. Die Lösung: minAvailable immer mindestens 1 unter der Replica-Anzahl setzen oder maxUnavailable verwenden.

2. PDB auf Pods ohne Controller

Ein PDB auf einzelne Pods (ohne Deployment/StatefulSet) ist problematisch. Wird der Pod evicted, erstellt kein Controller einen neuen - der PDB blockiert danach alle weiteren Evictions dauerhaft.

3. Selector trifft keine Pods

# PDB-Status prüfen: 0 expected Pods = Selector falsch
kubectl get pdb api-pdb -n production -o yaml | grep -A5 status
# status:
#   currentHealthy: 0
#   desiredHealthy: 0
#   expectedPods: 0       # <-- Selector matcht nichts
#   disruptionsAllowed: 0

Der Selector im PDB muss exakt die Labels der Pod-Template-Spec treffen, nicht die Labels des Deployments.

4. Einzelnes Replica mit PDB

Bei replicas: 1 und minAvailable: 1 oder maxUnavailable: 0 ist kein Drain möglich. Für Single-Replica-Workloads entweder auf PDB verzichten oder maxUnavailable: 1 setzen (akzeptiert kurze Downtime).


PDB-Status überwachen

# Alle PDBs im Cluster anzeigen
kubectl get pdb -A

# Detaillierter Status
kubectl describe pdb api-pdb -n production

# PDBs mit 0 Allowed Disruptions finden (potenzielle Blocker)
kubectl get pdb -A -o json | \
  jq -r '.items[] | select(.status.disruptionsAllowed == 0) |
  "\(.metadata.namespace)/\(.metadata.name) - allowed: \(.status.disruptionsAllowed)"'

Ein Monitoring-Alert auf disruptionsAllowed == 0 über längere Zeit hilft, blockierende PDBs frühzeitig zu erkennen, bevor das nächste Cluster-Upgrade ansteht.

FAQ

Was passiert bei einem Node-Ausfall - schützt der PDB?

Nein. PDBs greifen nur bei freiwilligen Disruptions wie kubectl drain oder Cluster Autoscaler. Bei einem plötzlichen Node-Ausfall entfernt der Node Controller die Pods nach dem pod-eviction-timeout (Standard: 5 Minuten) ohne PDB-Prüfung.

Kann ich minAvailable und maxUnavailable gleichzeitig setzen?

Nein. Ein PDB akzeptiert genau einen der beiden Parameter. Wenn beide gesetzt sind, lehnt Kubernetes die Erstellung ab. Wähle den Parameter, der zum Anwendungsfall passt.

Wie interagiert ein PDB mit der RollingUpdate-Strategie eines Deployments?

Das Deployment respektiert den PDB bei Rolling Updates. Wenn der PDB maxUnavailable: 1 vorgibt und das Deployment maxUnavailable: 2, gilt der restriktivere Wert. In der Praxis sollten beide aufeinander abgestimmt sein.

Sollte jedes Deployment einen PDB haben?

Für produktive Workloads mit mehr als einem Replica: ja. Für Dev/Staging-Umgebungen oder Single-Replica-Deployments ist ein PDB oft unnötig und kann sogar Wartungsarbeiten blockieren.

Warum blockiert mein PDB den Node-Drain?

Häufigste Ursache: minAvailable ist gleich der aktuellen Replica-Anzahl oder Pods sind nicht healthy (reduziert currentHealthy). Prüfe mit kubectl get pdb -o yaml den Status und stelle sicher, dass disruptionsAllowed größer als 0 ist.

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

kubernetesdevops

Kubernetes Medizintechnik MDR 2026 Container-Compliance

Die EU-MDR stellt hohe Anforderungen an Medizintechnik-Software bis 2026. Dieser Artikel beleuchtet, wie Sie Ihre Kubernetes-Umgebung in Deutschland **MDR-konform** gestalten und Ihre **Container-Workflows** im **Healthcare**-Sektor sicher betreiben. Erfahren Sie die entscheidenden Strategien für **Infrastruktur-Qualifizierung**, **Software-Validierung** und umfassende **Kubernetes Compliance** in regulierten Umgebungen.

Weiterlesen →