Batchsystem mit Kueue bereitstellen


In diesem Tutorial erfahren Sie, wie Sie ein Batchsystem mit Kueue bereitstellen, um auf der Google Kubernetes Engine (GKE) Jobs in eine Warteschlange zu stellen. In dieser Anleitung erfahren Sie, wie Sie GKE und Kueue einrichten, um Jobs in einem FIFO-Modell (First-in-First-Out) auszuführen.

Hintergrund

Jobs sind Anwendungen, die vollständig ausgeführt werden, z. B. maschinelles Lernen, Rendering, Simulation, Analysen, CI/CD und ähnliche Arbeitslasten.

Kueue ist ein cloudnativer Jobplaner, der mit dem Standard-Kubernetes-Planer, dem Job-Controller und dem Cluster-Autoscaling ein End-to-End-Batchsystem bereitstellt. Kueue implementiert die Jobwarteschlangen und entscheidet anhand der Kontingente und einer Hierarchie für die faire Freigabe von Ressourcen, wann Jobs warten und wann sie gestartet werden sollen.

Kueue hat folgende Merkmale:

  • Es ist für Cloud-Architekturen optimiert, in denen Ressourcen heterogen, austauschbar und skalierbar sind.
  • Es bietet eine Reihe von APIs für die Verwaltung elastischer Kontingente und für die Verwaltung von Jobwarteschlangen.
  • Vorhandene Funktionen wie Autoscaling, Pod-Planung oder Verwaltung des Joblebenszyklus werden nicht neu implementiert.
  • Kueue bietet integrierte Unterstützung für die Kubernetes batch/v1.Job API.
  • Es kann in andere Job-APIs eingebunden werden.

Kueue bezieht sich auf Jobs, die mit einer beliebigen API als Arbeitslasten definiert sind, um Verwechslungen mit der spezifischen Kubernetes-Job-API zu vermeiden.

Lernziele

Diese Anleitung richtet sich an Clusteroperatoren und andere Nutzer, die ein Batchsystem in Kubernetes implementieren möchten. In dieser Anleitung richten Sie einen freigegebenen Cluster für zwei Mandantenteams ein. Jedes Team hat einen eigenen Namespace, in dem es Jobs erstellt und dieselben globalen Ressourcen verwendet, die durch die entsprechenden Kontingente gesteuert werden.

Diese Anleitung umfasst die folgenden Schritte:

  1. GKE-Cluster erstellen
  2. ResourceFlavor erstellen
  3. ClusterQueue erstellen
  4. LocalQueue erstellen
  5. Jobs erstellen und zugelassene Arbeitslasten beobachten

Kosten

In dieser Anleitung werden die folgenden kostenpflichtigen Komponenten von Google Cloud verwendet:

Sie können mithilfe des Preisrechners eine Kostenschätzung für Ihre voraussichtliche Nutzung erstellen.

Löschen Sie die erstellten Ressourcen nach Abschluss dieser Anleitung, um weitere Kosten zu vermeiden. Weitere Informationen finden Sie unter Bereinigen.

Vorbereitung

Projekt einrichten

  1. Melden Sie sich bei Ihrem Google Cloud-Konto an. Wenn Sie mit Google Cloud noch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  4. GKE API aktivieren.

    Aktivieren Sie die API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  6. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  7. GKE API aktivieren.

    Aktivieren Sie die API

Standardeinstellungen für die Google Cloud CLI festlegen

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

  2. Laden Sie den Quellcode für diese Beispielanwendung herunter:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/batch/kueue-intro
    
  3. Legen Sie die Standardumgebungsvariablen fest:

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    

    Ersetzen Sie die folgenden Werte:

GKE-Cluster erstellen

  1. Erstellen Sie einen GKE Autopilot-Cluster mit dem Namen kueue-autopilot:

    gcloud container clusters create-auto kueue-autopilot \
      --release-channel "rapid" --region COMPUTE_REGION
    

    Autopilot-Cluster werden vollständig verwaltet und haben integriertes Autoscaling. Weitere Informationen zu GKE-Autopilot.

    Kueue unterstützt auch Standard-GKE mit automatischer Knotenbereitstellung und regulären automatisch skalierten Knotenpools.

    Das Ergebnis sieht nach der Erstellung des Clusters in etwa so aus:

      NAME: kueue-autopilot
      LOCATION: us-central1
      MASTER_VERSION: 1.26.2-gke.1000
      MASTER_IP: 35.193.173.228
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.26.2-gke.1000
      NUM_NODES: 3
      STATUS: RUNNING
    

    Dabei ist STATUS gleich RUNNING für den kueue-autopilot.

  2. Authentifizierungsdaten für den Cluster abrufen:

    gcloud container clusters get-credentials kueue-autopilot
    
  3. Installieren Sie Kueue im Cluster:

    VERSION=VERSION
    kubectl apply --server-side -f \
      https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

    Ersetzen Sie VERSION durch die neueste Version von Kueue. Weitere Informationen zu Kueue-Versionen finden Sie unter Kueue-Releases.

  4. Warten Sie, bis die Kueue-Pods bereit sind:

    watch kubectl -n kueue-system get pods
    

    Die Ausgabe sollte in etwa so aussehen, bevor Sie fortfahren können:

    NAME                                        READY   STATUS    RESTARTS   AGE
    kueue-controller-manager-66d8bb946b-wr2l2   2/2     Running   0          3m36s
    
  5. Erstellen Sie zwei neue Namespaces mit den Namen team-a und team-b:

    kubectl create namespace team-a
    kubectl create namespace team-b
    

