- Authors

- Name
- Phillip Pham
- @ddppham
TL;DR
Kubernetes bietet mehrere Mechanismen für gezieltes Pod-Scheduling: nodeSelector für einfache Label-basierte Platzierung, Node Affinity für flexible Regeln mit Required/Preferred-Gewichtung, Pod Affinity/AntiAffinity für Co-Location und Spreading, sowie Taints und Tolerations zum Ausschließen von Workloads auf bestimmten Nodes. Kombiniert ermöglichen sie präzise Kontrolle über die Pod-Verteilung im Cluster.
Scheduling-Grundlagen: nodeSelector
Der einfachste Weg, Pods auf bestimmte Nodes zu lenken, ist nodeSelector. Zuerst labeln Sie Ihren Node, dann referenzieren Sie das Label im Pod-Spec.
# Node mit Label versehen
kubectl label nodes worker-gpu-01 gpu=nvidia-a100
# Labels prüfen
kubectl get nodes --show-labels | grep gpu
apiVersion: v1
kind: Pod
metadata:
name: ml-training
spec:
nodeSelector:
gpu: nvidia-a100
containers:
- name: training
image: pytorch/pytorch:2.1.0
resources:
limits:
nvidia.com/gpu: 1
nodeSelector ist simpel, aber unflexibel. Es gibt nur Hard-Requirements - der Pod bleibt Pending, wenn kein passender Node existiert.
Node Affinity: Flexible Platzierungsregeln
Node Affinity erweitert nodeSelector um zwei Modi:
| Typ | Verhalten | Einsatz |
|---|---|---|
requiredDuringSchedulingIgnoredDuringExecution | Hard-Constraint, Pod wird nur auf passende Nodes geschedulet | GPU-Workloads, Compliance |
preferredDuringSchedulingIgnoredDuringExecution | Soft-Constraint mit Gewichtung, Scheduler bevorzugt passende Nodes | Performance-Optimierung |
Required: GPU-Workloads auf dedizierte Nodes
apiVersion: apps/v1
kind: Deployment
metadata:
name: inference-server
spec:
replicas: 3
selector:
matchLabels:
app: inference
template:
metadata:
labels:
app: inference
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- gpu
- key: gpu-model
operator: In
values:
- a100
- h100
containers:
- name: inference
image: my-registry/inference:v2
resources:
limits:
nvidia.com/gpu: 1
Mehrere matchExpressions innerhalb eines nodeSelectorTerms werden mit AND verknüpft. Mehrere nodeSelectorTerms untereinander mit OR.
Preferred: Bevorzugt in bestimmter Zone
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- eu-central-1a
- weight: 20
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- eu-central-1b
Der weight-Wert (1-100) beeinflusst die Scheduler-Bewertung. Höhere Gewichtung bedeutet stärkere Präferenz, aber keine Garantie.
Pod Affinity und AntiAffinity
Während Node Affinity Pods relativ zu Nodes platziert, steuert Pod Affinity die Platzierung relativ zu anderen Pods.
Co-Location: Cache neben der Anwendung
Redis-Cache soll auf demselben Node wie die Anwendung laufen, um Netzwerk-Latenz zu minimieren:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
replicas: 3
selector:
matchLabels:
app: redis-cache
template:
metadata:
labels:
app: redis-cache
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-frontend
topologyKey: kubernetes.io/hostname
containers:
- name: redis
image: redis:7-alpine
resources:
requests:
cpu: 100m
memory: 128Mi
Der topologyKey bestimmt die Granularität: kubernetes.io/hostname bedeutet gleicher Node, topology.kubernetes.io/zone bedeutet gleiche Availability Zone.
AntiAffinity: Pods über Zonen verteilen
Für Hochverfügbarkeit sollen Replicas auf verschiedenen Nodes in verschiedenen Zonen laufen:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
spec:
replicas: 3
selector:
matchLabels:
app: web-frontend
template:
metadata:
labels:
app: web-frontend
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-frontend
topologyKey: topology.kubernetes.io/zone
containers:
- name: web
image: nginx:1.27
Tipp: Verwenden Sie preferred statt required für AntiAffinity bei Zone-Spreading. Bei required bleibt der Pod Pending, wenn alle Zonen bereits einen Pod haben.
Taints und Tolerations
Taints funktionieren umgekehrt zu Affinity: Statt Pods anzuziehen, stoßen Nodes Pods ab. Nur Pods mit passender Toleration werden auf einen Tainted Node geschedulet.
Taint-Effekte
| Effekt | Verhalten |
|---|---|
NoSchedule | Neue Pods ohne Toleration werden nicht geschedulet |
PreferNoSchedule | Scheduler vermeidet den Node, nutzt ihn aber als Fallback |
NoExecute | Bestehende Pods ohne Toleration werden evicted |
Praxis: GPU-Nodes exklusiv für ML-Workloads
# Taint setzen - nur ML-Pods dürfen auf GPU-Nodes
kubectl taint nodes worker-gpu-01 workload=gpu:NoSchedule
kubectl taint nodes worker-gpu-02 workload=gpu:NoSchedule
# Taint entfernen (mit Minus am Ende)
kubectl taint nodes worker-gpu-01 workload=gpu:NoSchedule-
Die passende Toleration im Pod-Spec:
apiVersion: v1
kind: Pod
metadata:
name: ml-job
spec:
tolerations:
- key: workload
operator: Equal
value: gpu
effect: NoSchedule
nodeSelector:
gpu: nvidia-a100
containers:
- name: training
image: pytorch/pytorch:2.1.0
Wichtig: Eine Toleration allein platziert den Pod nicht auf dem Tainted Node - sie erlaubt es nur. Kombinieren Sie Tolerations mit Node Affinity oder nodeSelector für gezielte Platzierung.
Kombiniertes Beispiel: Dedizierte Monitoring-Nodes
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
tolerations:
- operator: Exists
containers:
- name: exporter
image: prom/node-exporter:v1.8.0
operator: Exists ohne key toleriert alle Taints. Das ist typisch für DaemonSets wie Node-Exporter, die auf jedem Node laufen müssen.
Debugging: Scheduling-Probleme lösen
Wenn ein Pod im Status Pending bleibt:
# Events prüfen - zeigt Scheduling-Fehler
kubectl describe pod <pod-name> | grep -A 5 Events
# Typische Meldungen:
# "0/5 nodes are available: 2 node(s) had taint {workload: gpu}"
# "0/5 nodes are available: 5 node(s) didn't match Pod's node affinity"
# Node-Taints anzeigen
kubectl get nodes -o custom-columns=\
NAME:.metadata.name,TAINTS:.spec.taints
# Verfügbare Labels prüfen
kubectl get nodes --show-labels
FAQ
Was ist der Unterschied zwischen nodeSelector und Node Affinity?
nodeSelector unterstützt nur exakte Label-Matches. Node Affinity bietet Operatoren wie In, NotIn, Exists, Gt, Lt und unterscheidet zwischen Hard- und Soft-Constraints.
Kann ein Pod mehrere Tolerations haben?
Ja, ein Pod kann beliebig viele Tolerations definieren. Jede Toleration wird unabhängig gegen die Taints eines Nodes geprüft. Der Pod wird nur geschedulet, wenn alle Taints des Nodes toleriert werden.
Wann sollte ich PreferNoSchedule statt NoSchedule verwenden?
PreferNoSchedule eignet sich, wenn der Node als Fallback dienen soll - etwa für Burst-Workloads wenn dedizierte Nodes ausgelastet sind. NoSchedule für strikte Isolation wie GPU- oder Compliance-Nodes.
Wie verteile ich Pods gleichmäßig über Availability Zones?
Nutzen Sie podAntiAffinity mit topologyKey: topology.kubernetes.io/zone als Preferred-Regel. Ab Kubernetes 1.19 bieten Topology Spread Constraints noch feinere Kontrolle mit maxSkew.
Kubernetes ohne DevOps-Overhead?
Wir betreiben Ihre Kubernetes-Cluster 24/7 – Sie fokussieren auf Ihr Kerngeschäft. Ab 4.000€/Monat, DSGVO-konform, mit deutschem Support.
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
Kubernetes Taints und Tolerations: Workloads verteilen
Taints und Tolerations in Kubernetes: Nodes für bestimmte Workloads reservieren, GPU-Isolation umsetzen und Wartungsfenster sicher planen.
Taints und Tolerations erklärt: NoSchedule und NoExecute
Taints und Tolerations in Kubernetes verstehen: NoSchedule, PreferNoSchedule und NoExecute mit Praxis-Beispielen für GPU- und Infra-Node-Isolation.
CKA Scheduling: Node Affinity, Taints und Resources
Kubernetes Scheduling für die CKA-Prüfung meistern: Node Affinity, Taints, Tolerations, Resource Requests und Limits mit praktischen YAML-Beispielen.
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.
Kubernetes Datensouveränität: Node Affinity für DSGVO
Datensouveränität auf Kubernetes sicherstellen mit Node Affinity, Kyverno-Policies und EU-Cloud-Regionen für DSGVO-konforme Datenverarbeitung.