Best Practices für fortgeschrittene Planungsfunktionen in Azure Kubernetes Service (AKS) mithilfe des Kube-Schedulers

Zu den bewährten Methoden für erweiterte Schedulerfeatures in AKS gehören die Verwendung von Taints und Toleranzen, um Knoten dediziert zuzuweisen, von Knotenselektoren und Knotenaffinität zur Steuerung der Pod-Platzierung sowie von Inter-Pod-Affinität bzw. -Antiaffinität, um die Workloadverteilung in Ihrem Cluster zu verwalten. Beim Verwalten von Clustern in Azure Kubernetes Service (AKS) müssen Sie oft Teams oder Workloads isolieren. Mit erweiterten Funktionen, die vom Kubernetes-Scheduler bereitgestellt werden, können Sie Folgendes steuern:

  • Welche Pods auf bestimmten Knoten geplant werden können.
  • Wie Anwendungen mit mehreren Pods angemessen über den Cluster verteilt werden können.

Dieser Artikel zu Best Practices konzentriert sich auf erweiterten Kubernetes-Planungsfunktionen für Clusteroperatoren. In diesem Artikel werden folgende Vorgehensweisen behandelt:

  • Verwenden von Taints und Toleranzen, um einzuschränken welche Pods auf Knoten geplant werden können
  • Festlegen, dass Pods auf bestimmten Knoten ausgeführt werden, mit Knotenselektoren oder Knotenaffinität
  • Trennen oder Gruppieren von Pods mit Pod-interner Affinität oder Antiaffinität
  • Beschränken Sie die Planung von Workloads, die GPUs erfordern, nur auf Knoten mit planbaren GPUs.

Wenn zusätzliche Funktionen oder ML-Frameworks erforderlich sind, um Batchworkloads zu planen und in die Warteschlange zu stellen, können Sie Kueue auf AKS installieren und konfigurieren , um eine effiziente, richtliniengesteuerte Planung in AKS-Clustern sicherzustellen.

Wenn eine fein abgestimmte Zeitplankonfiguration erforderlich ist, um zu optimieren, wie Pods und Aufträge bestimmte Knoten, Speicherressourcen, Topologie und vieles mehr priorisieren, können Sie einen Zeitplan auf AKS konfigurieren.

Vergleich der Planungsfunktionen

Feature Anwendungsfall Planungsverhalten Wann wählen
Taints und Toleranzen Dedizierte Knoten für bestimmte Workloads (z. B. GPU-Knoten) Harte Einschränkung: Pods ohne übereinstimmende Tolerierung können nicht auf kontaminierten Knoten geplant werden Wenn Sie eine strenge Knotenisolation benötigen und nicht autorisierte Workloads verhindern möchten
Knotenselektoren Einfache labelbasierte Platzierung von Pods Weiche Einschränkung: Pods erfordern übereinstimmende Bezeichnungen, aber Pods ohne Bezeichnungen können weiterhin auf Knoten mit Bezeichnungen eingeplant werden Wenn Sie grundlegende Planungssteuerung mit einfachem Bezeichnungsabgleich benötigen
Knotenaffinität Flexible Knotenadressierung mit Fallbackoptionen Konfigurierbar: unterstützt sowohl erforderliche (harte) als auch bevorzugte (weiche) Abgleichsregeln. Wenn Sie erweiterte Ausdrücke benötigen oder Terminplanungseinstellungen mit Fallbackverhalten wünschen
Pod-interne Affinität/Antiaffinität Pods zusammen platzieren oder trennen, basierend auf der vorhandenen Pod-Platzierung Steuert die Podverteilung relativ zu anderen Pods auf Knoten. Wenn Pod-zu-Pod-Beziehungen wichtig sind (z. B. für die gemeinsame Platzierung von App und Cache oder für das Verteilen von Replikaten)

Was sindTaints und Tolerationen?

Taints und Tolerations sind ein Kubernetes-Mechanismus, mit dem Knoten Pods fernhalten können, sofern diese Pods den Taint des Knotens nicht ausdrücklich tolerieren, und der eine strikte Isolation für dedizierte Workloads ermöglicht.

Bewährte Methode: Verwenden von Taints und Tolerationen zum Verwendungszweck von GPU-Knoten Beschränken Sie den Zugriff für ressourcenintensive Anwendungen, z. B. Eingangscontroller, auf bestimmte Knoten. Halten Sie die Knotenressourcen für Workloads, die sie benötigen, verfügbar, und erlauben Sie keine Zuweisung anderer Workloads auf den Knoten.

Wenn Sie Ihren AKS-Cluster erstellen, können Sie Knoten mit GPU-Unterstützung oder einer großen Anzahl leistungsstarker CPUs bereitstellen. Weitere Informationen finden Sie unter Verwenden von GPUs in AKS. Sie können diese Knoten für große Datenverarbeitungsworkloads wie Machine Learning (ML) oder Künstliche Intelligenz (KI) verwenden.

