Veröffentlicht am

PodDisruptionBudget richtig konfigurieren

Teilen:
Authors

Kubernetes PodDisruptionBudget richtig setzen

Node-Upgrades, Cluster-Autoscaler, Spot-Instance-Evictions -- es gibt viele Gruende, warum Kubernetes Pods verschieben muss. Ohne PodDisruptionBudget (PDB) kann Kubernetes dabei alle Pods eines Services gleichzeitig beenden. Das Ergebnis: Downtime. Ein PDB verhindert das, indem es eine Mindest-Verfuegbarkeit definiert.

TL;DR

  • Ein PDB schuetzt Pods vor freiwilligen Unterbrechungen (Drain, Cluster-Autoscaler, Upgrades). Gegen Crashes oder OOMKills hilft es nicht.
  • minAvailable definiert die Mindestanzahl laufender Pods. maxUnavailable definiert die maximale Anzahl gleichzeitig nicht verfuegbarer Pods.
  • Fuer die meisten Services: maxUnavailable: 1. Das erlaubt Wartung und garantiert Verfuegbarkeit.
  • Ein PDB mit minAvailable: 100% blockiert Drain-Operationen komplett. Das ist fast immer ein Fehler.

Was ist eine freiwillige Unterbrechung?

Bevor Sie ein PDB erstellen, muessen Sie den Unterschied kennen:

# Aktuelle PDBs im Cluster anzeigen
kubectl get pdb -A

# Details eines PDB
kubectl describe pdb web-app-pdb -n production

Kubernetes unterscheidet zwei Arten von Unterbrechungen:

Freiwillig (voluntary) -- durch einen Administrator oder Controller ausgeloest:

  • kubectl drain (Node-Wartung)
  • Cluster-Autoscaler skaliert Nodes herunter
  • Spot/Preemptible Instance wird zurueckgefordert
  • Pod wird durch Upgrade verschoben

Unfreiwillig (involuntary) -- durch Hardware oder Software-Fehler:

  • Node faellt aus
  • Container crasht (OOMKill, Anwendungsfehler)
  • Netzwerkfehler

Ein PDB schuetzt nur vor freiwilligen Unterbrechungen. Gegen unfreiwillige Unterbrechungen brauchen Sie Replicas, Health Checks und Pod Anti-Affinity.

PDB erstellen: minAvailable vs maxUnavailable

Es gibt zwei Optionen -- verwenden Sie nie beide gleichzeitig.

maxUnavailable: Die pragmatische Wahl

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-app-pdb
  namespace: production
spec:
  maxUnavailable: 1              # Maximal 1 Pod darf gleichzeitig fehlen
  selector:
    matchLabels:
      app: web-app

Bei 5 Replicas bedeutet maxUnavailable: 1: Kubernetes darf maximal 1 Pod gleichzeitig evicten. Es muessen immer mindestens 4 Pods laufen, bevor der naechste beendet wird.

minAvailable: Die explizite Garantie

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: database-pdb
  namespace: production
spec:
  minAvailable: 2                # Mindestens 2 Pods muessen immer laufen
  selector:
    matchLabels:
      app: database

Prozentuale Werte

Beide Felder akzeptieren auch Prozentwerte:

spec:
  maxUnavailable: "25%"          # Max 25% der Pods duerfen fehlen

Bei 8 Replicas und maxUnavailable: "25%" duerfen maximal 2 Pods gleichzeitig fehlen (25% von 8 = 2, abgerundet).

Welches Feld waehlen?

SzenarioEmpfehlungGrund
Stateless Service, 3+ ReplicasmaxUnavailable: 1Einfach, erlaubt Wartung
Datenbank-Cluster (3 Nodes)minAvailable: 2Quorum-Schutz
Batch JobKein PDBUnterbrechung ist akzeptabel
Single-Replica ServicemaxUnavailable: 0 nur temporaerBlockiert sonst alle Drains

maxUnavailable ist in den meisten Faellen die bessere Wahl, weil es sich automatisch an die Anzahl der Replicas anpasst. minAvailable ist sinnvoll, wenn Sie eine absolute Mindestanzahl garantieren muessen (z.B. Quorum bei verteilten Datenbanken).

PDB und kubectl drain

So funktioniert das Zusammenspiel in der Praxis. Angenommen, Sie haben 3 Replicas von web-app mit maxUnavailable: 1:

# Node fuer Wartung drainieren
kubectl drain node-02 --ignore-daemonsets --delete-emptydir-data

Was passiert Schritt fuer Schritt:

  1. Kubernetes prueft die PDBs aller Pods auf node-02
  2. web-app hat 3 Replicas, PDB erlaubt maxUnavailable: 1
  3. Kubernetes evicted 1 Pod von node-02
  4. Der Scheduler startet den Pod auf einem anderen Node
  5. Sobald der neue Pod Ready ist, evicted Kubernetes den naechsten Pod
  6. Das wiederholt sich, bis alle Pods von node-02 verschoben sind

Wenn das PDB nicht eingehalten werden kann (z.B. weil ein anderer Pod schon nicht verfuegbar ist), wartet der Drain:

evicting pod production/web-app-7d4f5c8b9-abc12
error when evicting pods/"web-app-7d4f5c8b9-abc12" -n "production" (will retry after 5s):
Cannot evict pod as it would violate the pod's disruption budget.

Der Drain blockiert, bis das PDB wieder eingehalten werden kann -- oder bis Sie mit --timeout abbrechen.

# Drain mit Timeout
kubectl drain node-02 --ignore-daemonsets --delete-emptydir-data --timeout=300s

PDB und Rolling Updates

Wichtig zu wissen: Rolling Updates eines Deployments sind keine freiwilligen Unterbrechungen im PDB-Sinne. Ein Deployment-Rollout wird durch maxSurge und maxUnavailable in der Deployment-Strategie gesteuert, nicht durch das PDB.

Das PDB greift aber, wenn der Cluster-Autoscaler waehrend eines Rollouts einen Node drainiert. In diesem Fall arbeiten beide Mechanismen zusammen:

# Deployment-Strategie steuert Rollouts
spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0        # Kein Pod fehlt waehrend des Rollouts

---
# PDB schuetzt bei Node-Drain waehrend des Rollouts
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-app-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: web-app

Typische Fehler

Fehler 1: minAvailable gleich Replicas

# FALSCH: Blockiert jeden Drain
spec:
  minAvailable: 3       # Bei 3 Replicas: kein Pod darf fehlen

Das blockiert kubectl drain, Cluster-Autoscaler und Node-Upgrades komplett. In der Praxis fuehrt das dazu, dass Ops-Teams PDBs irgendwann loeschen, weil sie die Arbeit blockieren.

Fehler 2: PDB ohne passenden Selector

# PDB selektiert "app: web" statt "app: web-app"
spec:
  selector:
    matchLabels:
      app: web          # Trifft keine Pods!

Pruefen Sie, ob der PDB-Selector Pods matcht:

# Pods anzeigen, die der PDB selektiert
kubectl get pods -n production -l app=web-app

# PDB-Status pruefen
kubectl get pdb web-app-pdb -n production
# NAME           MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
# web-app-pdb    N/A             1                 2                     5d

Die Spalte ALLOWED DISRUPTIONS zeigt, wie viele Pods aktuell evicted werden duerfen. Bei 0 blockiert jeder Drain.

Fehler 3: PDB fuer Single-Replica Deployments

Ein PDB mit maxUnavailable: 0 oder minAvailable: 1 fuer ein Deployment mit 1 Replica blockiert ebenfalls jeden Drain. Wenn Sie nur 1 Replica haben, muessen Sie akzeptieren, dass es bei Wartung kurze Downtime gibt -- oder auf mindestens 2 Replicas skalieren.

Praxis-Setup fuer einen typischen Service

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
  namespace: production
spec:
  replicas: 4
  selector:
    matchLabels:
      app: api-service
  template:
    metadata:
      labels:
        app: api-service
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: kubernetes.io/hostname
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: api-service
      containers:
      - name: api
        image: api-service:5.3
        resources:
          requests:
            cpu: 250m
            memory: 256Mi
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-service-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: api-service

Die topologySpreadConstraints verteilen die Pods auf verschiedene Nodes. Zusammen mit dem PDB ergibt das: Pods sind verteilt, und bei einem Node-Drain faellt maximal 1 Pod gleichzeitig aus.

FAQ

Braucht jeder Service ein PDB?

Nicht jeder, aber jeder produktive Service mit mehr als 1 Replica sollte eins haben. Batch Jobs und kurzlebige Pods koennen darauf verzichten.

Was passiert, wenn ich kein PDB habe?

Kubernetes kann bei einem Drain alle Pods Ihres Services gleichzeitig evicten. Die Pods werden zwar auf anderen Nodes neu gestartet, aber in der Zwischenzeit ist der Service nicht verfuegbar.

Kann ich ein PDB nachtraeglich aendern?

Ja, PDBs koennen jederzeit mit kubectl apply aktualisiert werden. Die Aenderung greift sofort fuer zukuenftige Evictions.

Was ist der Unterschied zwischen PDB und Pod Anti-Affinity?

Pod Anti-Affinity steuert, wo Pods platziert werden (auf verschiedene Nodes verteilen). PDB steuert, wie viele Pods gleichzeitig beendet werden duerfen. Beides zusammen ergibt eine robuste Hochverfuegbarkeits-Konfiguration.

Greift ein PDB auch beim Loeschen eines Deployments?

Nein. Wenn Sie ein Deployment loeschen, werden alle Pods geloescht -- das PDB wird ignoriert. PDBs schuetzen nur vor Eviction-APIs (Drain, Autoscaler), nicht vor direktem Delete.


Naechster Schritt: Pruefen Sie mit kubectl get pdb -A, welche Services in Ihrem Cluster bereits ein PDB haben. Erstellen Sie PDBs fuer alle produktiven Services mit maxUnavailable: 1 als Startpunkt.


Weiterführende Artikel:

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