Veröffentlicht am

Pod Disruption Budget: Wartung ohne Downtime

Teilen:
Authors

Pod Disruption Budgets: Kubernetes-Wartung ohne Downtime

TL;DR

  • Ein PDB definiert, wie viele Pods einer Anwendung bei freiwilligen Unterbrechungen (Node Drain, Cluster-Upgrade) mindestens laufen muessen.
  • Verwenden Sie minAvailable wenn Sie eine feste Mindestanzahl brauchen, maxUnavailable wenn Sie die gleichzeitige Ausfallrate begrenzen wollen.
  • PDBs schuetzen nur vor freiwilligen Disruptions -- nicht vor Hardwareausfaellen oder OOMKills.
  • Fuer StatefulSets ist maxUnavailable: 1 fast immer die richtige Wahl.
  • Ohne PDBs kann ein kubectl drain alle Pods Ihrer Anwendung gleichzeitig beenden.

Das Problem: Wartung killt Ihre Pods

Kubernetes muss regelmaessig Nodes warten: Betriebssystem-Updates, Kernel-Patches, Cluster-Version-Upgrades, Hardware-Tausch. Bei all diesen Operationen werden Pods von einem Node entfernt und auf anderen Nodes neu gestartet.

Ohne Schutzmechanismus passiert dabei folgendes: Kubernetes raeumt einen Node mit kubectl drain, und wenn zufaellig alle drei Replikas Ihrer Anwendung auf diesem Node laufen, sind alle gleichzeitig weg. Die neuen Pods starten zwar auf anderen Nodes, aber bis sie bereit sind (Image Pull, Startup, Readiness Probe), ist Ihr Dienst nicht erreichbar.

Ein Pod Disruption Budget verhindert genau das. Es sagt dem Kubernetes API-Server: "Von dieser Anwendung muessen immer mindestens N Pods laufen. Warte mit dem Eviction, bis die Bedingung wieder erfuellt ist."

PDB-Grundlagen: minAvailable vs. maxUnavailable

Es gibt zwei Wege, ein PDB zu konfigurieren. Sie koennen nicht beide gleichzeitig in einem PDB verwenden.

ParameterBedeutungBeispiel
minAvailableMindestanzahl (oder Prozent) der Pods, die jederzeit verfuegbar sein muessenminAvailable: 2 bei 3 Replikas = max. 1 Pod darf gleichzeitig ausfallen
maxUnavailableMaximale Anzahl (oder Prozent) der Pods, die gleichzeitig nicht verfuegbar sein duerfenmaxUnavailable: 1 = immer nur 1 Pod auf einmal weg

Beide Parameter akzeptieren absolute Zahlen oder Prozentwerte. Bei Prozentwerten rundet Kubernetes ab (bei minAvailable) bzw. auf (bei maxUnavailable).

Beispiel 1: PDB fuer ein stateless Deployment

Ein typischer Web-Service mit 4 Replikas. Wir wollen, dass bei Wartungsarbeiten immer mindestens 3 Pods laufen:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-frontend-pdb
  namespace: production
spec:
  minAvailable: 3
  selector:
    matchLabels:
      app: web-frontend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-frontend
  namespace: production
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web-frontend
  template:
    metadata:
      labels:
        app: web-frontend
    spec:
      containers:
      - name: web
        image: registry.example.com/web-frontend:2.1.0
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

Wenn jetzt ein Admin kubectl drain node-2 ausfuehrt und auf node-2 zwei Pods dieser Anwendung laufen, wird Kubernetes nur einen davon evicten. Erst wenn der evicted Pod auf einem anderen Node wieder ready ist, darf der zweite Pod entfernt werden.

Beispiel 2: PDB fuer ein StatefulSet

Fuer StatefulSets wie Datenbanken oder Message Queues ist maxUnavailable: 1 die Standard-Empfehlung. Hier am Beispiel eines Redis-Clusters:

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: redis-cluster-pdb
  namespace: data
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: redis-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  namespace: data
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:7-alpine
        ports:
        - containerPort: 6379
        resources:
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "1"
            memory: "2Gi"

