Multislice-Arbeitslasten mit JobSet und Kueue orchestrieren

In dieser Anleitung wird gezeigt, wie Sie mehrere Multislice-Arbeitslasten in Google Kubernetes Engine (GKE) orchestrieren, um die Ressourcennutzung zu verbessern. Sie stellen eine Jax-Arbeitslast als Beispiel bereit, führen sie auf TPU-Multislice aus und implementieren die Jobwarteschlange mit JobSet und Kueue. Kueue bestimmt anhand der verfügbaren Ressourcen, Kontingente und einer Hierarchie für die faire Freigabe von Ressourcen, wann Jobs ausgeführt werden sollen.

Diese Anleitung richtet sich an Entwickler von maschinellem Lernen (ML) und Plattformadministratoren und ‑betreiber, die sich für die Containerorchestrierungsfunktionen von Kubernetes zum Trainieren von LLMs interessieren. Weitere Informationen zu gängigen Rollen und Beispielaufgaben, auf die wir in Google Cloud -Inhalten verweisen, finden Sie unter Häufig verwendete GKE-Nutzerrollen und -Aufgaben.

Machen Sie sich vor dem Lesen dieser Seite mit den folgenden Themen vertraut:

Umgebung vorbereiten

  1. Starten Sie in der Google Cloud Console eine Cloud Shell-Instanz:
    Cloud Shell öffnen

  2. Legen Sie die Standardumgebungsvariablen mit dem Befehl gcloud config set fest:

    gcloud config set project PROJECT_ID
    

    Ersetzen Sie PROJECT_ID durch Ihre Google Cloud Projekt-ID.

Autopilot-Cluster, auf denen Version 1.29.2-gke.1521000 oder höher ausgeführt wird, aktivieren standardmäßig TPUs. TPUs in Autopilot-Clustern werden in der Arbeitslastspezifikation konfiguriert. Weitere Informationen finden Sie im Abschnitt Multislice-Arbeitslasten mit JobSets definieren.

GKE-Cluster erstellen

Erstellen Sie in Cloud Shell einen GKE-Cluster:

Autopilot

gcloud container clusters create-auto multislice-cluster \
    --location=CONTROL_PLANE_LOCATION \
    --cluster-version 1.29.2-gke.1521000 \
    --release-channel rapid

Dabei gilt:

  • Das Flag --location gibt die Compute Engine-Region der Steuerungsebene des Clusters an.
  • Mit dem Flag --cluster-version wird die Kubernetes-Version für Ihren Cluster angegeben.
  • Das Flag --release-channel gibt die Release-Version für Ihren Cluster an. In diesem Fall unterstützt der Rapid Channel die neuesten in GKE verfügbaren Versionen.

Standard

gcloud container clusters create multislice-cluster \
    --location=CONTROL_PLANE_LOCATION

Ersetzen Sie CONTROL_PLANE_LOCATION durch den Standort, an dem Sie den Cluster erstellen möchten. Achten Sie darauf, dass es Kapazität für den Maschinentyp ct5lp-hightpu-4t hat. Die Erstellung eines Clusters kann einige Minuten dauern.

Wenn Sie den GKE-Autopilot-Modus verwenden, fahren Sie mit dem Abschnitt Kuee-Ressourcen erstellen fort. Autopilot-Cluster, die Version 1.29.2-gke.1521000 oder höher ausführen, aktivieren standardmäßig TPUs.

Drei TPU-Slice-Knotenpools im Standardmodus erstellen

In diesem Abschnitt erstellen Sie TPU-Knotenpools mit dem Befehl gcloud beta container node-pools create.

  1. Erstellen Sie den ersten Knotenpool mit dem Namen nodepool1:

    gcloud beta container node-pools create nodepool1 \
        --location=CONTROL_PLANE_LOCATION \
        --cluster=multislice-cluster \
        --node-locations=NODE_LOCATION \
        --machine-type=ct5lp-hightpu-4t \
        --tpu-topology=2x4 \
        --project=PROJECT_ID
    

    Ersetzen Sie NODE_LOCATION durch eine oder mehrere Zonen in der Clusterregion, in der Sie die Knoten erstellen möchten.

  2. Erstellen Sie den zweiten Knotenpool mit dem Namen nodepool2:

    gcloud beta container node-pools create nodepool2 \
        --location=CONTROL_PLANE_LOCATION \
        --cluster=multislice-cluster \
        --node-locations=NODE_LOCATION \
        --machine-type=ct5lp-hightpu-4t \
        --tpu-topology=2x4 \
        --project=PROJECT_ID
    
  3. Erstellen Sie den dritten Knotenpool mit dem Namen nodepool3:

    gcloud beta container node-pools create nodepool3 \
        --location=CONTROL_PLANE_LOCATION \
        --cluster=multislice-cluster \
        --node-locations=NODE_LOCATION \
        --machine-type=ct5lp-hightpu-4t \
        --tpu-topology=2x4 \
        --project=PROJECT_ID
    

GKE erstellt drei Knotenpools. Jeder Knotenpool ist ein separates TPU-Slice.

In den vorherigen Schritten haben Sie den Befehl gcloud beta container node-pools create verwendet, um die Knotenpools zu erstellen. Diese Befehle verwenden die folgenden Flags:

  • --node-locations: Die durch Kommas getrennte Liste mit einer oder mehreren Zonen, in denen GKE die Knotenpools erstellt.
  • --machine-type: Der Maschinentyp für Knoten. In diesem Fall haben Sie ct5lp-hightpu-4t verwendet. Weitere Informationen zu TPU-kompatiblen Maschinentypen finden Sie in der Tabelle unter TPU-Version auswählen.
  • --tpu-topology: Die TPU-Topologie, die für den Knotenpool verwendet werden soll. In diesem Fall haben Sie 2x4 verwendet. Weitere Informationen zu TPU-Topologien finden Sie unter TPU-Topologie auswählen.

Kueue-Ressourcen erstellen

  1. Erstellen Sie das folgende kueue.yaml-Manifest:

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
      name: "vlp-24"
    spec:
      nodeLabels:
        cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
        cloud.google.com/gke-tpu-topology: 2x4
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: "cluster-queue"
    spec:
      namespaceSelector: {}
      queueingStrategy: BestEffortFIFO
      resourceGroups:
      - coveredResources: ["google.com/tpu"]
        flavors:
        - name: "vlp-24"
          resources:
          - name: "google.com/tpu"
            nominalQuota: 24
    
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      namespace: default
      name: multislice-queue
    spec:
      clusterQueue: cluster-queue
    
  2. Wenden Sie das kueue.yaml-Manifest an:

    kubectl apply -f kueue.yaml
    

GKE erstellt die folgenden Kueue-Ressourcen:

  • ResourceFlavor: Eine Abstraktion der Ressourcen in einem Cluster. In diesem Beispiel erstellt GKE drei TPU-Slices mit 2x4-Topologie. Jedes TPU-Slice hat eine 2x4-Topologie mit 8 Chips (insgesamt 24 TPU-Chips).
  • ClusterQueue: Eine globale Warteschlange zur Verwaltung von Arbeitslasten und Clusterressourcen.
  • LocalQueue: Hier werden eng verwandte Arbeitslasten gruppiert, die in der Regel von einem einzelnen Mandanten (Nutzer) ausgeführt werden. Jede LocalQueue verweist auf eine ClusterQueue, aus der Ressourcen zum Ausführen der Arbeitslasten zugewiesen werden. Eine Kueue-Arbeitslast ist eine Abstraktion, die eine Batcharbeitslast darstellt. In diesem Fall ist jede Arbeitslast ein JobSet.

Multislice-Arbeitslasten mit JobSets definieren

In diesem Abschnitt erstellen Sie drei JobSets. Ein Jobset ist eine Arbeitslast-API, mit der Sie eine Gruppe von Kubernetes-Jobs als Einheit verwalten können. Der häufigste Anwendungsfall für ein JobSet ist das verteilte Training. Sie können es aber auch zum Ausführen von Batch-Arbeitslasten verwenden.

Die folgenden JobSets führen eine Jax-Arbeitslast aus, die die globale Anzahl von TPU-Chips im Slice ausgibt, 60 Sekunden lang pausiert, um eine gewisse Modelltrainingszeit zu simulieren, und dann beendet wird.

  1. Installieren Sie die JobSet API in Ihrem Cluster:

    VERSION=v0.8.1
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/jobset/releases/download/$VERSION/manifests.yaml
    
  2. Erstellen Sie das folgende jobsets-multislice.yaml-Manifest:

    Autopilot

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-1slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 1
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    command:
                    - bash
                    - -c
                    - |
                      pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                      python -c 'import jax; print("Global device count:", jax.device_count())'
                    resources:
                      limits:
                        google.com/tpu: 4
    
    ---
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-2slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 2
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    command:
                    - bash
                    - -c
                    - |
                      pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                      python -c 'import jax; print("Global device count:", jax.device_count())'
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4
    ---
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-3slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 3
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    command:
                    - bash
                    - -c
                    - |
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4
    

    Standard

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-1slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 1
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    securityContext:
                      privileged: true
                    command:
                    - bash
                    - -c
                    - |
                      pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                      python -c 'import jax; print("Global device count:", jax.device_count())'
                    resources:
                      limits:
                        google.com/tpu: 4
    
    ---
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-2slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 2
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    securityContext:
                      privileged: true
                    command:
                    - bash
                    - -c
                    - |
                      pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                      python -c 'import jax; print("Global device count:", jax.device_count())'
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4
    ---
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: multislice-3slice
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 3
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    securityContext:
                      privileged: true
                    command:
                    - bash
                    - -c
                    - |
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4
    
  3. Wenden Sie das jobsets-multislice.yaml-Manifest an:

    kubectl apply -f jobsets-multislice.yaml
    

GKE erstellt die Jobs mit den folgenden Ressourcenanfragen:

  • Mit dem multislice-1slice-JobSet wird ein Job erstellt, für den insgesamt ein TPU-Slice erforderlich ist.
  • Mit dem multislice-2slice-JobSet werden zwei Jobs erstellt, für die insgesamt zwei TPU-Slices erforderlich sind.
  • Im multislice-3slice-JobSet werden drei Jobs erstellt, für die insgesamt drei TPU-Slices erforderlich sind.

Da der Cluster nur drei TPU-Slices hat, können nicht alle JobSets gleichzeitig ausgeführt werden. Wenn Kueue alle drei multislice-3slice-JobSets in die Warteschlange stellt, werden die Jobs allein bis zum Abschluss ausgeführt. Das multislice-1slice und multislice-2slice warten und werden gemeinsam ausgeführt.

Prüfen, ob Kueue die Arbeitslasten zugelassen hat

  1. Prüfen Sie die in die Warteschlange eingereihten Arbeitslasten in Kueue:

    kubectl get workloads
    

    Die Ausgabe sieht in etwa so aus:

    NAME                             QUEUE              ADMITTED BY     AGE
    jobset-multislice-1slice-2530a   multislice-queue                   3s
    jobset-multislice-2slice-ffb02   multislice-queue                   4s
    jobset-multislice-3slice-8c695   multislice-queue   cluster-queue   10s
    

Kueue stellt je nach den erforderlichen TPU-Ressourcen eine oder mehrere Arbeitslasten in die Warteschlange.

Arbeitslasten überwachen

Messwerte und Dashboards zur Beobachtbarkeit von JobSet und Knotenpool in der Google Cloud Console sind allgemein verfügbar.

Dashboards

Wenn Sie den Status Ihrer TPU-Knotenpools mit mehreren Hosts in GKE aufrufen möchten, rufen Sie das von Cloud Monitoring bereitgestellte Dashboard GKE TPU Node Pool Status auf:

Zum GKE TPU-Knotenpoolstatus

Weitere Informationen finden Sie unter Zustandsmesswerte für TPU-Knoten und ‑Knotenpools überwachen.

Auf der Seite Kubernetes Engine AI/ML in derGoogle Cloud -Konsole wird auf dem Tab KI-Bereitstellung > Jobs ein JobSet-Monitoring-Dashboard mit umfassenden Informationen zum Zustand und zur Leistung von JobSets und der zugrunde liegenden Infrastruktur angezeigt, z. B. JobSet-Status, Replikatbereitschaft und Replikatstatus. Das Dashboard enthält auch Infrastrukturmesswerte wie CPU-, GPU-, TPU-, Arbeitsspeicher- und Speichermesswerte. Weitere Informationen finden Sie unter JobSet-Zustand mit Messwerten überwachen.

Überwachen, welche Pods ausgeführt werden

kubectl get pods

Die Ausgabe sieht etwa so aus:

NAME                                READY   STATUS      RESTARTS   AGE
multislice-1slice-slice-0-0-pf2ll   1/1     Running     0          1s
multislice-1slice-slice-0-1-55g62   1/1     Running     0          1s
multislice-2slice-slice-0-0-f4hf7   1/1     Running     0          3s
multislice-2slice-slice-0-1-c8kv7   1/1     Running     0          3s
multislice-2slice-slice-1-0-7h46t   1/1     Running     0          3s
multislice-2slice-slice-1-1-lj9hb   1/1     Running     0          3s
multislice-3slice-slice-0-0-wzq9t   0/1     Completed   0          2m31s
multislice-3slice-slice-0-1-zf4dp   0/1     Completed   0          2m30s
multislice-3slice-slice-1-0-hbfn5   0/1     Completed   0          2m31s
multislice-3slice-slice-1-1-45fgl   0/1     Completed   0          2m30s
multislice-3slice-slice-2-0-wjbp4   0/1     Completed   0          2m30s
multislice-3slice-slice-2-1-lwnvs   0/1     Completed   0          2m30s

Prüfen Sie, ob GKE die Pods für multislice-3slice zuerst geplant, erstellt und ausgeführt hat. Anschließend hat GKE die Pods aus den JobSets multislice-1slice und multislice-2slice ausgeführt.

JobSet-Zustand mit Messwerten überwachen

Um zu sehen, ob ein JobSet wie erwartet ausgeführt wird oder ob es unterbrochen wurde, können Sie Prometheus-Messwerte aus dem JobSet-Messwertepaket verwenden, z. B. kube_jobset_succeeded_replicas.

Hinweis: Jobset-Messwerte für den Zustand werden nur in GKE-Version 1.32.1-gke.135700 oder höher unterstützt. JobSet-Messwerte für den Zustand sind in neu erstellten Clustern mit unterstützten Versionen standardmäßig aktiviert. Bei vorhandenen Clustern, die auf unterstützte Versionen aktualisiert werden, müssen Kunden das JobSet-Messwertepaket manuell aktivieren. Weitere Informationen finden Sie in der Dokumentation.

Prüfen Sie für dieses Tutorial den Abschluss des JobSets mit dieser PromQL-Abfrage:

kube_jobset_succeeded_replicas{
  cluster="multislice-cluster",
  jobset_name=~"mulitslice-.*"}

Betriebszeit, Wiederherstellungszeiten (Time To Recover, TTR) und Zeiten zwischen Unterbrechungen (Time Between Interruptions, TBI) von JobSets überwachen

Die folgenden Messwerte sind nützlich, um die Verfügbarkeit eines JobSets zu überwachen:

  • kubernetes.io/jobset/uptime: Gesamtzeit, in der der JobSet verfügbar war.
  • kubernetes.io/jobset/times_to_recover: Verteilung des Wiederherstellungszeitraums für ein JobSet. Jede Stichprobe steht für ein einzelnes Wiederherstellungsereignis nach einer Ausfallzeit für das JobSet.
  • kubernetes.io/jobset/times_between_interruptions: Verteilung des Intervalls zwischen dem Ende der vorherigen Unterbrechung und dem Beginn der aktuellen Unterbrechung für ein JobSet. Jedes Beispiel gibt die Dauer zwischen der vorherigen und der aktuellen Unterbrechung an.

Diese Messwerte gelten für JobSets mit genau einem replizierten GPU- oder TPU-Job. Die Berechnung der Messwerte basiert nur auf der Verfügbarkeit dieses einzelnen replizierten Jobs. Die Messwerte werden in allen GKE-Versionen unterstützt.

Führen Sie die folgende PromQL-Abfrage aus, um die Betriebszeit für die in dieser Anleitung verwendeten JobSets aufzurufen:

avg_over_time(
  kubernetes_io:jobset_uptime{
    monitored_resource="k8s_entity", entity_type="jobset",
    entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}])

Führen Sie die folgende PromQL-Abfrage aus, um die TBI-Verteilungen für die JobSets aus diesem Tutorial aufzurufen:

histogram_quantile(0.50,
  sum_over_time(
    kubernetes_io:jobset_times_between_interruptions_bucket{
      monitored_resource="k8s_entity",entity_type="jobset",
      entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))

Sie können das Intervall der Abfrage auf einen längeren Zeitraum ausdehnen, z. B. 7 Tage, und die durchschnittliche Zeit zwischen Unterbrechungen (Mean Time Between Interruptions, MTBI) für diesen Zeitraum berechnen:

sum(sum_over_time(
  kubernetes_io:jobset_times_between_interruptions_sum{
    monitored_resource="k8s_entity",entity_type="jobset",
    entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))
/
sum(sum_over_time(
  kubernetes_io:jobset_times_between_interruptions_count{
    monitored_resource="k8s_entity",entity_type="jobset",
    entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))

Wenn Sie die TTR-Verteilungen aufrufen möchten, können Sie die folgenden PromQL-Abfragen ausführen:

histogram_quantile(0.50,
  sum_over_time(
    kubernetes_io:jobset_times_to_recover_bucket{
      monitored_resource="k8s_entity",entity_type="jobset",
      entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))

Nachdem Sie das Abfrageintervall auf einen längeren Zeitraum, z. B. 7 Tage, erhöht haben, können Sie die durchschnittliche Zeit bis zur Wiederherstellung (Mean Time to Recover, MTTR) für diesen Zeitraum berechnen:

sum(sum_over_time(
  kubernetes_io:jobset_times_to_recover_sum{
    monitored_resource="k8s_entity",entity_type="jobset",
    entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))
/
sum(sum_over_time(
  kubernetes_io:jobset_times_to_recover_count{
    monitored_resource="k8s_entity",entity_type="jobset",
    entity_name=~"multislice-.*",cluster_name="multislice-cluster"}[${__interval}]))

Kueue-Arbeitslastprioritäten und vorzeitiges Beenden aktivieren

Optional können Sie Kueue-Arbeitslasten Prioritäten zuweisen, die die Reihenfolge bestimmen, in der in die Warteschlange eingereihte Arbeitslasten von Kueue zugelassen werden.

  1. Aktualisieren Sie Ihre ClusterQueue mit einer Richtlinie zum vorzeitigen Beendigen:

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
      name: "vlp-24"
    spec:
      nodeLabels:
        cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
        cloud.google.com/gke-tpu-topology: 2x4
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: "cluster-queue"
    spec:
      namespaceSelector: {}
      resourceGroups:
      - coveredResources: ["google.com/tpu"]
        flavors:
        - name: "vlp-24"
          resources:
          - name: "google.com/tpu"
            nominalQuota: 24
      preemption:
        reclaimWithinCohort: Any
        withinClusterQueue: LowerPriority
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      namespace: default
      name: multislice-queue
    spec:
      clusterQueue: cluster-queue
    
  2. Erstellen Sie eine PriorityClass für jede Prioritätsstufe, die Sie Arbeitslasten zuweisen möchten:

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: low-priority
    value: 100
    globalDefault: false
    description: "This low priority class should be used for some Pods only."
    
  3. Weisen Sie Ihrem JobSet priorityClassName zu:

    Autopilot

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: low-priority
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 1
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  priorityClassName: low-priority
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    command:
                    - bash
                    - -c
                    - |
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4 # Number of TPU chips per worker
    

    Standard

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: low-priority
      labels:
        kueue.x-k8s.io/queue-name: multislice-queue
      annotations:
        alpha.jobset.sigs.k8s.io/exclusive-topology: cloud.google.com/gke-nodepool
    spec:
      failurePolicy:
        maxRestarts: 4
      replicatedJobs:
        - name: slice
          replicas: 1
          template:
            spec:
              parallelism: 2
              completions: 2
              backoffLimit: 0
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu-v5-lite-podslice
                    cloud.google.com/gke-tpu-topology: 2x4
                  priorityClassName: low-priority
                  containers:
                  - name: jax-tpu
                    image: python:3.8
                    ports:
                    - containerPort: 8471
                    - containerPort: 8080
                    securityContext:
                      privileged: true
                    command:
                    - bash
                    - -c
                    - |
                      sleep 60
                    resources:
                      limits:
                        google.com/tpu: 4 # Number of TPU chips per worker
    

GKE enthält eine Preemption-Richtlinie, die definiert, wie Kueue die verfügbaren Ressourcen zuweist. Die Richtlinie gibt an, dass eine Arbeitslast vorzeitig beendet werden kann, wenn eine Arbeitslast mit höherer Priorität die Ressourcen benötigt. Arbeitslasten mit einem niedrigeren Prioritätswert werden mit höherer Wahrscheinlichkeit von Arbeitslasten mit höherer Priorität unterbrochen.