Gestisci Llama 3.1 405B su GKE con disaggregazione dei DP utilizzando Dynamo e SGLang su VM A4

Questo tutorial mostra come eseguire il deployment e l'erogazione di Llama 3.1 405B (nvidia/Llama-3.1-405B-Instruct-FP8), un modello con ottimizzazione delle istruzioni da 405 miliardi di parametri quantizzato in FP8, su Google Kubernetes Engine (GKE) su Google Cloud. Il deployment utilizza Cluster Toolkit, due istanze di macchine virtuali (VM) A4 (a4-highgpu-8g) con un totale di 16 GPU NVIDIA B200, NVIDIA Dynamo e il framework di distribuzione SGLang con disaggregazione prefill-decode (DP) su un singolo host.

Nella configurazione del deployment descritta in questo tutorial, utilizzi Cluster Toolkit per eseguire il provisioning di un cluster GKE in modalità Standard. Il cluster contiene due nodi a4-highgpu-8g connessi tramite rete GPUDirect accesso diretto alla memoria da remoto (RDMA). Poi installi KAI Scheduler e la piattaforma NVIDIA Dynamo con il gang scheduling di Grove. Infine, esegui il deployment di una risorsa personalizzata DynamoGraphDeployment che separa pre-riempimento e decodifica su due worker a host singolo con otto GPU con parallelismo dei tensori e una cache KV FP8.

Obiettivi

  • Installa Cluster Toolkit ed esegui il provisioning di un cluster GKE A4 a due nodi in modalità Standard.
  • Installa KAI Scheduler e la piattaforma NVIDIA Dynamo con lo scheduling di gruppo Grove sul tuo cluster.
  • Esegui il deployment di un server di inferenza SGLang disaggregato DP con un worker di pre-compilazione A4 single-host e un worker di decodifica A4 single-host.
  • Invia una richiesta di completamento della chat al router di frontend Dynamo.
  • Esegui un workload di benchmark di gestione.
  • Esegui la pulizia delle risorse di cui hai eseguito il deployment.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili diGoogle Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

Prima di iniziare

Configura l'ambiente per il tutorial:

  1. Installa e inizializza Google Cloud CLI e installa kubectl e Helm (versione 3.10 o successive). Se utilizzi Cloud Shell, questi strumenti sono preinstallati.
  2. Se esegui questo tutorial da una workstation Linux o macOS anziché da Cloud Shell, installa le dipendenze di Cluster Toolkit richieste, come Terraform e Git.
  3. Abilita l'API Kubernetes Engine, l'API Compute Engine, l'API Cloud Storage, l'API Identity and Access Management, l'API Cloud Resource Manager e l'API Service Usage nel tuo progetto Google Cloud :

    Abilita le API

Ottieni un token di accesso a Hugging Face

Per utilizzare questo tutorial, devi disporre di un token di accesso a Hugging Face. Puoi registrarti per un account senza costi su Hugging Face. Dopo aver creato un account, genera un token di accesso:

  1. Nella pagina Welcome to Hugging Face, fai clic sull'avatar del tuo account e seleziona Token di accesso.
  2. Nella pagina Token di accesso, fai clic su Crea nuovo token.
  3. Seleziona il tipo di token Lettura e inserisci un nome per il token.
  4. Viene visualizzato il token di accesso. Salva il token in un luogo sicuro.

Ruoli obbligatori

Per ottenere le autorizzazioni necessarie per completare questo tutorial, chiedi all'amministratore di concederti i seguenti ruoli IAM nel progetto:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Imposta le variabili di ambiente

Esporta le variabili di ambiente che utilizzi in questo tutorial:

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}"