ResourceFlavor erstellen

Ein ResourceFlavor ist ein Objekt, das die Varianten der Knoten in Ihrem Cluster darstellt, indem sie mit Knotenlabels und Markierungen verknüpft werden. Sie können mit ResourceFlavors beispielsweise VMs mit unterschiedlichen Garantien (z. B. Spot im Vergleich zu On-Demand), Architekturen (z. B. x86 im Vergleich zu ARM-CPUs), Marken und Modellen (z. B. Nvidia A100 im Vergleich zu T4-GPUs) darstellen.

In dieser Anleitung hat der Cluster kueue-autopilot homogene Ressourcen. Erstellen Sie daher ein einzelnes ResourceFlavor für CPU, Arbeitsspeicher, sitzungsspezifischen Speicher und GPUs ohne Labels oder Markierungen.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: default-flavor # This ResourceFlavor will be used for all the resources
Stellen Sie das ResourceFlavor bereit:

kubectl apply -f flavors.yaml

ClusterQueue erstellen

Eine ClusterQueue ist ein clusterbezogenes Objekt, das einen Pool von Ressourcen wie CPU, Arbeitsspeicher und GPU verwaltet. Es verwaltet die ResourceFlavors und begrenzt die Nutzung und legt die Reihenfolge fest, in der Arbeitslasten zugelassen werden.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: cluster-queue
spec:
  namespaceSelector: {} # Available to all namespaces
  queueingStrategy: BestEffortFIFO # Default queueing strategy
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu", "ephemeral-storage"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 10
      - name: "memory"
        nominalQuota: 10Gi
      - name: "nvidia.com/gpu"
        nominalQuota: 10
      - name: "ephemeral-storage"
        nominalQuota: 10Gi

ClusterQueue bereitstellen:

kubectl apply -f cluster-queue.yaml

Die Reihenfolge der Nutzung wird durch .spec.queueingStrategy bestimmt, wobei es zwei Konfigurationen gibt:

  • BestEffortFIFO

    • Die Standardkonfiguration der Warteschlangenstrategie.
    • Die Aufnahme von Arbeitslasten erfolgt nach der FIFO-Regel (first in first out). Wenn jedoch das Kontingent nicht ausreicht, um die Arbeitslast am Anfang der Warteschlange aufzunehmen, wird die nächste in der Reihe versucht.
  • StrictFIFO

    • Garantiert FIFO-Semantik.
    • Eine Arbeitslast an der Spitze der Warteschlange kann die Warteschlange blockieren, bis die Arbeitslast zugelassen werden kann.

In cluster-queue.yaml erstellen Sie eine neue ClusterQueue mit dem Namen cluster-queue. Diese ClusterQueue verwaltet die vier Ressourcen cpu, memory, nvidia.com/gpu und ephemeral-storage mit dem in flavors.yaml erstellten Flavor. Das Kontingent wird für die Anfragen in den Pod-Spezifikationen der Arbeitslast verbraucht.

Für jede Variante werden Nutzungslimits als .spec.resourceGroups[].flavors[].resources[].nominalQuota angegeben. In diesem Fall lässt die ClusterQueue Arbeitslasten nur dann zu, wenn:

  • Die Summe der CPU-Anfragen ist kleiner oder gleich 10.
  • Die Summe der Speicheranfragen ist kleiner oder gleich 10 Gi.
  • Die Summe der GPU-Anfragen ist kleiner oder gleich 10
  • Die Summe des verwendeten Speichers ist kleiner oder gleich 10 Gi.

LocalQueue erstellen

Eine LocalQueue ist ein Namespace-Objekt, das Arbeitslasten von Nutzern im Namespace akzeptiert. LocalQueues aus verschiedenen Namespaces können auf dieselbe ClusterQueue verweisen, wo sie das Kontingent der Ressourcen gemeinsam nutzen können. In diesem Fall verweist LocalQueue aus dem Namespace team-a und team-b auf dieselbe ClusterQueue cluster-queue unter .spec.clusterQueue.

apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: team-a # LocalQueue under team-a namespace
  name: lq-team-a
spec:
  clusterQueue: cluster-queue # Point to the ClusterQueue
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: team-b # LocalQueue under team-b namespace
  name: lq-team-b
spec:
  clusterQueue: cluster-queue # Point to the ClusterQueue

Jedes Team sendet seine Arbeitslasten an die LocalQueue in seinem eigenen Namespace. Diesen werden dann von der ClusterQueue Ressourcen zugewiesen.

LocalQueues bereitstellen:

kubectl apply -f local-queue.yaml

Jobs erstellen und zugelassene Arbeitslasten beobachten

apiVersion: batch/v1
kind: Job
metadata:
  namespace: team-a # Job under team-a namespace
  generateName: sample-job-team-a-
  annotations:
    kueue.x-k8s.io/queue-name: lq-team-a # Point to the LocalQueue
spec:
  ttlSecondsAfterFinished: 60 # Job will be deleted after 60 seconds
  parallelism: 3 # This Job will have 3 replicas running at the same time
  completions: 3 # This Job requires 3 completions
  suspend: true # Set to true to allow Kueue to control the Job when it starts
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-accelerator: "nvidia-tesla-t4" # Specify the GPU hardware
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:latest
        args: ["10s"] # Sleep for 10 seconds
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
            ephemeral-storage: "512Mi"
            nvidia.com/gpu: "1"
          limits:
            cpu: "500m"
            memory: "512Mi"
            ephemeral-storage: "512Mi"
            nvidia.com/gpu: "1"
      restartPolicy: Never

Jobs werden unter dem Namespace team-a erstellt. Dieser Job verweist auf die LocalQueue lq-team-a. Zum Anfordern von GPU-Ressourcen wird nodeSelector auf nvidia-tesla-t4 gesetzt.

Der Job besteht aus drei Pods, die parallel zehn Sekunden lang in den Ruhemodus wechseln. Jobs werden entsprechend ttlSecondsAfterFinished nach 60 Sekunden bereinigt.

Für diesen Job sind 1.500 MilliCPU, 1.536 Mi Arbeitsspeicher, 1.536 Mi sitzungsspezifischer Speicher und drei GPUs erforderlich, da es drei Pods gibt.

Jobs werden auch unter der Datei job-team-b.yaml erstellt, deren Namespace zu team-b gehört, mit Anfragen, die verschiedene Teams mit unterschiedlichen Bedürfnissen repräsentieren.

Weitere Informationen finden Sie unter GPU-Arbeitslasten in Autopilot bereitstellen.

  1. Beobachten Sie in einem neuen Terminal den Status der ClusterQueue, die alle zwei Sekunden aktualisiert wird:

    watch -n 2 kubectl get clusterqueue cluster-queue -o wide
    
  2. Beobachten Sie in einem neuen Terminal den Status der Knoten:

    watch -n 2 kubectl get nodes -o wide
    
  3. Erstellen Sie in einem neuen Terminal alle 10 Sekunden Jobs aus dem Namespace team-a und team-b für die LocalQueue:

    ./create_jobs.sh job-team-a.yaml job-team-b.yaml 10
    
  4. Beobachten Sie, wie Jobs in die Warteschlange gestellt und in der ClusterQueue zugelassen werden und wie Knoten mit GKE Autopilot erstellt werden.

  5. Rufen Sie einen Job aus dem Namespace team-a ab:

    kubectl -n team-a get jobs
    

    Die Ausgabe sieht in etwa so aus:

    NAME                      COMPLETIONS   DURATION   AGE
    sample-job-team-b-t6jnr   3/3           21s        3m27s
    sample-job-team-a-tm7kc   0/3                      2m27s
    sample-job-team-a-vjtnw   3/3           30s        3m50s
    sample-job-team-b-vn6rp   0/3                      40s
    sample-job-team-a-z86h2   0/3                      2m15s
    sample-job-team-b-zfwj8   0/3                      28s
    sample-job-team-a-zjkbj   0/3                      4s
    sample-job-team-a-zzvjg   3/3           83s        4m50s
    
  6. Kopieren Sie einen Jobnamen aus dem vorherigen Schritt und beobachten Sie den Zulassungsstatus und die Ereignisse für einen Job über die Workloads API:

    kubectl -n team-a describe workload JOB_NAME
    
  7. Wenn die ausstehenden Jobs von der ClusterQueue-Ressource zunehmen, beenden Sie das Script, indem Sie im ausgeführten Script CTRL + C drücken.

  8. Beachten Sie, dass die Knoten herunterskaliert werden, nachdem alle Jobs abgeschlossen sind.

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.

Projekt löschen

  1. Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Einzelne Ressource löschen

  1. Das Kueue-Kontingentsystem löschen:

    kubectl delete -n team-a localqueue lq-team-a
    kubectl delete -n team-b localqueue lq-team-b
    kubectl delete clusterqueue cluster-queue
    kubectl delete resourceflavor default-flavor
    
  2. Das Kueue-Manifest löschen:

    VERSION=VERSION
    kubectl delete -f \
      https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    
  3. Löschen Sie den Cluster:

    gcloud container clusters delete kueue-autopilot --region=COMPUTE_REGION
    

Nächste Schritte