Da diese Knotenressourcen-Hardware in der Regel teuer in der Bereitstellung ist, begrenzen Sie die Workloads, die auf diesen Knoten geplant werden können. Stattdessen widmen Sie einige Knoten im Cluster dem Ausführen von Ingress-Diensten und um andere Workloads zu verhindern.

Diese Unterstützung für verschiedene Knoten erhalten Sie durch die Verwendung von mehrerer Knotenpools. Ein AKS-Cluster bietet einen oder mehrere Knotenpools.

Der Kubernetes-Scheduler verwendet Taints und Toleranzen, um einzuschränken, welche Workloads auf Knoten ausgeführt werden können.

  • Wenden Sie ein Taint auf einen Knoten an, um anzugeben, dass nur bestimmte Pods auf ihm geplant werden können.
  • Dann wenden Sie eine Toleranz auf einen Pod an, sodass dieser den Taint des Knotens tolerieren kann.

Wenn Sie einen Pod in einem AKS-Cluster bereitstellen, plant Kubernetes nur Pods auf Knoten, deren Taint der Toleranz entspricht. Taints und Toleranzen arbeiten zusammen, um sicherzustellen, dass Pods nicht auf ungeeigneten Knoten geplant werden. Ein oder mehrere Taints werden auf einen Knoten angewendet und markieren den Knoten so, dass er keine Pods akzeptiert, die die Taints nicht tolerieren.

Wie kann ich Taints und Tolerationen in AKS implementieren?

Angenommen, Sie haben Ihrem AKS-Cluster einen Knotenpool für Knoten mit GPU-Unterstützung hinzugefügt. Sie definieren einen Namen, z.B. gpu und dann einen Wert für die Planung. Wenn Sie diesen Wert auf NoSchedule festlegen, kann der Kubernetes-Scheduler keine Pods mit nicht definierter Toleranz auf dem Knoten planen.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name taintnp \
    --node-taints sku=gpu:NoSchedule \
    --no-wait

Wenn für Knoten im Knotenpool ein Taint angewendet wird, definieren Sie in den Podspezifikationen eine Toleranz, die eine Planung für die Knoten ermöglicht. Im folgenden Beispiel werden sku: gpu und effect: NoSchedule so definiert, dass der im vorherigen Schritt auf den Knotenpool angewendete Taint toleriert wird.

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"

Wenn dieser Pod mit kubectl apply -f gpu-toleration.yaml bereitgestellt wird, kann Kubernetes den Pod erfolgreich auf den Knoten mit dem angewandten Taint planen. Mit dieser logischen Isolation können Sie den Zugriff auf Ressourcen innerhalb eines Clusters steuern.

Bereitstellen von Knotenpools für mehrere Anwendungen

Um verschiedenen Anwendungen jeweils eigene Knoten zuzuweisen, erstellen Sie für jede Anwendung einen Knotenpool mit einem eindeutigen Taint und einem entsprechenden Label. Die Markierung verhindert, dass andere Pods dem Knotenpool zugewiesen werden, während Sie mit dem Label festlegen können, dass eine Anwendung nur auf ihrem dedizierten Knotenpool ausgeführt wird.

Im folgenden Beispiel werden separate Knotenpools für Frontend- und Back-End-Anwendungen erstellt:

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name frontpool \
    --node-count 1 \
    --labels workload=frontend \
    --node-taints workload=frontend:NoSchedule

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name backpool \
    --node-count 1 \
    --labels workload=backend \
    --node-taints workload=backend:NoSchedule

Erstellen Sie eine Datei mit dem Namen dedicated-apps.yaml , und fügen Sie die folgenden Poddefinitionen hinzu. Jeder Pod verfügt über eine Toleration, die mit dem Taint seines Knotenpools übereinstimmt, und über ein nodeSelector, das das entsprechende Knotenpool-Label voraussetzt:

apiVersion: v1
kind: Pod
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  nodeSelector:
    workload: frontend
  tolerations:
  - key: "workload"
    operator: "Equal"
    value: "frontend"
    effect: "NoSchedule"
  containers:
  - name: frontend
    image: mcr.microsoft.com/oss/nginx/nginx:1.25.5
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi
---
apiVersion: v1
kind: Pod
metadata:
  name: backend
  labels:
    app: backend
spec:
  nodeSelector:
    workload: backend
  tolerations:
  - key: "workload"
    operator: "Equal"
    value: "backend"
    effect: "NoSchedule"
  containers:
  - name: backend
    image: mcr.microsoft.com/oss/nginx/nginx:1.25.5
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi

Anwenden des Manifests:

kubectl apply -f dedicated-apps.yaml

Überprüfen Sie, ob jeder Pod auf einem Knoten mit dem erwarteten Workload-Label läuft:

kubectl get pods -o wide
kubectl get nodes -L workload

Der frontend pod wird auf einem mit workload=frontend gekennzeichneten Knoten ausgeführt, und der backend pod wird auf einem mit workload=backend gekennzeichneten Knoten ausgeführt. Eine Toleration allein ermöglicht einem Pod die Verwendung eines nicht markierten Knotens, erfordert jedoch keine Platzierung auf diesem Knoten. nodeSelector erfüllt diese Anforderung.

Löschen Sie die Beispielressourcen, wenn Sie sie nicht mehr benötigen:

kubectl delete -f dedicated-apps.yaml

az aks nodepool delete \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name frontpool

az aks nodepool delete \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name backpool

Wenn Sie Taints anwenden, arbeiten Sie mit Ihren Anwendungsentwicklern und -besitzern zusammen, damit sie die erforderlichen Toleranzen in ihren Bereitstellungen definieren können.

Weitere Informationen zur Verwendung mehrerer Knotenpools in AKS finden Sie unter Erstellen mehrerer Knotenpools für einen Cluster in AKS.

Verhalten von Taints und Toleranzen in AKS

Wenn Sie ein Upgrade für einen Knotenpool in AKS durchführen, folgen Taints und Toleranzen einem festen Muster, da sie für neue Knoten angewendet werden:

Standardcluster, die Azure-VM-Skalierungsgruppen verwenden

Sie können über die AKS-API einen Knotenpool mit Taints versehen, damit neu aufskalierte Knoten die von der API angegebenen Knotentaints erhalten.

Gehen Sie von folgender Annahme aus:

  1. Sie beginnen mit einem Cluster mit zwei Knoten: node1 und node2.
  2. Sie führen ein Upgrade für den Knotenpool durch.
  3. Zwei zusätzliche Knoten werden erstellt: node3 und node4.
  4. Die Taints werden entsprechend übergeben.
  5. Die ursprünglichen node1 und node2 werden gelöscht.

Cluster ohne Unterstützung für VM-Skalierungsgruppen

Gehen Sie noch einmal von folgender Annahme aus:

  1. Sie haben einen Cluster mit zwei Knoten: node1 und node2.
  2. Sie führen ein Upgrade für den Knotenpool durch.
  3. Ein zusätzlicher Knoten wird erstellt: node3.
  4. Die Taints von node1 werden auf node3 übertragen.
  5. node1 wird gelöscht.
  6. Es wird ein neuer Knoten1 erstellt, um den ursprünglichen Knoten1 zu ersetzen.
  7. Die Taints aus node2 werden auf den neuen node1 angewendet.
  8. node2 wird gelöscht.

Zusammengefasst wird node1 zu node3, und node2 wird zum neuen node1.

Wenn Sie einen Knotenpool in AKS skalieren, werden Taints und Toleranzen absichtlich nicht übertragen.

Was sind Knotenselektoren und Knotenaffinität?

Node-Selektoren und Node-Affinität sind Funktionen von Kubernetes, mit denen Pods anhand von Knoten-Labels Präferenzen dafür angeben können, auf welchen Knoten sie ausgeführt werden sollen.

Best Practice: Verwenden Sie Knotenselektoren und Affinität, um die Platzierung von Pods nach Hardwaretyp zu steuern Steuern Sie die Planung von Pods auf Knoten mithilfe von Knotenselektoren, Knotenaffinität oder Inter-Pod-Affinität. Diese Einstellungen ermöglichen es dem Kubernetes-Scheduler, Workloads logisch zu isolieren, z.B. durch Hardware im Knoten.

Mit Taints und Toleranzen werden Ressourcen durch eine harte Trennung logisch isoliert. Wenn der Pod den Taint eines Knotens nicht toleriert, wird er nicht auf dem Knoten geplant.

Alternativ können Sie Knotenselektoren verwenden. Beispielsweise bezeichnen Sie Knoten, um einen lokal angefügten SSD-Speicher oder eine große Menge an Speicher anzuzeigen, und definieren dann in der Podspezifikation einen Knotenselektor. Kubernetes plant diese Pods auf einem passenden Knoten.

Im Gegensatz zu Toleranzen können Pods ohne einen übereinstimmenden Knotenselektor dennoch auf bezeichneten Knoten geplant werden. Dieses Verhalten ermöglicht es, ungenutzte Ressourcen auf den Knoten zu verwenden, priorisiert aber Pods, die den passenden Knotenselektor definieren.