Sostituisci quanto segue:

  • YOUR_PROJECT_ID: l'ID del tuo progetto Google Cloud.
  • YOUR_REGION: la regione in cui si trova la tua capacità A4 e in cui vuoi eseguire il deployment del cluster, ad esempio us-central1.
  • YOUR_ZONE: la zona in cui si trova la tua capacità A4, ad esempio us-central1-b.
  • YOUR_CLUSTER_NAME: il nome del tuo cluster GKE e del deployment di Cluster Toolkit. Utilizza un nome di massimo 20 caratteri in modo che l'ID account del service account del pool di nodi generato (YOUR_CLUSTER_NAME-gke-np-sa) rimanga entro il limite di 30 caratteri di Identity and Access Management (IAM).
  • YOUR_RESERVATION_NAME: il nome della prenotazione A4.
  • YOUR_BUCKET_NAME: un nome univoco a livello globale per il bucket Cloud Storage che archivia lo stato Terraform per Cluster Toolkit.
  • YOUR_HF_TOKEN: il tuo token di accesso a Hugging Face.

Crea il cluster GKE

Scarica Cluster Toolkit ed esegui il provisioning di un cluster GKE in modalità Standard con due nodi a4-highgpu-8g, networking GPUDirect RDMA e supporto DRA:

  1. Accedi a Google Cloud CLI e genera le Credenziali predefinite dell'applicazione per Terraform:

    gcloud auth login
    gcloud auth application-default login
  2. Scarica ed estrai il bundle Cluster Toolkit predefinito per la versione specificata in CLUSTER_TOOLKIT_VERSION (v1.104.0):

    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

    Se esegui questo comando su macOS o su una workstation arm64, imposta OS="mac" o ARCH="arm64" in modo che corrisponda alla tua piattaforma.

  3. Per archiviare lo stato di Terraform per il deployment di Cluster Toolkit, crea un bucket Cloud Storage con il controllo delle versioni degli oggetti abilitato:

    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. Crea il file di configurazione del deployment cluster-toolkit/examples/gke-a4/gke-a4-deployment.yaml per due nodi a4-highgpu-8g:

    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

    Per impostazione predefinita, il file di deployment è configurato per utilizzare una prenotazione specifica. Se non hai una prenotazione specifica, prima di eseguire il deployment del cluster, puoi aggiornare cluster-toolkit/examples/gke-a4/gke-a4-deployment.yaml in modo che utilizzi un'opzione di consumo alternativa, ad esempio VM spot o Flex-start VM. Per istruzioni sulla configurazione, consulta Opzioni di consumo di GKE.

  5. Passa alla directory cluster-toolkit, esegui il deployment del cluster GKE utilizzando il comando gcluster deploy, quindi torna alla directory di lavoro:

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

    La creazione del cluster richiede circa 20-30 minuti. Se esegui ./gcluster deploy senza il flag --auto-approve, per applicare le modifiche proposte, inserisci a quando richiesto.

  6. Configura le credenziali kubectl per comunicare con il tuo cluster:

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

Installa KAI Scheduler e NVIDIA Dynamo

Prepara il cluster creando un secret di Hugging Face e installando lo scheduler KAI e la piattaforma NVIDIA Dynamo con lo scheduling di gruppo Grove:

  1. Crea un secret di Kubernetes denominato hf-secret per archiviare il tuo token di accesso Hugging Face:

    kubectl create secret generic hf-secret \
        --from-literal=hf_api_token="${HF_TOKEN}" \
        --dry-run=client -o yaml | kubectl apply -f -
  2. Scarica il grafico Helm della piattaforma NVIDIA Dynamo (v1.5.0), installa lo scheduler KAI e installa la piattaforma Dynamo con Grove abilitato:

    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

Esegui il deployment del server SGLang disaggregato su un singolo host

