Veröffentlicht am

Kubernetes PriorityClass und Preemption konfigurieren

Teilen:
Authors

Kubernetes Priority und Preemption: Workload-Priorisierung in Production [2026]

TL;DR

  • PriorityClasses definieren, welche Pods bei Ressourcenknappheit ueberleben und welche verdraengt werden -- ein falsch gesetzter Wert kann ganze Namespaces lahmlegen.
  • Preemption entfernt automatisch niedrig-priorisierte Pods, um Platz fuer hoeher-priorisierte Pods zu schaffen -- das passiert nur, wenn keine Nodes mit freien Ressourcen existieren.
  • PreemptionPolicy: Never erlaubt hoehere Prioritaet beim Scheduling ohne aktive Verdraengung -- ideal fuer Batch-Workloads, die warten koennen.
  • System-kritische Pods (CoreDNS, kube-proxy, Monitoring) brauchen immer die hoechste PriorityClass, damit sie niemals verdraengt werden.
  • Ohne PriorityClasses behandelt Kubernetes alle Pods gleich -- bei Ressourcenknappheit entscheidet der Zufall, welche Pods sterben.

Warum Priority und Preemption unverzichtbar sind

In einem Cluster mit ausreichend Ressourcen spielt Prioritaet keine Rolle. Aber Production-Cluster sind selten leer. Sobald Nodes an ihre Kapazitaetsgrenze stossen, muss Kubernetes entscheiden: Welcher Pod bekommt die letzten Ressourcen? Und welcher Pod muss weichen?

Ohne PriorityClasses ist diese Entscheidung effektiv zufaellig. Ein unwichtiger Cronjob kann dafuer sorgen, dass ein kritischer Payment-Service keinen Platz findet. Priority und Preemption geben dem Cluster-Administrator die Kontrolle ueber diese Entscheidung.

PriorityClasses: Die Grundlagen

Eine PriorityClass ist ein cluster-weites Objekt, das einen numerischen Wert zwischen -2147483648 und 1000000000 definiert. Hoehere Werte bedeuten hoehere Prioritaet.

Standard-PriorityClasses definieren

Ein typisches Production-Setup braucht 4 bis 5 PriorityClasses:

# 1. System-kritisch (Cluster-Infrastruktur)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: system-cluster-critical
value: 2000001000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "Reserviert fuer kube-system Pods (CoreDNS, kube-proxy, CNI)"
---
# 2. Platform-kritisch (Monitoring, Logging, Ingress)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: platform-critical
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "Monitoring, Logging, Ingress Controller, Cert-Manager"
---
# 3. Production-Workloads (Business-kritische Services)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: production-high
value: 500000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "Kundenseitige Services, Payment, Auth"
---
# 4. Standard (Default fuer alle Deployments)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: production-standard
value: 100000
globalDefault: true
preemptionPolicy: PreemptLowerPriority
description: "Standard-Prioritaet fuer alle Workloads ohne explizite Zuweisung"
---
# 5. Batch und Development (niedrig, verdraengbar)
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: batch-low
value: 10000
globalDefault: false
preemptionPolicy: Never
description: "Batch-Jobs, Cronjobs, Dev-Workloads -- werden nie preempten, warten stattdessen"

PriorityClass einem Deployment zuweisen

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-service
  template:
    metadata:
      labels:
        app: payment-service
    spec:
      priorityClassName: production-high
      containers:
        - name: payment
          image: registry.example.com/payment-service:v4.1.0
          resources:
            requests:
              cpu: 500m
              memory: 512Mi
            limits:
              cpu: "1"
              memory: 1Gi
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5

Fuer die korrekte Konfiguration von Liveness und Readiness Probes lesen Sie unseren ausfuehrlichen Artikel Kubernetes Health Checks: Liveness, Readiness und Startup Probes.

Wie Preemption funktioniert

