Llama 3.1 405B in GKE mit PD-Disaggregation mithilfe von Dynamo und SGLang auf A4-VMs bereitstellen

In dieser Anleitung erfahren Sie, wie Sie Llama 3.1 405B (nvidia/Llama-3.1-405B-Instruct-FP8), ein auf FP8 quantisiertes, auf Anweisungen abgestimmtes Modell mit 405 Milliarden Parametern, in Google Kubernetes Engine (GKE) auf Google Cloudbereitstellen und bereitstellen. Für die Bereitstellung werden das Cluster Toolkit, zwei virtuelle A4-Maschinen (a4-highgpu-8g) mit insgesamt 16 NVIDIA B200-GPUs, NVIDIA Dynamo und das SGLang-Serving-Framework mit Single-Host-Prefill-Decode-Disaggregation (PD) verwendet.

In der in dieser Anleitung beschriebenen Bereitstellungskonfiguration verwenden Sie das Cluster Toolkit, um einen GKE-Cluster im Standardmodus bereitzustellen. Der Cluster enthält zwei a4-highgpu-8g-Knoten, die über ein GPUDirect-RDMA-Netzwerk (Remote Direct Memory Access) verbunden sind. Anschließend installieren Sie den KAI-Scheduler und die NVIDIA Dynamo-Plattform mit Grove-Gang-Scheduling. Schließlich stellen Sie eine benutzerdefinierte Ressource vom Typ „DynamoGraphDeployment“ bereit, die Prefill und Decodierung auf zwei Single-Host-Worker mit acht GPUs mit Tensorparallelität und einem FP8-KV-Cache aufteilt.

Ziele

  • Cluster Toolkit installieren und einen A4-GKE-Cluster mit zwei Knoten im Standardmodus bereitstellen.
  • Installieren Sie den KAI-Scheduler und die NVIDIA Dynamo-Plattform mit Grove-Gang-Scheduling auf Ihrem Cluster.
  • Stellen Sie einen PD-disaggregierten SGLang-Inferenzserver mit einem A4-Prefill-Worker mit einem Host und einem A4-Decodierungs-Worker mit einem Host bereit.
  • Senden Sie eine Anfrage zur Chat-Vervollständigung an den Dynamo-Frontend-Router.
  • Führen Sie eine Benchmark-Arbeitslast für die Bereitstellung aus.
  • Bereinigen Sie die bereitgestellten Ressourcen.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten vonGoogle Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung Ihrer voraussichtlichen Nutzung vornehmen.

Hinweis

Richten Sie die Umgebung für die Anleitung ein:

  1. Installieren und initialisieren Sie die Google Cloud CLI und installieren Sie kubectl und Helm (Version 3.10 oder höher). Wenn Sie Cloud Shell verwenden, sind diese Tools vorinstalliert.
  2. Wenn Sie diese Anleitung auf einer Linux- oder macOS-Workstation statt in Cloud Shell ausführen, installieren Sie die erforderlichen Cluster Toolkit-Abhängigkeiten wie Terraform und Git.
  3. Aktivieren Sie die Kubernetes Engine API, die Compute Engine API, die Cloud Storage API, die Identity and Access Management API, die Cloud Resource Manager API und die Service Usage API in Ihrem Google Cloud -Projekt:

    APIs aktivieren

Hugging Face-Zugriffstoken abrufen

Für diese Anleitung benötigen Sie ein Hugging Face-Zugriffstoken. Sie können sich bei Hugging Face für ein kostenloses Konto registrieren. Nachdem Sie ein Konto erstellt haben, generieren Sie ein Zugriffstoken:

  1. Klicken Sie auf der Seite Willkommen bei Hugging Face auf Ihren Konto-Avatar und wählen Sie Zugriffstokens aus.
  2. Klicken Sie auf der Seite Zugriffstokens auf Neues Token erstellen.
  3. Wählen Sie den Tokentyp Lesen aus und geben Sie einen Namen für das Token ein.
  4. Ihr Zugriffstoken wird angezeigt. Speichern Sie das Token an einem sicheren Ort.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für Ihr Projekt zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Ausführen dieser Anleitung benötigen:

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff auf Projekte, Ordner und Organisationen verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

Umgebungsvariablen einrichten

Exportieren Sie die Umgebungsvariablen, die Sie in dieser Anleitung verwenden:

