Veröffentlicht am

Pod Affinity und Anti-Affinity: Latenz senken

Teilen:
Authors

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 topologyKey bestimmt die Granularitaet: kubernetes.io/hostname fuer Node-Ebene, topology.kubernetes.io/zone fuer 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:

VarianteVerhaltenEmpfohlener Einsatz
requiredDuringSchedulingIgnoredDuringExecutionPod wird nur geplant, wenn die Bedingung erfuellt ist. Sonst bleibt er im Pending-Status.Strikte HA-Anforderungen, z.B. Datenbank-Replikas auf verschiedenen Nodes
preferredDuringSchedulingIgnoredDuringExecutionScheduler 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":

topologyKeyGranularitaetTypischer Einsatz
kubernetes.io/hostnameEinzelner NodeAnti-Affinity: Pods auf verschiedene Nodes verteilen
topology.kubernetes.io/zoneAvailability ZoneAnti-Affinity: Pods ueber Zonen verteilen
topology.kubernetes.io/regionRegionSelten sinnvoll, da Cluster meist in einer Region laufen
Custom Labels (z.B. rack)Selbst definiertOn-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?

SzenarioRegeltyptopologyKeyVariante
App + Cache auf demselben NodePod Affinitykubernetes.io/hostnamepreferred
DB-Replikas auf verschiedene NodesPod Anti-Affinitykubernetes.io/hostnamerequired
Stateless Pods ueber Zonen verteilenPod Anti-Affinitytopology.kubernetes.io/zonepreferred
GPU-Workloads auf spezielle NodesNode Affinity (nicht Pod Affinity)--required
Frontend nahe am API-GatewayPod Affinitykubernetes.io/hostnamepreferred

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:

MechanismusSteuertReferenziert
Pod Affinity / Anti-AffinityPod-zu-Pod-PlatzierungPod-Labels
Node AffinityPod-zu-Node-PlatzierungNode-Labels
Taints & TolerationsNode-ExklusivitaetNode-Taints
Topology Spread ConstraintsGleichmaessige VerteilungTopology-Domains
Resource Requests/LimitsRessourcen-basiertes SchedulingNode-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

  1. Beginnen Sie mit Anti-Affinity fuer kritische Workloads. Verteilen Sie Datenbank-Replikas und wichtige API-Services auf verschiedene Nodes. Das bringt den groessten Stabilitaetsgewinn.

  2. Nutzen Sie Affinity fuer latenz-sensitive Service-Paare. Wenn Profiling zeigt, dass Netzwerk-Latenz zwischen zwei Services ein Bottleneck ist, platzieren Sie sie mit preferred Affinity zusammen.

  3. 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.

  4. Kombinieren Sie mit dem Horizontal Pod Autoscaler und dem Cluster Autoscaler, damit neue Nodes automatisch bereitgestellt werden, wenn Anti-Affinity-Regeln mehr Kapazitaet erfordern.

  5. Dokumentieren Sie Ihre Affinity-Regeln als Teil Ihrer Deployment-Dokumentation. In sechs Monaten werden Sie sich fragen, warum ein bestimmtes required gesetzt wurde.

Weitergehende Ressourcen


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