Il manifest del workload (llama3.1-405b-singlehost-a4.yaml) definisce un ResourceClaimTemplate di Kubernetes (all-mrdma), che alloca i dispositivi RDMA multi-NIC del nodo (mrdma.google.com) tramite DRA, e un DynamoGraphDeployment di NVIDIA Dynamo (llama3-405b-a4-disagg) con lo scheduling di gruppo di Grove abilitato. Il deployment è costituito da quanto segue:

  • Frontend (Frontend): esegue una replica del router che accetta le richieste dei client, rileva i worker di precompilazione e decodifica registrati e coordina il routing delle richieste disaggregate.
  • Worker di precompilazione (Prefill): esegue un worker single-host su un nodo a4-highgpu-8g con otto GPU NVIDIA B200. All'avvio, il pod recupera l'ambiente NCCL/gIB, scarica il checkpoint nvidia/Llama-3.1-405B-Instruct-FP8 dall'hub Hugging Face all'SSD NVMe locale del nodo e avvia python3 -m dynamo.sglang in --disaggregation-mode prefill con i seguenti flag:
    • --tensor-parallel-size 8
    • --kv-cache-dtype fp8_e4m3
    • --context-length 16384
    • --mem-fraction-static 0.85
  • Worker di decodifica (Decode): esegue un worker single-host sul secondo nodo a4-highgpu-8g con otto GPU NVIDIA B200. All'avvio, il pod memorizza nella cache i pesi del modello sull'SSD NVMe locale del nodo e avvia python3 -m dynamo.sglang in --disaggregation-mode decode con i seguenti flag:
    • --tensor-parallel-size 8
    • --kv-cache-dtype fp8_e4m3
    • --context-length 16384
    • --mem-fraction-static 0.85

Esegui il deployment e il monitoraggio del server di inferenza disaggregato:

  1. Scarica il manifest del workload llama3.1-405b-singlehost-a4.yaml:

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

    In alternativa, crea un file denominato llama3.1-405b-singlehost-a4.yaml con i seguenti contenuti:

    # ==============================================================================
    # 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. Applica il manifest del workload al cluster:

    kubectl apply -f llama3.1-405b-singlehost-a4.yaml
  3. Per monitorare il download dei pesi e l'inizializzazione del server, elenca i pod nel tuo cluster e trasmetti in streaming i log dei pod di precompilazione e decodifica:

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

    Sostituisci YOUR_POD_NAME con il nome del pod di precompilazione o di decodifica dall'output kubectl get pods.

    Alla prima esecuzione, sono necessari circa 10-20 minuti per scaricare i pesi del modello 405B FP8 e inizializzare i server SGLang. Prima di inviare qualsiasi richiesta, attendi che i pod di frontend, precompilazione e decodifica mostrino 1/1 nella colonna READY di kubectl get pods:

    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
    

Invia richieste di inferenza

Invia una richiesta di completamento della chat al servizio Llama 3.1 405B di cui è stato eseguito il deployment:

  1. Inoltra la porta locale 8000 al servizio llama3-405b-a4-disagg-frontend:

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

    Lascia il port forwarding in esecuzione in questa sessione del terminale o esegui il comando in background.

  2. In una seconda sessione del terminale, invia una richiesta di completamento della chat all'endpoint /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 .

Esegui un workload di benchmark

Esegui il benchmark del server Llama 3.1 405B di cui è stato eseguito il deployment dal pod di frontend Dynamo utilizzando sglang.bench_serving. Configura il benchmark per 1024 token di input, 1024 token di output (1k/1k), 2048 prompt e una contemporaneità massima di 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

Al termine del benchmark, cerca un output contenente metriche come le seguenti:

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

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi aggiuntivi per le risorse utilizzate in questo tutorial, elimina i workload Kubernetes, il cluster GKE e il bucket Cloud Storage:

  1. Elimina le risorse DynamoGraphDeployment e ResourceClaimTemplate:

    kubectl delete -f llama3.1-405b-singlehost-a4.yaml --ignore-not-found || true
  2. Disinstalla le release Helm della piattaforma NVIDIA Dynamo e di KAI Scheduler:

    helm uninstall dynamo-platform kai-scheduler || true
  3. Elimina il secret Kubernetes di Hugging Face:

    kubectl delete secret hf-secret --ignore-not-found || true
  4. Dalla directory cluster-toolkit, elimina il cluster GKE e l'infrastruttura associata utilizzando il comando gcluster destroy:

    cd cluster-toolkit
    ./gcluster destroy "${CLUSTER_NAME}" --auto-approve || true
    cd ..
  5. Per eliminare il bucket Cloud Storage che archivia lo stato di Terraform, utilizza il comando gcloud storage rm:

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

Passaggi successivi