Sehen wir uns ein Beispiel für Knoten mit einer hohe Menge an Arbeitsspeicher an. Diese Knoten priorisieren Pods, für die viel Speicher erforderlich ist. Um sicherzustellen, dass die Ressourcen nicht ungenutzt bleiben, können sie auch andere Pods ausführen. Der folgende Beispielbefehl fügt myAKSCluster in myResourceGroup einen Knotenpool mit der Bezeichnung hardware=highmem hinzu. Alle Knoten in diesem Knotenpool verfügen über diese Bezeichnung.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name labelnp \
    --node-count 1 \
    --labels hardware=highmem \
    --no-wait

Eine Podspezifikation fügt dann die Eigenschaft nodeSelector hinzu, um einen Knotenselektor zu definieren, der mit der auf einem Knoten festgelegten Bezeichnung übereinstimmt:

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  nodeSelector:
      hardware: highmem

Wenn Sie diese Scheduler-Optionen verwenden, arbeiten Sie mit Ihren Anwendungsentwicklern und -besitzern zusammen, damit sie ihre Pod-Spezifikationen korrekt definieren können.

Weitere Informationen zur Verwendung von Knotenselektoren finden Sie unter Zuweisen von Pods zu Knoten.

Was ist die Knotenaffinität?

Ein Knotenselektor ist eine grundlegende Methode zum Zuweisen von Pods zu einem bestimmten Knoten. Die Knotenaffinität bietet mehr Flexibilität, indem Sie festlegen können, was geschieht, wenn der Pod keinem Knoten zugewiesen werden kann. Ihre Möglichkeiten:

  • Anfordern, dass der Kubernetes-Scheduler einem Pod mit einem bezeichneten Host entspricht. Oder:
  • Eine Übereinstimmung bevorzugen, aber zulassen, dass der Pod auf einem anderen Host geplant wird, wenn keine Übereinstimmung vorhanden ist.

Im folgenden Beispiel wird die Knotenaffinität auf RequiredDuringSchedulingIgnoredDuringExecution festgelegt. Aufgrund dieser Affinität muss der Kubernetes-Scheduler einen Knoten mit einer übereinstimmenden Bezeichnung verwenden. Wenn kein Knoten verfügbar ist, muss der Pod warten, bis die Planung fortgesetzt wird. Damit der Pod auf einem anderen Knoten eingeplant werden kann, können Sie stattdessen den Wert auf preferredDuringSchedulingIgnoreDuringExecution festlegen:

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: hardware
            operator: In
            values:
            - highmem

Der IgnoredDuringExecution-Teil der Einstellung gibt an, dass der Pod nicht vom Knoten entfernt werden soll, wenn sich die Bezeichnung des Knotens ändert. Der Kubernetes-Scheduler verwendet nur die aktualisierten Knotenbezeichnungen für neue Pods, die geplant werden, nicht für bereits geplante Pods auf den Knoten.

Weitere Informationen finden Sie unter Affinität und Antiaffinität.

Was ist Inter-Pod-Affinität und Antiaffinität?

Ein letzter Ansatz für den Kubernetes-Scheduler zur logischen Isolation von Workloads ist die Verwendung von Pod-interner Affinität oder Antiaffinität. Diese Einstellungen definieren, dass Pods auf einem Knoten mit einem übereinstimmenden Pod entweder geplant oder nicht geplant werden sollten. Standardmäßig versucht der Kubernetes-Scheduler mehrere Pods knotenübergreifend in einer Replikatgruppe zu planen. Sie können spezifischere Regeln für dieses Verhalten definieren.

Beispielsweise verfügen Sie über eine Webanwendung, die auch eine Azure Managed Redis-Ressource verwendet.

  • Sie verwenden Regeln für die Pod-Antiaffinität, um anzufordern, dass der Kubernetes-Scheduler Replikate über Knoten verteilt.
  • Sie verwenden Affinitätsregeln, um sicherzustellen, dass jede Komponente der Webanwendung auf dem gleichen Host wie ein entsprechender Cache geplant ist.

Die Verteilung der Pods auf die Knoten sieht beispielsweise wie folgt aus:

Knoten 1 Knoten 2 Knoten 3
webapp-1 webapp-2 webapp-3
cache-1 cache-2 cache-3

Pod-interne Affinität und Antiaffinität ermöglichen eine komplexere Bereitstellung als Knotenselektoren oder Knotenaffinität. Mit der Bereitstellung nehmen Sie eine logische Isolierung von Ressourcen vor und steuern, wie Kubernetes Pods auf Knoten plant.

Ein vollständiges Beispiel für diese Webanwendung mit Azure Managed Redis finden Sie unter Pods auf demselben Knoten zusammenführen.

Nächste Schritte

Dieser Artikel konzentriert sich auf erweiterte Funktionen des Kubernetes-Schedulers. Weitere Informationen zu Clustervorgängen in AKS finden Sie in den folgenden Best Practices: