Dennis Hemeier
Dennis Hemeier
August 23, 2024

101 Series: Kubernetes Affinity und Anti Affinity

101 Series
Wie steuert Kubernetes die Platzierung von Pods in einem Cluster, um sicherzustellen, dass Anwendungen optimal und sicher laufen? In dieser Ausgabe der 101-Series erfahrt ihr alles über Kubernetes Affinity und Anti Affinity, zwei mächtige Mechanismen zur Steuerung der Pod-Platzierung.
Kubernetes Affinity und Anti Affinity

Warum werden Affinity und Anti Affinity benötigt?

Innerhalb eines Kubernetes Clusters laufen typischerweise viele verschiedene Anwendungen parallel. Dabei ist es oft entscheidend, wie und wo diese Anwendungen im Cluster platziert werden. Wie ihr vermutlich alle wisst, übernimmt das platzieren der Pods der Kube Scheduler. Bereits ohne weitere Konfiguration sind viele Anwendungsfälle abgedeckt. Aber was ist, wenn ihr bestimmte Anforderungen habt?

Beispiele hierfür sind:

  1. Eine Anwendung, die spezielle Hardware wie GPUs benötigt, sollte auf Nodes laufen, die diese Hardware bereitstellen. Schlagwort: Machine Learning

  2. Zwei Pods, die intensiv miteinander kommunizieren, sollten auf derselben Node laufen, um die Netzwerk-Latenz zu minimieren.

  3. Um eine hohe Verfügbarkeit sicherzustellen, sollten Replicas eines Pods auf unterschiedlichen Nodes laufen, damit ein Node-Ausfall nicht alle Replicas betrifft.

Für all diese Anwendungsfälle gibt es innerhalb von Kubernetes die Konzepte Node Affinity, Pod Affinity sowie Pod Anti Affinity.

Was sind Node Affinity, Pod Affinity & Pod Anti Affinity?

Node Affinity beschreibt die Präferenz eines Pods, auf einer bestimmten Node oder einer Gruppe von Nodes mit spezifischen Labels platziert zu werden. Zum Beispiel könnt ihr sicherstellen, dass Pods, die auf SSD-Speicher angewiesen sind, nur auf Nodes mit SSDs laufen.

Pod Affinity beschreibt die Beziehung zwischen Pods untereinander und bestimmt, dass Pods nahe beieinander oder sogar auf demselben Node platziert werden. Ein klassischer Anwendungsfall ist, dass Pods eines Frontend-Services auf demselben Node wie Pods eines Backend-Services laufen, um die Netzwerklatenz zu minimieren.

Pod Anti Affinity hingegen stellt sicher, dass bestimmte Pods auf verschiedenen Nodes laufen, um Redundanz und Ausfallsicherheit zu gewährleisten. Ein typischer Anwendungsfall ist die Verteilung von Redis-Replikas auf verschiedene Nodes.

Typen von Affinity und Anti Affinity

Affinity und Anti Affinity können auf zwei verschiedene Arten definiert werden:

  1. PreferredDuringSchedulingIgnoredDuringExecution
    Kubernetes versucht, die Pod-Platzierung basierend auf den angegebenen Regeln zu optimieren, ignoriert diese jedoch, falls sie nicht erfüllt werden können.

  2. RequiredDuringSchedulingIgnoredDuringExecution
    Diese Regeln müssen strikt eingehalten werden. Wenn Kubernetes keinen passenden Node finden kann, bleibt der Pod unplatziert.

Typische Anwendungsfälle

1. High Availability und Redundanz

Um hohe Verfügbarkeit zu gewährleisten, sollte man sicherstellen, dass Replicas eines Pods nicht auf derselben Node laufen. Dies minimiert das Risiko eines kompletten Ausfalls, falls eine Node ausfällt.

Beispiel für Pod Anti Affinity:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis-container
        image: redis:latest
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: redis
            topologyKey: "kubernetes.io/hostname"

Hierbei wird sichergestellt, dass keine zwei Redis-Replicas auf derselben Node platziert werden, was die Ausfallsicherheit erhöht.

2. Optimierung der Netzwerklatenz

Wenn zwei Pods miteinander kommunizieren, kann es sinnvoll sein, sie auf derselben Node zu platzieren, um die Netzwerklatenz zu minimieren.

Beispiel für Pod Affinity:

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod
spec:
  containers:
  - name: backend-container
    image: backend-app:latest
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: frontend
        topologyKey: "kubernetes.io/hostname"

In diesem Fall wird der Pod auf demselben Node wie ein Pod mit dem Label app=frontend platziert.

3. Nutzung spezieller Hardware-Ressourcen

Manchmal muss sichergestellt werden, dass Pods nur auf Nodes laufen, die bestimmte Hardware-Ressourcen wie z.B. GPUs oder SSDs bereitstellen.

Beispiel für Node Affinity:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
  - name: myapp-container
    image: myapp:latest
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd

Hierbei wird der Pod nur auf Nodes platziert, die das Label disktype=ssd haben, um sicherzustellen, dass er auf der richtigen Hardware läuft.

4. Compliance und Sicherheit

In bestimmten Szenarien müssen Pods getrennt voneinander auf unterschiedlichen Nodes laufen, um Sicherheits- oder Compliance-Anforderungen zu erfüllen.

Pod Anti Affinity kann verwendet werden, um sicherzustellen, dass sensible Workloads nicht auf denselben Nodes wie weniger vertrauenswürdige Workloads laufen.

5. Workload-Isolation

In Multi-Tenant-Umgebungen kann es wichtig sein, Workloads bestimmter Nutzer oder Teams auf dedizierte Nodes zu isolieren. Dies kann mit einer weichen Node Affinity erreicht werden.

Beispiel für eine weiche Node Affinity:

apiVersion: v1
kind: Pod
metadata:
  name: preferred-affinity-pod
spec:
  containers:
  - name: app-container
    image: app:latest
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - us-west

In diesem Beispiel versucht Kubernetes, den Pod bevorzugt auf Nodes mit dem Label zone=us-west zu platzieren, ignoriert dies aber, falls keine solchen Nodes verfügbar sind.

Fazit

Die Verwendung von Kubernetes Affinity und Anti Affinity ermöglicht es, Workloads im Cluster gezielt zu steuern und zu optimieren. Diese Mechanismen bieten flexible und leistungsstarke Möglichkeiten, die Platzierung von Pods zu kontrollieren und sicherzustellen, dass Anwendungen effizient, sicher und zuverlässig laufen.

Habt ihr noch Fragen oder Feedback zu Affinity und Anti-Affinity? Weitere Informationen dazu findet ihr in unserer Kubernetes Einführungsschulung! Zögert nicht, uns zu kontaktieren – schreibt uns eine kurze Nachricht oder nutzt den Chat auf unserer Website. Wir freuen uns auf eure Rückmeldungen!