- Authors

- Name
- Phillip Pham
- @ddppham
Kubernetes Pod Affinity und Anti-Affinity: Praxisleitfaden
TL;DR
- Pod Affinity platziert Pods bevorzugt zusammen auf denselben Nodes (z.B. App + Cache), um Netzwerk-Latenz zu reduzieren.
- Pod Anti-Affinity verteilt Pods gezielt auf verschiedene Nodes oder Zonen, um Hochverfuegbarkeit bei Node-Ausfaellen sicherzustellen.
- Der
topologyKeybestimmt die Granularitaet:kubernetes.io/hostnamefuer Node-Ebene,topology.kubernetes.io/zonefuer Availability Zones. - Starten Sie immer mit
preferredDuringSchedulingIgnoredDuringExecution, bevor Sie harte Regeln (required) einsetzen. - Falsche Labels oder zu restriktive Regeln fuehren zu Pods im
Pending-Status -- testen Sie Regeln immer in Staging.
Was ist Pod Affinity?
Pod Affinity und Anti-Affinity sind Scheduling-Regeln in Kubernetes, die steuern, auf welchen Nodes ein Pod relativ zu anderen Pods platziert wird. Im Gegensatz zu Node Affinity (die sich auf Node-Labels bezieht) referenzieren diese Regeln die Labels anderer Pods.
Das ist relevant, wenn Ihre Anwendungsarchitektur Abhaengigkeiten zwischen Services hat. Ein typisches Beispiel: Ihr API-Server und der zugehoerige Redis-Cache sollten auf demselben Node laufen, um Netzwerk-Roundtrips zu minimieren. Gleichzeitig wollen Sie sicherstellen, dass drei Replikas Ihres API-Servers auf drei verschiedenen Nodes laufen, damit ein Node-Ausfall nicht den gesamten Dienst betrifft.
Die zwei Regeltypen
Kubernetes unterscheidet zwei Varianten fuer beide Affinity-Typen:
| Variante | Verhalten | Empfohlener Einsatz |
|---|---|---|
requiredDuringSchedulingIgnoredDuringExecution | Pod wird nur geplant, wenn die Bedingung erfuellt ist. Sonst bleibt er im Pending-Status. | Strikte HA-Anforderungen, z.B. Datenbank-Replikas auf verschiedenen Nodes |
preferredDuringSchedulingIgnoredDuringExecution | Scheduler versucht die Regel zu erfuellen, plant den Pod aber auch ohne Erfuellung. | Latenz-Optimierung, Performance-Tuning, erste Testphase |
Die preferred-Variante hat zusaetzlich ein weight-Feld (1-100), mit dem Sie die Prioritaet gegenueber anderen Scheduling-Praeferenzen steuern koennen.
Praxisbeispiel 1: Co-Lokalisierung mit Pod Affinity
Hier wird sichergestellt, dass Frontend-Pods bevorzugt auf Nodes laufen, auf denen bereits ein Backend-Pod laeuft. Das reduziert die Netzwerk-Latenz zwischen den beiden Services.
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
podAffinityTerm:
labelSelector:
matchLabels:
app: backend
topologyKey: "kubernetes.io/hostname"
containers:
- name: frontend
image: registry.example.com/frontend:1.4.2
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
Wichtig: weight: 80 bedeutet, dass diese Praeferenz einen hohen Stellenwert hat, aber der Scheduler trotzdem Freiheit bei der Platzierung behaelt. Wenn kein Node einen Backend-Pod hat, wird der Frontend-Pod trotzdem geplant.
Praxisbeispiel 2: Hochverfuegbarkeit mit Anti-Affinity
Fuer Datenbank-Replikas oder andere stateful Workloads ist es kritisch, dass keine zwei Instanzen auf demselben Node landen. Ein Node-Ausfall wuerde sonst mehrere Replikas gleichzeitig betreffen.
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: postgres
topologyKey: "kubernetes.io/hostname"
containers:
- name: postgres
image: postgres:16-alpine
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "4Gi"
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
Hier wird required statt preferred verwendet. Das bedeutet: Wenn der Cluster nur zwei Nodes hat, bleibt das dritte Replika im Pending-Status, bis ein weiterer Node verfuegbar ist. Das ist beabsichtigt -- lieber ein Pod weniger als zwei Replikas auf demselben Node.
Praxisbeispiel 3: Zone-Level Anti-Affinity mit Terraform
Wenn Sie Ihre Infrastruktur mit Terraform verwalten, koennen Sie Node-Labels direkt beim Erstellen der Node-Pools setzen. Hier ein Beispiel fuer GKE:
resource "google_container_node_pool" "app_pool" {
name = "app-pool"
cluster = google_container_cluster.primary.name
location = "europe-west3"
node_config {
machine_type = "e2-standard-4"
labels = {
"team" = "platform"
"environment" = "production"
}
}
autoscaling {
min_node_count = 3
max_node_count = 10
}
}
Mit dem topologyKey: "topology.kubernetes.io/zone" in Ihrer Anti-Affinity-Regel verteilt Kubernetes die Pods dann ueber verschiedene Availability Zones. Das schuetzt vor Zone-weiten Ausfaellen, nicht nur vor einzelnen Node-Ausfaellen.
Der topologyKey im Detail
Der topologyKey ist der am haeufigsten missverstandene Parameter. Er referenziert ein Node-Label und definiert die "Topologie-Domaene":
| topologyKey | Granularitaet | Typischer Einsatz |
|---|---|---|
kubernetes.io/hostname | Einzelner Node | Anti-Affinity: Pods auf verschiedene Nodes verteilen |
topology.kubernetes.io/zone | Availability Zone | Anti-Affinity: Pods ueber Zonen verteilen |
topology.kubernetes.io/region | Region | Selten sinnvoll, da Cluster meist in einer Region laufen |
Custom Labels (z.B. rack) | Selbst definiert | On-Premise: Verteilung ueber physische Racks |
Ein haeufiger Fehler: Sie verwenden einen topologyKey, der auf Ihren Nodes gar nicht als Label existiert. Das fuehrt dazu, dass die Regel nicht greift oder Pods im Pending-Status haengen. Pruefen Sie die vorhandenen Labels mit:
kubectl get nodes --show-labels
# Gezielt nach Topology-Labels filtern
kubectl get nodes -o custom-columns=\
NAME:.metadata.name,\
ZONE:.metadata.labels.topology\\.kubernetes\\.io/zone,\
HOSTNAME:.metadata.labels.kubernetes\\.io/hostname
Affinity vs. Anti-Affinity: Wann was einsetzen?
| Szenario | Regeltyp | topologyKey | Variante |
|---|---|---|---|
| App + Cache auf demselben Node | Pod Affinity | kubernetes.io/hostname | preferred |
| DB-Replikas auf verschiedene Nodes | Pod Anti-Affinity | kubernetes.io/hostname | required |
| Stateless Pods ueber Zonen verteilen | Pod Anti-Affinity | topology.kubernetes.io/zone | preferred |
| GPU-Workloads auf spezielle Nodes | Node Affinity (nicht Pod Affinity) | -- | required |
| Frontend nahe am API-Gateway | Pod Affinity | kubernetes.io/hostname | preferred |
Haeufige Fehler und Debugging
1. Pods bleiben im Pending-Status
Die haeufigste Ursache: Eine required-Regel kann nicht erfuellt werden, weil es nicht genug Nodes gibt oder die Labels nicht stimmen. So finden Sie das Problem:
# Warum ist der Pod nicht geplant?
kubectl describe pod <pod-name> | grep -A 10 "Events"
# Welche Nodes sind verfuegbar und welche Labels haben sie?
kubectl get nodes --show-labels
# Welche Pods mit dem referenzierten Label laufen wo?
kubectl get pods -l app=backend -o wide
2. Labels stimmen nicht ueberein
Der labelSelector in der Affinity-Regel muss exakt mit den Labels der Ziel-Pods uebereinstimmen. Ein Tippfehler (z.B. app: Backend statt app: backend) fuehrt dazu, dass die Regel ins Leere laeuft.
3. Scheduler-Overhead bei grossen Clustern
In Clustern mit mehreren hundert Nodes und vielen Affinity-Regeln kann der Scheduler merklich langsamer werden. Kubernetes muss fuer jeden neuen Pod die Platzierung aller referenzierten Pods pruefen. Reduzieren Sie die Anzahl der required-Regeln und nutzen Sie preferred wo moeglich.
4. Konflikte mit Pod Disruption Budgets
Wenn Sie Anti-Affinity mit Pod Disruption Budgets kombinieren, kann es bei Wartungsarbeiten zu Blockaden kommen. Ein kubectl drain verschiebt Pods, aber die Anti-Affinity-Regel verhindert moeglicherweise die Neuplanung auf dem verbleibenden Node. Planen Sie genuegend Kapazitaet ein.
Zusammenspiel mit anderen Scheduling-Mechanismen
Pod Affinity ist ein Baustein in einem groesseren Scheduling-Toolkit. Hier eine Uebersicht, wie die verschiedenen Mechanismen zusammenspielen:
| Mechanismus | Steuert | Referenziert |
|---|---|---|
| Pod Affinity / Anti-Affinity | Pod-zu-Pod-Platzierung | Pod-Labels |
| Node Affinity | Pod-zu-Node-Platzierung | Node-Labels |
| Taints & Tolerations | Node-Exklusivitaet | Node-Taints |
| Topology Spread Constraints | Gleichmaessige Verteilung | Topology-Domains |
| Resource Requests/Limits | Ressourcen-basiertes Scheduling | Node-Kapazitaet |
Fuer fortgeschrittene Szenarien lohnt sich ein Blick auf Topology Spread Constraints (ab Kubernetes 1.19 stable). Sie bieten feinere Kontrolle ueber die Verteilung als Anti-Affinity, weil Sie ein maxSkew definieren koennen -- also wie ungleichmaessig die Verteilung maximal sein darf.
Empfohlene Vorgehensweise
Beginnen Sie mit Anti-Affinity fuer kritische Workloads. Verteilen Sie Datenbank-Replikas und wichtige API-Services auf verschiedene Nodes. Das bringt den groessten Stabilitaetsgewinn.
Nutzen Sie Affinity fuer latenz-sensitive Service-Paare. Wenn Profiling zeigt, dass Netzwerk-Latenz zwischen zwei Services ein Bottleneck ist, platzieren Sie sie mit
preferredAffinity zusammen.Testen Sie in Staging mit weniger Nodes als in Production. So entdecken Sie schnell, ob Ihre Regeln in Randfaellen (z.B. waehrend eines Rolling Updates) zu Scheduling-Problemen fuehren.
Kombinieren Sie mit dem Horizontal Pod Autoscaler und dem Cluster Autoscaler, damit neue Nodes automatisch bereitgestellt werden, wenn Anti-Affinity-Regeln mehr Kapazitaet erfordern.
Dokumentieren Sie Ihre Affinity-Regeln als Teil Ihrer Deployment-Dokumentation. In sechs Monaten werden Sie sich fragen, warum ein bestimmtes
requiredgesetzt wurde.
Weitergehende Ressourcen
- Wenn Sie gerade erst einen Production-Cluster aufsetzen, lesen Sie unseren Guide zur Kubernetes Cluster-Einrichtung fuer die Produktion.
- Fuer die richtige Dimensionierung Ihrer Nodes im Zusammenspiel mit Affinity-Regeln hilft der Artikel zu Kubernetes Capacity Planning.
- Ergaenzend zu Pod-Platzierung sollten Sie Ihre Network Policies pruefen, um auch auf Netzwerkebene Isolation und Performance sicherzustellen.
Wenn Sie Unterstuetzung bei der Konfiguration Ihrer Scheduling-Regeln brauchen oder eine Architektur-Review Ihres Clusters wuenschen, melden Sie sich gerne bei uns 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
Jobs und CronJobs: Batch-Workloads auf Kubernetes
Kubernetes Jobs und CronJobs für Batch-Verarbeitung einrichten: Job-Typen, Cron-Scheduling, Fehlerbehandlung und TTL-Cleanup mit praxisnahen YAML-Beispielen.
Prometheus Recording Rules für Kubernetes optimieren
Prometheus Recording Rules beschleunigen PromQL-Abfragen in Kubernetes. Konfiguration, Naming Conventions und praktische Beispiele.
Kubernetes Scheduling: Affinity, Taints und Tolerations
Kubernetes Scheduling mit Node Affinity, Taints und Tolerations steuern. Praktische Beispiele für GPU-Nodes, Zone-Spreading und Co-Location.
Java Kubernetes OOMKilled: JVM Heap richtig setzen
Java-Pods werden auf Kubernetes mit OOMKilled (Exit Code 137) beendet. So setzt ihr JVM Heap, MaxRAMPercentage und Container-Limits korrekt für stabile Java-Workloads.
Kubernetes Requests und Limits richtig setzen
CPU und Memory Requests und Limits korrekt konfigurieren: QoS-Klassen verstehen, typische Fehler vermeiden und die richtigen Werte finden.