Wenn ein hoch-priorisierter Pod nicht gescheduled werden kann, weil alle Nodes voll sind, prueft der Scheduler:

  1. Gibt es einen Node, auf dem das Entfernen von niedrig-priorisierten Pods genug Platz schafft?
  2. Wenn ja: Die niedrig-priorisierten Pods erhalten ein graceful termination Signal.
  3. Der neue Pod wird auf den Node gescheduled, sobald die alten Pods beendet sind.

Was Preemption NICHT tut

  • Preemption toetet keine Pods mit gleicher oder hoeherer Prioritaet
  • Preemption ignoriert PodDisruptionBudgets nicht -- wenn ein PDB die Eviction verhindert, wird der Node uebersprungen
  • Preemption ist kein Sofort-Kill: Pods erhalten ihre terminationGracePeriodSeconds

Mehr zur Absicherung durch PodDisruptionBudgets erfahren Sie in Kubernetes Pod Disruption Budget.

PreemptionPolicy: Never -- Prioritaet ohne Verdraengung

Nicht jeder hoch-priorisierte Pod sollte andere verdraengen duerfen. Batch-Jobs haben oft eine niedrigere Prioritaet, sollen aber trotzdem vor Dev-Workloads gescheduled werden -- ohne aktiv Pods zu killen.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: batch-priority
value: 50000
globalDefault: false
preemptionPolicy: Never
description: "Batch-Jobs: hoehere Prioritaet als Dev, aber keine Preemption"

Mit PreemptionPolicy: Never wird der Pod in die Scheduling-Queue priorisiert, verdraengt aber niemanden. Der Pod wartet, bis genuegend Ressourcen frei werden -- entweder durch natuerliche Pod-Beendigung oder durch den Cluster Autoscaler.

Resource Contention: Wenn der Cluster voll ist

Priority und Preemption loesen das Problem der Scheduling-Reihenfolge. Aber was passiert, wenn der gesamte Cluster dauerhaft unter Ressourcendruck steht?

Kombination mit ResourceQuotas

ResourceQuotas begrenzen den Verbrauch pro Namespace und verhindern, dass ein Team den gesamten Cluster belegt:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    requests.cpu: "40"
    requests.memory: 80Gi
    limits.cpu: "80"
    limits.memory: 160Gi
    pods: "200"
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: batch-quota
  namespace: batch-processing
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.cpu: "40"
    limits.memory: 80Gi
    pods: "500"
  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values:
          - batch-low

ResourceQuota mit PriorityClass-Scope

ResourceQuotas koennen auf bestimmte PriorityClasses eingeschraenkt werden. Das verhindert, dass Teams ihre Workloads kuenstlich hoch priorisieren:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: high-priority-quota
  namespace: production
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values:
          - production-high

Integration mit Taints und Tolerations

PriorityClasses bestimmen die Scheduling-Reihenfolge. Taints und Tolerations bestimmen, welche Pods auf welchen Nodes laufen duerfen. Beide Mechanismen ergaenzen sich:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monitoring-agent
  namespace: monitoring
spec:
  replicas: 3
  selector:
    matchLabels:
      app: monitoring-agent
  template:
    metadata:
      labels:
        app: monitoring-agent
    spec:
      priorityClassName: platform-critical
      tolerations:
        - key: dedicated
          operator: Equal
          value: monitoring
          effect: NoSchedule
      nodeSelector:
        node-role: monitoring
      containers:
        - name: prometheus
          image: prom/prometheus:v2.53.0
          resources:
            requests:
              cpu: "1"
              memory: 2Gi
            limits:
              cpu: "2"
              memory: 4Gi

Fuer eine vertiefte Anleitung zu Taints und Tolerations lesen Sie Kubernetes Taints und Tolerations.

Anti-Patterns und haeufige Fehler

Anti-Pattern 1: Alle Pods auf hoechste Prioritaet setzen