export PROJECT_ID="YOUR_PROJECT_ID"
export REGION="YOUR_REGION"
export ZONE="YOUR_ZONE"
export CLUSTER_NAME="YOUR_CLUSTER_NAME"
export RESERVATION_NAME="YOUR_RESERVATION_NAME"
export GCS_BUCKET="YOUR_BUCKET_NAME"
export HF_TOKEN="YOUR_HF_TOKEN"
export CLUSTER_TOOLKIT_VERSION="v1.104.0"
export DYNAMO_RELEASE_VERSION="1.5.0"

gcloud config set project "${PROJECT_ID}"
gcloud config set billing/quota_project "${PROJECT_ID}"

Ersetzen Sie Folgendes:

  • YOUR_PROJECT_ID: die ID Ihres Projekts in Google Cloud.
  • YOUR_REGION: die Region, in der sich Ihre A4-Kapazität befindet und in der Sie Ihren Cluster bereitstellen möchten, z. B. us-central1.
  • YOUR_ZONE: die Zone, in der sich Ihre A4-Kapazität befindet, z. B. us-central1-b.
  • YOUR_CLUSTER_NAME: der Name für Ihren GKE-Cluster und die Cluster Toolkit-Bereitstellung. Verwenden Sie einen Namen mit maximal 20 Zeichen, damit die generierte Dienstkonto-ID des Knotenpools (YOUR_CLUSTER_NAME-gke-np-sa) innerhalb des IAM-Limits (Identity and Access Management) von 30 Zeichen bleibt.
  • YOUR_RESERVATION_NAME: der Name Ihrer A4-Reservierung.
  • YOUR_BUCKET_NAME: ein global eindeutiger Name für den Cloud Storage-Bucket, in dem der Terraform-Status für das Cluster Toolkit gespeichert wird.
  • YOUR_HF_TOKEN: Ihr Hugging Face-Zugriffstoken.

GKE-Cluster erstellen

Laden Sie das Cluster Toolkit herunter und stellen Sie einen GKE-Cluster im Standardmodus mit zwei a4-highgpu-8g-Knoten, GPUDirect RDMA-Netzwerk und DRA-Unterstützung bereit:

  1. Melden Sie sich in der Google Cloud CLI an und generieren Sie Standardanmeldedaten für Anwendungen für Terraform:

    gcloud auth login
    gcloud auth application-default login
  2. Laden Sie das vordefinierte Cluster Toolkit-Bundle für die in CLUSTER_TOOLKIT_VERSION (v1.104.0) angegebene Version herunter und extrahieren Sie es:

    TAG="${CLUSTER_TOOLKIT_VERSION:-v1.104.0}"
    OS="linux"
    ARCH="amd64"
    mkdir -p cluster-toolkit && curl -L "https://github.com/GoogleCloudPlatform/cluster-toolkit/releases/download/${TAG}/gcluster_bundle_${OS}_${ARCH}.tgz" | tar -xz -C cluster-toolkit

    Wenn Sie diesen Befehl unter macOS oder auf einer arm64-Workstation ausführen, legen Sie OS="mac" oder ARCH="arm64" entsprechend Ihrer Plattform fest.

  3. Erstellen Sie einen Cloud Storage-Bucket mit aktivierter Objektversionsverwaltung, um den Terraform-Zustand für Ihre Cluster Toolkit-Bereitstellung zu speichern:

    gcloud storage buckets create "gs://${GCS_BUCKET}" \
        --default-storage-class=STANDARD \
        --project="${PROJECT_ID}" \
        --location="${REGION}" \
        --uniform-bucket-level-access
    gcloud storage buckets update "gs://${GCS_BUCKET}" --versioning
  4. Erstellen Sie die Bereitstellungskonfigurationsdatei cluster-toolkit/examples/gke-a4/gke-a4-deployment.yaml für zwei a4-highgpu-8g-Knoten:

    cat <<EOF > cluster-toolkit/examples/gke-a4/gke-a4-deployment.yaml
    terraform_backend_defaults:
      type: gcs
      configuration:
        bucket: ${GCS_BUCKET}
    
    vars:
      project_id: ${PROJECT_ID}
      deployment_name: ${CLUSTER_NAME}
      region: ${REGION}
      zone: ${ZONE}
      static_node_count: 2
      authorized_cidr: 0.0.0.0/0
      reservation_affinity:
        consume_reservation_type: SPECIFIC_RESERVATION
        specific_reservations:
        - name: ${RESERVATION_NAME}
    EOF

    Standardmäßig ist die Bereitstellungsdatei so konfiguriert, dass eine bestimmte Reservierung genutzt wird. Wenn Sie keine bestimmte Reservierung haben, können Sie vor dem Bereitstellen des Clusters cluster-toolkit/examples/gke-a4/gke-a4-deployment.yaml aktualisieren, um eine alternative Nutzungsoption wie Spot-VMs oder Flex-Start-VMs zu verwenden. Eine Konfigurationsanleitung finden Sie unter GKE-Nutzungsoptionen.

  5. Wechseln Sie in das Verzeichnis cluster-toolkit, stellen Sie den GKE-Cluster mit dem Befehl gcluster deploy bereit und kehren Sie dann zu Ihrem Arbeitsverzeichnis zurück:

    cd cluster-toolkit
    ./gcluster deploy \
        -d examples/gke-a4/gke-a4-deployment.yaml \
        examples/gke-a4/gke-a4.yaml \
        --auto-approve -w
    cd ..

    Die Erstellung eines Clusters dauert etwa 20 bis 30 Minuten. Wenn Sie ./gcluster deploy ohne das Flag --auto-approve ausführen, geben Sie a ein, wenn Sie dazu aufgefordert werden, um die vorgeschlagenen Änderungen anzuwenden.

  6. Konfigurieren Sie kubectl-Anmeldedaten für die Kommunikation mit Ihrem Cluster:

    gcloud container clusters get-credentials "${CLUSTER_NAME}" \
        --location="${REGION}" \
        --project="${PROJECT_ID}"

KAI Scheduler und NVIDIA Dynamo installieren

Bereiten Sie Ihren Cluster vor, indem Sie ein Hugging Face-Secret erstellen und den KAI-Scheduler und die NVIDIA Dynamo-Plattform mit Grove-Gang-Scheduling installieren:

  1. Erstellen Sie ein Kubernetes-Secret mit dem Namen hf-secret, um Ihr Hugging Face-Zugriffstoken zu speichern:

    kubectl create secret generic hf-secret \
        --from-literal=hf_api_token="${HF_TOKEN}" \
        --dry-run=client -o yaml | kubectl apply -f -
  2. Laden Sie das Helm-Diagramm für die NVIDIA Dynamo-Plattform (v1.5.0) herunter, installieren Sie den KAI-Scheduler und installieren Sie die Dynamo-Plattform mit aktiviertem Grove:

    RELEASE_VERSION="${DYNAMO_RELEASE_VERSION:-1.5.0}"
    helm fetch "https://helm.ngc.nvidia.com/nvidia/ai-dynamo/charts/dynamo-platform-${RELEASE_VERSION}.tgz"
    tar -zxf "dynamo-platform-${RELEASE_VERSION}.tgz"
    
    helm upgrade --install kai-scheduler ./dynamo-platform/charts/kai-scheduler \
        --set scheduler.args.default-staleness-grace-period="-1s" \
        --set topologyMigration.enabled=false
    
    kubectl wait --for=condition=Available deployment/kai-operator --timeout=120s
    until kubectl get deployment/queue-controller >/dev/null 2>&1; do sleep 2; done
    kubectl wait --for=condition=Available deployment/queue-controller --timeout=120s
    
    helm upgrade --install dynamo-platform ./dynamo-platform \
        --set global.grove.install=true \
        --set global.grove.enabled=true \
        --set global.kai-scheduler.enabled=true

Disaggregierten SGLang-Server mit einem einzelnen Host bereitstellen

Das Arbeitslastmanifest (llama3.1-405b-singlehost-a4.yaml) definiert ein Kubernetes-ResourceClaimTemplate (all-mrdma), das die Multi-NIC-RDMA-Geräte (mrdma.google.com) des Knotens über DRA zuweist, und ein NVIDIA Dynamo DynamoGraphDeployment (llama3-405b-a4-disagg) mit aktiviertem Grove-Gang-Scheduling. Die Bereitstellung umfasst Folgendes:

  • Frontend (Frontend): Führt ein Router-Replikat aus, das Clientanfragen akzeptiert, registrierte Prefill- und Decodierungs-Worker erkennt und das disaggregierte Anfragerouting koordiniert.
  • Prefill-Worker (Prefill): Führt einen Single-Host-Worker auf einem a4-highgpu-8g-Knoten mit acht NVIDIA B200-GPUs aus. Beim Start bezieht der Pod die NCCL/gIB-Umgebung, lädt den nvidia/Llama-3.1-405B-Instruct-FP8-Prüfpunkt vom Hugging Face Hub auf die lokale NVMe-SSD des Knotens herunter und startet python3 -m dynamo.sglang in --disaggregation-mode prefill mit den folgenden Flags:
    • --tensor-parallel-size 8
    • --kv-cache-dtype fp8_e4m3
    • --context-length 16384
    • --mem-fraction-static 0.85
  • Decode-Worker (Decode): Führt einen Single-Host-Worker auf dem zweiten a4-highgpu-8g-Knoten mit acht NVIDIA B200-GPUs aus. Beim Start speichert der Pod die Modellgewichtungen auf der lokalen NVMe-SSD des Knotens im Cache und startet python3 -m dynamo.sglang in --disaggregation-mode decode mit den folgenden Flags:
    • --tensor-parallel-size 8
    • --kv-cache-dtype fp8_e4m3
    • --context-length 16384
    • --mem-fraction-static 0.85

Disaggregierten Inferenzserver bereitstellen und überwachen:

  1. Laden Sie das Arbeitslastmanifest llama3.1-405b-singlehost-a4.yaml herunter:

    curl -O https://raw.githubusercontent.com/GoogleCloudSamples/AIHypercomputerSamples/refs/heads/main/gpu/inference/llama3-405b/llama3.1-405b-singlehost-a4.yaml

    Alternativ können Sie eine Datei mit dem Namen llama3.1-405b-singlehost-a4.yaml und folgendem Inhalt erstellen:

    # ==============================================================================
    # Single-Host Disaggregated Serving of Llama 3.1 405B FP8 on GKE
    # using NVIDIA Dynamo Platform (v1.5.0) and SGLang on GPU A4 (2 x a4-highgpu-8g)
    # Topology: 1-node Prefill (8 x B200, TP=8) + 1-node Decode (8 x B200, TP=8)
    # ==============================================================================
    apiVersion: resource.k8s.io/v1
    kind: ResourceClaimTemplate
    metadata:
      name: all-mrdma
    spec:
      spec:
        devices:
          requests:
            - name: req-mrdma
              exactly:
                deviceClassName: mrdma.google.com
                allocationMode: All
    ---
    apiVersion: nvidia.com/v1alpha1
    kind: DynamoGraphDeployment
    metadata:
      name: llama3-405b-a4-disagg
      annotations:
        nvidia.com/enable-grove: "true"
    spec:
      backendFramework: sglang
      services:
        # --------------------------------------------------------------------------
        # FRONTEND: Dynamo OpenAI-Compatible Router (`python3 -m dynamo.frontend`)
        # --------------------------------------------------------------------------
        Frontend:
          componentType: frontend
          replicas: 1
          resources:
            requests:
              cpu: "8"
              memory: "32Gi"
            limits:
              cpu: "8"
              memory: "32Gi"
          extraPodSpec:
            tolerations:
              - key: "nvidia.com/gpu"
                operator: "Exists"
                effect: "NoSchedule"
            mainContainer:
              image: nvcr.io/nvidia/ai-dynamo/sglang-runtime:1.5.0
              command: ["/bin/bash", "-c"]
              args:
                - |
                  set -ex
                  exec python3 -m dynamo.frontend --http-port 8000
    
        # --------------------------------------------------------------------------
        # PREFILL WORKER: 1 x GPU A4 (`a4-highgpu-8g`, 8 x B200 GPUs, TP=8)
        # --------------------------------------------------------------------------
        Prefill:
          componentType: worker
          subComponentType: prefill
          replicas: 1
          livenessProbe:
            httpGet:
              path: /live
              port: system
            initialDelaySeconds: 600
            periodSeconds: 60
            timeoutSeconds: 30
            failureThreshold: 60
          readinessProbe:
            httpGet:
              path: /health
              port: system
            initialDelaySeconds: 120
            periodSeconds: 30
            timeoutSeconds: 30
            failureThreshold: 60
          sharedMemory:
            size: 128Gi
          resources:
            requests:
              gpu: "8"
              cpu: "128"
              memory: "1500Gi"
            limits:
              gpu: "8"
              cpu: "128"
              memory: "2000Gi"
          envs:
            - name: MODEL_PATH
              value: "nvidia/Llama-3.1-405B-Instruct-FP8"
            - name: HF_HOME
              value: "/data"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
                  optional: true
            - name: DYN_SYSTEM_ENABLED
              value: "true"
            - name: DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS
              value: "[\"generate\"]"
            - name: DYN_SYSTEM_PORT
              value: "9090"
            - name: LD_LIBRARY_PATH
              value: "/usr/local/gib/lib64:/usr/local/nvidia/lib64"
            - name: GLOO_SOCKET_IFNAME
              value: "eth0"
            - name: WITH_NVIDIA_PEERMEM
              value: "0"
            # Xet CAS downloads returned unretried 429s; plain HTTP downloads back off on 429.
            - name: HF_HUB_DISABLE_XET
              value: "1"
          extraPodSpec:
            resourceClaims:
              - name: rdma
                resourceClaimTemplateName: all-mrdma
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-b200
              cloud.google.com/gke-gpu: "true"
              kubernetes.io/arch: amd64
            tolerations:
              - key: "nvidia.com/gpu"
                operator: "Exists"
                effect: "NoSchedule"
              - key: "kubernetes.io/arch"
                operator: "Equal"
                value: "amd64"
                effect: "NoSchedule"
            mainContainer:
              image: nvcr.io/nvidia/ai-dynamo/sglang-runtime:1.5.0
              resources:
                claims:
                  - name: rdma
              startupProbe:
                httpGet:
                  path: /live
                  port: system
                initialDelaySeconds: 120
                periodSeconds: 30
                timeoutSeconds: 10
                failureThreshold: 120
              command: ["/bin/bash", "-c"]
              args:
                - |
                  set -ex
                  if [ -f /usr/local/gib/scripts/set_nccl_env.sh ]; then
                    . /usr/local/gib/scripts/set_nccl_env.sh
                  fi
    
                  # Pre-download with huggingface_hub, which backs off on HTTP 429s. Dynamo's built-in
                  # downloader (ModelExpress) aborts on the first 429 and skips fetching if weights are cached.
                  echo "=== [Dynamo Prefill Worker] Ensuring weights are cached in ${HF_HOME:-/data} ==="
                  python3 -c "import os; from huggingface_hub import snapshot_download; snapshot_download(os.environ['MODEL_PATH'], max_workers=16)"
                  # --host 0.0.0.0 is required so MooncakeKVBootstrapServer binds to 0.0.0.0:30001 instead of 127.0.0.1:30001.
                  echo "=== [Dynamo Prefill Worker] Launching dynamo.sglang ==="
                  exec python3 -m dynamo.sglang \
                    --model-path "${MODEL_PATH}" \
                    --host 0.0.0.0 \
                    --disaggregation-mode prefill \
                    --disaggregation-bootstrap-port 30001 \
                    --tensor-parallel-size 8 \
                    --kv-cache-dtype fp8_e4m3 \
                    --context-length 16384 \
                    --mem-fraction-static 0.85 \
                    --enable-metrics
              volumeMounts:
                - name: library-dir-host
                  mountPath: /usr/local/nvidia
                - name: gib
                  mountPath: /usr/local/gib
                - name: data-volume
                  mountPath: /data
            volumes:
              - name: library-dir-host
                hostPath:
                  path: /home/kubernetes/bin/nvidia
              - name: gib
                hostPath:
                  path: /home/kubernetes/bin/gib
              - name: data-volume
                emptyDir: {}
    
        # --------------------------------------------------------------------------
        # DECODE WORKER: 1 x GPU A4 (`a4-highgpu-8g`, 8 x B200 GPUs, TP=8)
        # --------------------------------------------------------------------------
        Decode:
          componentType: worker
          subComponentType: decode
          replicas: 1
          livenessProbe:
            httpGet:
              path: /live
              port: system
            initialDelaySeconds: 600
            periodSeconds: 60
            timeoutSeconds: 30
            failureThreshold: 60
          readinessProbe:
            httpGet:
              path: /health
              port: system
            initialDelaySeconds: 120
            periodSeconds: 30
            timeoutSeconds: 30
            failureThreshold: 60
          sharedMemory:
            size: 128Gi
          resources:
            requests:
              gpu: "8"
              cpu: "128"
              memory: "1500Gi"
            limits:
              gpu: "8"
              cpu: "128"
              memory: "2000Gi"
          envs:
            - name: MODEL_PATH
              value: "nvidia/Llama-3.1-405B-Instruct-FP8"
            - name: HF_HOME
              value: "/data"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
                  optional: true
            - name: DYN_SYSTEM_ENABLED
              value: "true"
            - name: DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS
              value: "[\"generate\"]"
            - name: DYN_SYSTEM_PORT
              value: "9090"
            - name: LD_LIBRARY_PATH
              value: "/usr/local/gib/lib64:/usr/local/nvidia/lib64"
            - name: GLOO_SOCKET_IFNAME
              value: "eth0"
            - name: WITH_NVIDIA_PEERMEM
              value: "0"
            # Xet CAS downloads returned unretried 429s; plain HTTP downloads back off on 429.
            - name: HF_HUB_DISABLE_XET
              value: "1"
          extraPodSpec:
            resourceClaims:
              - name: rdma
                resourceClaimTemplateName: all-mrdma
            nodeSelector:
              cloud.google.com/gke-accelerator: nvidia-b200
              cloud.google.com/gke-gpu: "true"
              kubernetes.io/arch: amd64
            tolerations:
              - key: "nvidia.com/gpu"
                operator: "Exists"
                effect: "NoSchedule"
              - key: "kubernetes.io/arch"
                operator: "Equal"
                value: "amd64"
                effect: "NoSchedule"
            mainContainer:
              image: nvcr.io/nvidia/ai-dynamo/sglang-runtime:1.5.0
              resources:
                claims:
                  - name: rdma
              startupProbe:
                httpGet:
                  path: /live
                  port: system
                initialDelaySeconds: 120
                periodSeconds: 30
                timeoutSeconds: 10
                failureThreshold: 120
              command: ["/bin/bash", "-c"]
              args:
                - |
                  set -ex
                  if [ -f /usr/local/gib/scripts/set_nccl_env.sh ]; then
                    . /usr/local/gib/scripts/set_nccl_env.sh
                  fi
    
                  # Pre-download with huggingface_hub, which backs off on HTTP 429s. Dynamo's built-in
                  # downloader (ModelExpress) aborts on the first 429 and skips fetching if weights are cached.
                  echo "=== [Dynamo Decode Worker] Ensuring weights are cached in ${HF_HOME:-/data} ==="
                  python3 -c "import os; from huggingface_hub import snapshot_download; snapshot_download(os.environ['MODEL_PATH'], max_workers=16)"
                  echo "=== [Dynamo Decode Worker] Launching dynamo.sglang ==="
                  exec python3 -m dynamo.sglang \
                    --model-path "${MODEL_PATH}" \
                    --host 0.0.0.0 \
                    --disaggregation-mode decode \
                    --disaggregation-bootstrap-port 30001 \
                    --tensor-parallel-size 8 \
                    --kv-cache-dtype fp8_e4m3 \
                    --context-length 16384 \
                    --mem-fraction-static 0.85 \
                    --enable-metrics
              volumeMounts:
                - name: library-dir-host
                  mountPath: /usr/local/nvidia
                - name: gib
                  mountPath: /usr/local/gib
                - name: data-volume
                  mountPath: /data
            volumes:
              - name: library-dir-host
                hostPath:
                  path: /home/kubernetes/bin/nvidia
              - name: gib
                hostPath:
                  path: /home/kubernetes/bin/gib
              - name: data-volume
                emptyDir: {}
  2. Wenden Sie das Arbeitslastmanifest auf Ihren Cluster an:

    kubectl apply -f llama3.1-405b-singlehost-a4.yaml
  3. Wenn Sie den Download der Gewichtungen und die Serverinitialisierung überwachen möchten, listen Sie die Pods in Ihrem Cluster auf und streamen Sie die Logs der Prefill- und Decode-Pods:

    kubectl get pods
    POD_NAME="YOUR_POD_NAME"
    kubectl logs -f "${POD_NAME}"

    Ersetzen Sie YOUR_POD_NAME durch den Namen des Pods für die Vorabfüllung oder des Pods für die Decodierung aus der Ausgabe von kubectl get pods.

    Beim ersten Durchlauf dauert es etwa 10 bis 20 Minuten, die 405B-FP8-Modellgewichtungen herunterzuladen und die SGLang-Server zu initialisieren. Warten Sie, bis die Pods für Frontend, Prefill und Decode in der Spalte READY von kubectl get pods den Wert 1/1 anzeigen, bevor Sie Anfragen senden:

    NAME                                        READY   STATUS    RESTARTS   AGE
    llama3-405b-a4-disagg-0-decode-tgl7q        1/1     Running   0          15m
    llama3-405b-a4-disagg-0-frontend-wrxq5      1/1     Running   0          15m
    llama3-405b-a4-disagg-0-prefill-67h5s       1/1     Running   0          15m
    

Inferenzanfragen senden

Senden Sie eine Chat-Vervollständigungsanfrage an den bereitgestellten Llama 3.1 405B-Dienst:

  1. Leiten Sie den lokalen Port 8000 an den Dienst llama3-405b-a4-disagg-frontend weiter:

    kubectl port-forward svc/llama3-405b-a4-disagg-frontend 8000:8000

    Lassen Sie die Portweiterleitung in dieser Terminalsitzung laufen oder führen Sie den Befehl im Hintergrund aus.

  2. Senden Sie in einer zweiten Terminalsitzung eine Anfrage zur Chat-Vervollständigung an den Endpunkt /v1/chat/completions:

    curl http://127.0.0.1:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "nvidia/Llama-3.1-405B-Instruct-FP8",
        "messages": [{"role": "user", "content": "Explain KV-cache disaggregation in one sentence."}],
        "max_tokens": 64
      }' | jq .

Benchmark-Arbeitslast ausführen

Führen Sie mit sglang.bench_serving einen Benchmark für den bereitgestellten Llama 3.1 405B-Server über den Dynamo-Frontend-Pod aus. Konfigurieren Sie den Benchmark für 1.024 Eingabetokens, 1.024 Ausgabetokens (1k/1k), 2.048 Prompts und eine maximale Nebenläufigkeit von 512:

ROUTER_POD=$(kubectl get pod -l 'nvidia.com/dynamo-component-type=frontend' -o jsonpath='{.items[0].metadata.name}')

kubectl exec "${ROUTER_POD}" -- python3 -m sglang.bench_serving \
  --backend sglang-oai-chat \
  --base-url http://localhost:8000 \
  --model nvidia/Llama-3.1-405B-Instruct-FP8 \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 1024 \
  --random-range-ratio 1.0 \
  --num-prompts 2048 \
  --max-concurrency 512 \
  --warmup-requests 10 | tee benchmark.log

Suchen Sie nach Abschluss des Benchmarks nach einer Ausgabe, die Messwerte wie die folgenden enthält:

  • Output token throughput
  • Total token throughput
  • TTFT
  • TPOT

Bereinigen

So vermeiden Sie, dass Ihrem Google Cloud -Konto die in dieser Anleitung verwendeten Ressourcen laufend in Rechnung gestellt werden: Löschen Sie die Kubernetes-Arbeitslasten, den GKE-Cluster und den Cloud Storage-Bucket:

  1. Löschen Sie die Ressourcen „DynamoGraphDeployment“ und „ResourceClaimTemplate“:

    kubectl delete -f llama3.1-405b-singlehost-a4.yaml --ignore-not-found || true
  2. Deinstallieren Sie die NVIDIA Dynamo-Plattform und die KAI Scheduler Helm-Releases:

    helm uninstall dynamo-platform kai-scheduler || true
  3. Löschen Sie das Hugging Face-Kubernetes-Secret:

    kubectl delete secret hf-secret --ignore-not-found || true
  4. Löschen Sie im Verzeichnis cluster-toolkit den GKE-Cluster und die zugehörige Infrastruktur mit dem Befehl gcluster destroy:

    cd cluster-toolkit
    ./gcluster destroy "${CLUSTER_NAME}" --auto-approve || true
    cd ..
  5. Verwenden Sie den Befehl gcloud storage rm, um den Cloud Storage-Bucket zu löschen, in dem der Terraform-Zustand gespeichert ist:

    gcloud storage rm --recursive "gs://${GCS_BUCKET}"

Nächste Schritte