Bei einem Cluster-Upgrade werden die Redis-Pods nacheinander verschoben -- nie mehr als einer gleichzeitig. Das gibt dem Redis-Cluster Zeit, Daten zu resynchronisieren, bevor der naechste Pod bewegt wird.

Beispiel 3: PDB mit Prozentwerten und kubectl-Befehle

Prozentwerte sind nuetzlich, wenn sich die Anzahl der Replikas dynamisch aendert (z.B. durch einen HPA):

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

Bei 8 Replikas duerfen maximal 2 Pods gleichzeitig ausfallen (25% von 8 = 2). Bei 4 Replikas nur 1 Pod (25% von 4 = 1, aufgerundet).

Nuetzliche Befehle zum Pruefen Ihrer PDBs:

# Alle PDBs im Cluster anzeigen
kubectl get pdb --all-namespaces

# Details eines PDBs anzeigen (inkl. erlaubte Disruptions)
kubectl get pdb web-frontend-pdb -n production -o yaml

# Wichtig: "disruptionsAllowed" zeigt, wie viele Pods aktuell evicted werden duerfen
kubectl get pdb -n production -o wide

# Dry-Run: Pruefen was passiert, bevor Sie tatsaechlich drainen
kubectl drain node-2 --dry-run=client --ignore-daemonsets --delete-emptydir-data

Wann greifen PDBs -- und wann nicht?

Das ist ein entscheidender Punkt, der oft missverstanden wird:

Disruption-TypPDB schuetzt?Beispiele
Freiwillig (voluntary)Jakubectl drain, Cluster-Upgrade, Cluster Autoscaler Scale-Down, Spot/Preemptible Node Eviction
Unfreiwillig (involuntary)NeinHardware-Ausfall, Kernel-Panic, Node-Netzwerkausfall, OOMKill durch den Kernel
AnwendungsfehlerNeinCrashLoopBackOff, fehlgeschlagene Liveness Probes

Fuer Schutz vor unfreiwilligen Ausfaellen brauchen Sie redundante Replikas in Kombination mit Pod Anti-Affinity, um sicherzustellen, dass Ihre Pods auf verschiedenen Nodes verteilt sind.

PDB + Rolling Updates: So spielen sie zusammen

PDBs interagieren mit der strategy Ihres Deployments. Ein Deployment mit maxUnavailable: 1 in der Rolling-Update-Strategie und einem PDB mit maxUnavailable: 1 koennen sich gegenseitig beeinflussen.

Die wichtigste Regel: PDBs gelten fuer Evictions durch den API-Server (z.B. bei kubectl drain). Rolling Updates werden vom Deployment Controller gesteuert und verwenden die maxUnavailable/maxSurge-Einstellungen der Update-Strategie, nicht das PDB.

Das bedeutet: Waehrend eines Rolling Updates kann ein Pod heruntergefahren werden, auch wenn das PDB eigentlich keine weitere Disruption erlauben wuerde. PDBs und Rolling-Update-Strategie sind zwei unabhaengige Mechanismen. Stellen Sie sicher, dass beide sinnvoll konfiguriert sind.

Typische Fehler

1. PDB blockiert Node Drain komplett

Wenn Sie minAvailable: 3 setzen und nur 3 Replikas haben, ist disruptionsAllowed: 0. Kein Pod darf jemals evicted werden. Ein kubectl drain haengt dann fuer immer (oder bis zum Timeout). Loesung: Entweder die Replikas erhoehen oder minAvailable reduzieren.

2. Selector stimmt nicht mit Pod-Labels ueberein

Das PDB referenziert Pods ueber den selector. Wenn die Labels nicht exakt uebereinstimmen, schuetzt das PDB nichts. Pruefen Sie mit:

# Welche Pods matcht das PDB?
kubectl get pods -n production -l app=web-frontend

# Stimmt die Anzahl mit dem PDB-Status ueberein?
kubectl get pdb web-frontend-pdb -n production

3. Kein PDB fuer kritische Services

Der haeufigste Fehler ist schlicht, kein PDB zu haben. Pruefen Sie systematisch, welche Deployments und StatefulSets in Ihrem Cluster kein PDB haben:

# Alle Deployments ohne PDB finden (vereinfachtes Skript)
for deploy in $(kubectl get deploy -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'); do
  ns=$(echo $deploy | cut -d/ -f1)
  name=$(echo $deploy | cut -d/ -f2)
  labels=$(kubectl get deploy $name -n $ns -o jsonpath='{.spec.selector.matchLabels}')
  echo "Checking $deploy with labels: $labels"
done

4. PDB bei Single-Replica Deployments

Ein PDB mit minAvailable: 1 bei einem Deployment mit replicas: 1 bedeutet: der einzige Pod darf nie evicted werden. Das blockiert jede Wartung. Fuer Single-Replica-Workloads brauchen Sie entweder mehr Replikas oder muessen das PDB weglassen und kurze Downtime akzeptieren.

Empfohlene Standardwerte

Workload-TypEmpfohlene ReplikasEmpfohlenes PDB
Stateless Web-Service3+maxUnavailable: 1
StatefulSet (DB, Queue)3+maxUnavailable: 1
Batch Job / CronJobvariabelKein PDB noetig
Singleton (z.B. Controller)1 (mit Leader Election)Kein PDB oder maxUnavailable: 1 mit 2+ Replikas
Latenz-kritischer Service4+minAvailable: 75%

PDB-Status interpretieren

Der Output von kubectl get pdb -o wide zeigt wichtige Felder:

NAME                MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
web-frontend-pdb    3               N/A               1                     7d
redis-cluster-pdb   N/A             1                 1                     7d
  • ALLOWED DISRUPTIONS: Wie viele Pods jetzt gerade evicted werden duerfen. Wenn dieser Wert 0 ist, blockiert das PDB jede Eviction.
  • Ueberwachen Sie diesen Wert in Ihrem Monitoring. Ein PDB mit dauerhaft 0 Allowed Disruptions deutet auf ein Problem hin (zu wenig Replikas, fehlende Kapazitaet).

Integration in CI/CD

PDBs gehoeren in dasselbe Repository wie Ihre Deployment-Manifeste. Behandeln Sie sie als Teil Ihres Application Stacks:

my-app/
  deployment.yaml
  service.yaml
  pdb.yaml              # Gehoert dazu
  hpa.yaml
  networkpolicy.yaml

Wenn Sie Helm verwenden, definieren Sie das PDB als Template mit konfigurierbaren Werten:

# values.yaml
pdb:
  enabled: true
  maxUnavailable: 1

So kann jedes Team die Werte fuer seine Services anpassen, und das PDB wird automatisch mit jedem Deployment ausgerollt.

Zusammenspiel mit Cluster Autoscaler

Der Cluster Autoscaler beruecksichtigt PDBs, wenn er Nodes herunterskalieren will. Ein Node wird nur entfernt, wenn alle Pods darauf unter Einhaltung ihrer PDBs evicted werden koennen. Wenn ein PDB die Eviction blockiert, bleibt der Node bestehen -- auch wenn er unterlastig ist.

Das kann zu unerwuenscht hohen Kosten fuehren: Nodes bleiben laufen, weil PDBs das Herunterskalieren verhindern. Stellen Sie sicher, dass Ihre PDB-Werte mit Ihrer Kapazitaetsplanung und dem Autoscaling-Setup zusammenpassen.

Weitergehende Ressourcen

  • Ergaenzend zu PDBs sollten Sie Rolling Updates korrekt konfigurieren, damit Deployments und PDBs nicht in Konflikt geraten.
  • Fuer die Verteilung von Pods auf verschiedene Nodes nutzen Sie Pod Affinity und Anti-Affinity in Kombination mit PDBs.
  • Ihr Monitoring-Stack sollte PDB-Metriken (z.B. ueber kube-state-metrics) erfassen und bei disruptionsAllowed: 0 einen Alert ausloesen.

Wenn Sie Hilfe bei der PDB-Konfiguration oder bei der Planung Ihrer Cluster-Wartungsstrategie brauchen, sprechen Sie uns an unter /kontakt.

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