Wenn alle Pods dieselbe hohe Prioritaet haben, ist die Prioritaet wertlos. Preemption kann nicht greifen, und bei Ressourcenknappheit entscheidet wieder der Zufall.

Loesung: Maximal 10-15% der Pods sollten die hoechste PriorityClass haben. Nutzen Sie globalDefault: true auf einer mittleren PriorityClass.

Anti-Pattern 2: Keine PriorityClass fuer System-Pods

Ohne explizite PriorityClass fuer kube-system Pods koennen CoreDNS und kube-proxy von Workload-Pods verdraengt werden. Das fuehrt zu Cluster-weiten DNS-Ausfaellen.

Loesung: Alle Pods in kube-system explizit mit system-cluster-critical oder system-node-critical konfigurieren.

Anti-Pattern 3: Preemption ohne Monitoring

Preemption-Events sind unsichtbar, wenn sie nicht aktiv ueberwacht werden. Teams bemerken erst Stunden spaeter, dass ihre Pods verdraengt wurden.

Loesung: Alerts auf Preemption-Events einrichten:

# PrometheusRule fuer Preemption-Monitoring
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: preemption-alerts
  namespace: monitoring
spec:
  groups:
    - name: preemption
      rules:
        - alert: PodPreempted
          expr: |
            increase(kube_pod_status_reason{reason="Preempting"}[5m]) > 0
          for: 0m
          labels:
            severity: warning
          annotations:
            summary: "Pod in {{ $labels.namespace }} wurde durch Preemption verdraengt"

        - alert: HighPreemptionRate
          expr: |
            sum(increase(kube_pod_status_reason{reason="Preempting"}[1h])) > 10
          for: 5m
          labels:
            severity: critical
          annotations:
            summary: "Mehr als 10 Preemption-Events in der letzten Stunde -- moeglicherweise Cluster-Ressourcen zu knapp"

Mehr zum Thema Performance-Monitoring und Alerting finden Sie in Kubernetes Performance Probleme identifizieren und loesen.

Best Practices fuer Production

Naming-Konvention fuer PriorityClasses

PriorityClassWertVerwendung
system-cluster-critical2000001000kube-system Pods
system-node-critical2000000000DaemonSets (kube-proxy, CNI)
platform-critical1000000Monitoring, Ingress, Cert-Manager
production-high500000Kundenseitige, business-kritische Services
production-standard100000Standard fuer alle Workloads (globalDefault)
batch-low10000Batch-Jobs, Cronjobs, Dev-Workloads

Deployment-Checkliste

  1. PriorityClasses cluster-weit definieren (einmalig)
  2. globalDefault: true auf genau einer PriorityClass setzen
  3. System-Pods in kube-system explizit konfigurieren
  4. ResourceQuotas pro Namespace UND pro PriorityClass setzen
  5. Preemption-Monitoring und Alerting einrichten
  6. Regelmaessig pruefen: Sind die richtigen Pods in der richtigen PriorityClass?

Verwandte Artikel

Fazit

PriorityClasses und Preemption sind die Grundlage fuer ein stabiles Production-Cluster. Ohne sie entscheidet der Zufall, welche Pods bei Ressourcenknappheit ueberleben. Mit einer klaren Hierarchie aus 4-5 PriorityClasses, ResourceQuotas pro Namespace und aktivem Preemption-Monitoring behalten DevOps-Teams die Kontrolle ueber ihr Cluster -- auch unter Last.

Der sicherste Einstieg: Eine production-standard PriorityClass als globalDefault setzen, platform-critical fuer Infrastruktur-Pods, und production-high nur fuer die wirklich business-kritischen Services. Batch-Workloads auf batch-low mit PreemptionPolicy: Never, damit sie niemanden verdraengen.

Falls Sie Unterstuetzung bei der Priorisierungs-Strategie fuer Ihre Kubernetes-Umgebung brauchen, stehen wir unter /kontakt fuer ein Beratungsgespraech zur Verfuegung.

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