Apri l'implementazione di riferimento solo software di Distributed Cloud per l'erogazione del modello

Panoramica

Questo documento funge da guida per l'implementazione di riferimento della soluzione (SRI), che descrive i passaggi concreti necessari per eseguire il deployment, l'erogazione e la convalida della soluzione Open Model Serving on Distributed Cloud solo software.

Questa guida implementa il deployment del motore di serving vLLM ottimizzato che esegue Gemma 4 (google/gemma-4-31B-it) in una configurazione del cluster a nodo singolo solo software Distributed Cloud destinata al deployment perimetrale utilizzando risorse GPU NVIDIA fisiche (ad es. RTX PRO 6000).

Questa procedura dettagliata è progettata per essere eseguita da un client terminale CLI con accesso kubectl al cluster solo software Distributed Cloud.

Obiettivi

Completando questa implementazione di riferimento della soluzione, potrai:

  • Configura i parametri dell'ambiente di pubblicazione tramite un file .env locale.
  • Esegui il deployment di una richiesta di volume permanente (PVC) utilizzando la classe di archiviazione local-shared per rendere persistenti i pesi del modello.
  • Esegui il deployment del motore di serving vLLM ottimizzato utilizzando i container qualificati per Vertex AI, mappando le risorse fisiche nvidia.com/gpu.
  • Esegui il deployment della UI web di Gradio per fornire un'interfaccia di chat interattiva.
  • Crea tunnel di port forwarding locale per convalidare la reattività della pubblicazione tramite API e interfaccia utente web.
  • Verifica l'integrazione dell'osservabilità confermando l'importazione di log e metriche (inclusa la telemetria della GPU) in Cloud Logging e Cloud Monitoring.

Prima di iniziare

Prerequisiti (configurazione del cluster)

Questa guida presuppone che tu abbia un cluster software Distributed Cloud solo in esecuzione con il supporto GPU configurato. Per installare il cluster, consulta la documentazione ufficiale di Distributed Cloud (solo software) per bare metal. La configurazione della GPU deve essere conforme alla documentazione ufficiale Google Cloud per Configurare e utilizzare le GPU NVIDIA.

Prerequisiti della workstation client

Assicurati che nel tuo ambiente terminale locale siano installati e configurati i seguenti strumenti:

  • gcloud CLI:necessaria per la configurazione del progetto e l'esecuzione di query sui log. Deve essere autenticato (gcloud auth login) e configurato per il progettoGoogle Cloud attivo in cui è registrato il cluster solo software Distributed Cloud.
  • kubectl: necessario per gestire le risorse del cluster. Deve essere configurato con il contesto appropriato per accedere al cluster software Distributed Cloud di destinazione (ad es. tramite gateway di connessione o accesso diretto alla rete locale).
  • curl:obbligatorio per l'invio di richieste di test all'endpoint di pubblicazione.
  • jq: obbligatorio per analizzare l'output JSON dell'endpoint di pubblicazione.

Accesso al modello Hugging Face

Per scaricare ed eseguire il deployment del modello Gemma 4, devi avere accesso al repository Hugging Face:

  1. Account Hugging Face:assicurati di avere un account registrato su Hugging Face.
  2. Accetta la licenza del modello:vai alla pagina del modello Gemma 4 31B IT e accetta i termini di licenza per accedere ai pesi del modello controllato.
  3. Genera token di accesso:genera un token di accesso utente con autorizzazioni di lettura dalle impostazioni dell'account Hugging Face (Impostazioni -> Token di accesso). Questo token verrà utilizzato come HF_TOKEN nella configurazione.

Configurazione di riferimento centrale

Tutti i parametri di deployment vengono gestiti tramite un file .env centrale che si trova in <local-config-dir>/.env. Assicurati che questo file esista e contenga i tuoi parametri specifici (token Hugging Face, spazio dei nomi, nome del modello e così via).

Struttura .env di esempio:

# GDCso Cluster Namespace
NAMESPACE_NAME="your-custom-namespace"

# Hugging Face Token (Required to download gated Gemma models)
HF_TOKEN="your-hf-token-here"

# Model Sizing Parameters
MODEL_NAME="google/gemma-4-31B-it"
SAFE_MODEL_NAME="google-gemma-4-31B-it"

# Hyperparameters
MAX_MODEL_LEN=8192
GPU_MEMORY_UTILIZATION=0.95
MAX_NUM_SEQS=512
MAX_NUM_BATCHED_TOKENS=4096
DTYPE="bfloat16"

# Pod Sizing Requests
CPU_REQUEST="4"
MEMORY_REQUEST="80"

Configura l'ambiente e le credenziali

Crea lo spazio dei nomi e il secret di Hugging Face

Prima del deployment, devi creare lo spazio dei nomi e il secret del token Hugging Face:

# Navigate to your project root
cd <local-working-dir>

# Sourced from your local .env file
source <local-config-dir>/.env

# Create namespace
kubectl create namespace ${NAMESPACE_NAME} --dry-run=client -o yaml | kubectl apply -f -

# Create Hugging Face token secret
kubectl create secret generic hf-token-secret \
  --from-literal=token="${HF_TOKEN}" \
  -n "${NAMESPACE_NAME}" --dry-run=client -o yaml | kubectl apply -f -

Deployment di vLLM su Kubernetes

Il deployment è costituito da tre manifest principali: PVC, Service e Deployment. Questi modelli utilizzano variabili di ambiente sostituite al momento del deployment.

Richiesta di volume permanente (PVC)

Il PVC garantisce la persistenza dei pesi del modello nei riavvii dei pod, utilizzando solo la classe di archiviazione local-shared del software Distributed Cloud.

Crea un file denominato vllm-pvc.yaml con i seguenti contenuti:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: model-cache-pvc
  namespace: ${NAMESPACE_NAME}
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-shared
  resources:
    requests:
      storage: 100Gi

Servizio

Espone internamente il server API vLLM sulla porta 8000.

Crea un file denominato vllm-service.yaml con i seguenti contenuti:

apiVersion: v1
kind: Service
metadata:
  name: vllm-service
  namespace: ${NAMESPACE_NAME}
  labels:
    app: vllm
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/path: "/metrics"
    prometheus.io/port: "8000"
spec:
  ports:
    - name: http
      port: 8000
      targetPort: 8000
  selector:
    app: vllm
  type: ClusterIP

Deployment

Esegue il container vLLM, monta il volume della cache del modello e richiede risorse GPU fisiche. Sebbene 96 GB di VRAM siano sufficienti per i pesi BF16 non quantizzati (~62 GB), questa implementazione di riferimento consente la quantizzazione FP8 di Blackwell (--quantization=fp8, pesi di circa 31 GB) per espandere la cache KV a 56,53 GiB (61,728 token) per una maggiore velocità effettiva simultanea.

Crea un file denominato vllm-deployment.yaml con i seguenti contenuti:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-deployment
  namespace: ${NAMESPACE_NAME}
  labels:
    app: vllm
    ai.gke.io/inference-server: vllm
    ai.gke.io/model: ${SAFE_MODEL_NAME}
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
        examples.ai.gke.io/source: user-guide
        ai.gke.io/inference-server: vllm
        ai.gke.io/model: ${SAFE_MODEL_NAME}
    spec:
      runtimeClassName: nvidia
      containers:
        - name: vllm-container
          image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:gemma4
          imagePullPolicy: IfNotPresent
          command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
          args:
            - --model=$(MODEL_ID)
            - --host=0.0.0.0
            - --port=8000
            - --tensor-parallel-size=1
            - --enable-log-requests
            - --max-model-len=${MAX_MODEL_LEN}
            - --gpu-memory-utilization=${GPU_MEMORY_UTILIZATION}
            - --max-num-seqs=${MAX_NUM_SEQS}
            - --max-num-batched-tokens=${MAX_NUM_BATCHED_TOKENS}
            - --dtype=${DTYPE}
            - --trust-remote-code
            - --enable-prefix-caching
            - --enable-chunked-prefill
            - --quantization=fp8
          env:
            - name: MODEL_ID
              value: ${MODEL_NAME}
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-token-secret
                  key: token
            - name: LD_LIBRARY_PATH
              value: "/usr/local/nvidia/lib64"
          ports:
            - name: http
              containerPort: 8000
          resources:
            requests:
              cpu: ${CPU_REQUEST}
              memory: "${MEMORY_REQUEST}Gi"
              nvidia.com/gpu: "1"
            limits:
              cpu: ${CPU_REQUEST}
              memory: "${MEMORY_REQUEST}Gi"
              nvidia.com/gpu: "1"
          volumeMounts:
            - mountPath: /root/.cache/huggingface
              name: cache-volume
            - mountPath: /dev/shm
              name: dshm
      volumes:
        - name: cache-volume
          persistentVolumeClaim:
            claimName: model-cache-pvc
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: 16Gi

Deployment dell'interfaccia utente di Gradio

La UI di Gradio fornisce un'interfaccia web interattiva per chattare con il modello. Viene deployato all'interno del cluster e si connette al servizio vLLM tramite la rete Kubernetes interna.

Deployment di Gradio

Crea un file denominato gradio-deployment.yaml con i seguenti contenuti:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gradio-deployment
  namespace: ${NAMESPACE_NAME}
  labels:
    app: gradio
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gradio
  template:
    metadata:
      labels:
        app: gradio
    spec:
      containers:
      - name: gradio
        image: us-docker.pkg.dev/google-samples/containers/gke/gradio-app:v1.0.4
        resources:
          requests:
            cpu: "250m"
            memory: "512Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        env:
        - name: CONTEXT_PATH
          value: "/v1/chat/completions"
        - name: HOST
          value: "http://vllm-service:8000"
        - name: MODEL_ID
          value: "${MODEL_NAME}"
        ports:
        - containerPort: 7860

Servizio Gradio

Crea un file denominato gradio-service.yaml con i seguenti contenuti:

apiVersion: v1
kind: Service
metadata:
  name: gradio-service
  namespace: ${NAMESPACE_NAME}
spec:
  selector:
    app: gradio
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 7860
  type: ClusterIP

Configurazione dell'osservabilità

Per informazioni dettagliate sulla configurazione del logging e del monitoraggio delle applicazioni, consulta la guida ufficiale Logging e monitoraggio delle applicazioni.

Monitoraggio vLLM

Per abilitare lo scraping delle metriche vLLM da parte di Google Cloud Managed Service per Prometheus (GMP), implementiamo una risorsa PodMonitoring che ha come target i pod vLLM.

Crea un file denominato vllm-pod-monitoring.yaml con i seguenti contenuti:

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: vllm-pod-monitoring
  namespace: ${NAMESPACE_NAME}
spec:
  selector:
    matchLabels:
      app: vllm
  endpoints:
  - port: http
    interval: 30s

Monitoraggio della GPU

Per abilitare lo scraping delle metriche GPU da NVIDIA DCGM Exporter da parte di Google Cloud Managed Service per Prometheus (GMP), implementiamo una risorsa PodMonitoring nello spazio dei nomi gpu-operator. Per maggiori dettagli, consulta Inviare metriche GPU a Cloud Monitoring.

Crea un file denominato gpu-pod-monitoring.yaml con i seguenti contenuti:

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: dcgm-gmp
  namespace: gpu-operator
spec:
  selector:
    matchLabels:
      app: nvidia-dcgm-exporter
  endpoints:
  - port: metrics
    interval: 30s

Passaggi di esecuzione

Esegui il deployment dei manifest

Applica i manifest al cluster. Poiché i file YAML contengono segnaposto per le variabili di ambiente, utilizza envsubst per sostituire le variabili del file .env prima di applicarle.

  1. Vai alla directory di lavoro contenente i file YAML:

    cd <local-working-dir>
    
  2. Recupera le variabili di ambiente:

    source <local-config-dir>/.env
    
  3. Applica i manifest in sequenza:

    # Apply core serving manifests
    envsubst < vllm-pvc.yaml | kubectl apply -f -
    envsubst < vllm-service.yaml | kubectl apply -f -
    envsubst < vllm-deployment.yaml | kubectl apply -f -
    
    # Apply observability manifests
    envsubst < vllm-pod-monitoring.yaml | kubectl apply -f -
    kubectl apply -f gpu-pod-monitoring.yaml
    
    # Apply Gradio UI manifests
    envsubst < gradio-deployment.yaml | kubectl apply -f -
    envsubst < gradio-service.yaml | kubectl apply -f -
    

Verifica

Monitora la sequenza di avvio del pod

Trasmetti in streaming i log del container per monitorare la sequenza di avvio:

# 1. Check pod status (wait until it is Running)
kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm

# 2. Stream logs to verify model loading
kubectl logs -f -l app=vllm -n ${NAMESPACE_NAME}

Attendi finché non viene visualizzato l'indicatore di pubblicazione attiva nei log:

INFO: Application startup complete.

Stabilisci il tunnel di port forwarding

Per testare l'endpoint localmente, inoltra la porta del servizio 8000:

kubectl port-forward service/vllm-service 8000:8000 -n ${NAMESPACE_NAME}

Tieni aperto questo terminale o eseguilo in background.

Endpoint di pubblicazione delle query

Da un terminale separato, testa la reattività dell'API:

1. Elenco dei modelli di query

curl -s http://localhost:8000/v1/models | jq

2. Query completamenti chat

curl -s http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "'"${MODEL_NAME}"'",
    "messages": [
      {"role": "user", "content": "What is AGI in 100 words"}
    ],
    "max_tokens": 150
  }' | jq

Verifica le allocazioni di GPU e VRAM

Per assicurarti che il modello utilizzi l'hardware in modo efficiente e che l'impronta di memoria sia corretta, puoi eseguire un controllo della GPU.

Controlla la GPU tramite nvidia-smi all'interno del pod

Recupera il nome del pod vLLM attivo ed esegui nvidia-smi all'interno del container:

# Dynamically get the pod name
export VLLM_POD_NAME=$(kubectl get pods -n ${NAMESPACE_NAME} -l app=vllm -o jsonpath='{.items[0].metadata.name}')

# Run nvidia-smi inside the container
kubectl exec ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} -- nvidia-smi

Output previsto: l'output deve indicare l'utilizzo della VRAM fisica corrispondente al parametro GPU_MEMORY_UTILIZATION. Ad esempio, su una workstation con una NVIDIA RTX PRO 6000 (circa 96 GB di VRAM) che esegue google/gemma-4-31B-it con GPU_MEMORY_UTILIZATION=0.95, dovresti vedere circa 95. 800 MiB allocati a VLLM::EngineCore:

+-----------------------------------------------------------------------------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA RTX PRO 6000 Blac...    On  |   00000000:05:00.0 Off |                    0 |
| N/A   36C    P0             85W /  600W |   95805MiB /  97887MiB |      0%      Default |
+-----------------------------------------+------------------------+----------------------+

Verifica l'allocazione della KV cache nei log

Puoi anche controllare i log di allocazione interni di vLLM per verificare le dimensioni della cache KV e la concorrenza dei token:

kubectl logs ${VLLM_POD_NAME} -n ${NAMESPACE_NAME} | grep -E "Available KV cache|GPU KV cache size"

Output previsto:

(EngineCore pid=362) INFO 06-18 15:03:43 [gpu_worker.py:456] Available KV cache memory: 56.53 GiB
(EngineCore pid=362) INFO 06-18 15:03:43 [kv_cache_utils.py:1316] GPU KV cache size: 61,728 tokens

Ciò conferma che 56,53 GiB di VRAM sono riservati alla cache KV contestuale, consentendo un numero elevato di token simultanei.

Verifica il deployment della UI di Gradio

Una volta in esecuzione, puoi accedere alla UI del pod Gradio stabilendo un tunnel di port forwarding.

Monitorare lo stato del pod Gradio

Assicurati che il pod Gradio sia in esecuzione:

kubectl get pods -n ${NAMESPACE_NAME} -l app=gradio

Output previsto:

NAME                                READY   STATUS    RESTARTS   AGE
gradio-deployment-yyyyyyyy-yyyyy    1/1     Running   0          1m

Stabilisci il tunnel di port forwarding a Gradio

Esegui il port forwarding della porta 8080 del servizio Gradio alla porta locale 7860:

kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME}

Tieni aperto questo terminale o esegui il comando in background:

kubectl port-forward service/gradio-service 7860:8080 -n ${NAMESPACE_NAME} > pf_gradio.log 2>&1 & sleep 3

Accedere all'interfaccia utente web

  • Se l'applicazione viene eseguita su una workstation locale: apri il browser e vai direttamente a: http://localhost:7860
  • Se l'app viene eseguita in Cloud Shell:utilizza il pulsante Anteprima web, seleziona Cambia porta, inserisci 7860 e fai clic su Cambia e visualizza anteprima.

Dovresti visualizzare l'interfaccia del chatbot Gradio. Puoi digitare un messaggio per interagire con il modello Gemma. Il pod Gradio indirizzerà la richiesta internamente all'endpoint vllm-service.

Liberare spazio nei tunnel

Per interrompere il tunnel di port forwarding:

pkill -f "port-forward service/gradio-service"

Verifica del monitoraggio

Una volta eseguito il deployment di vLLM e applicata la risorsa PodMonitoring, puoi verificare che le metriche vengano importate in Cloud Monitoring.

Verifica lo stato di PodMonitoring

Assicurati che la risorsa PodMonitoring sia creata e attiva:

kubectl get podmonitoring -n ${NAMESPACE_NAME}

Verifica l'importazione delle metriche utilizzando la console Google Cloud

Puoi verificare che le metriche vengano importate utilizzando la console Google Cloud (Metrics Explorer):

  1. Apri Esplora metriche nella console Google Cloud :
    • Vai a https://console.cloud.google.com/monitoring/metrics-explorer (assicurati di selezionare il tuo progetto ${GCP_PROJECT_ID}).
  2. Nel menu a discesa Seleziona una metrica, cerca e seleziona:
    • prometheus.googleapis.com/vllm:num_requests_running/gauge per verificare le metriche vLLM.
    • prometheus.googleapis.com/DCGM_FI_DEV_GPU_UTIL/gauge per verificare le metriche di utilizzo della GPU.
  3. Osserva il grafico per verificare che i punti dati vengano tracciati attivamente.

Verifica della registrazione

Una volta eseguito il workload, puoi verificare che i log vengano esportati in Cloud Logging.

Verificare l'importazione dei log vLLM

Verifica che i log dei container vLLM vengano esportati in Cloud Logging:

project_id=$(gcloud config get-value project)

gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"${NAMESPACE_NAME}\" AND resource.labels.container_name=\"vllm-container\"" --limit=10 --project=${project_id}

Verifica l'importazione dei log dell'esportatore GPU

Verifica che i log del container dell'esportatore GPU vengano esportati in Cloud Logging:

project_id=$(gcloud config get-value project)

gcloud logging read "resource.type=\"k8s_container\" AND resource.labels.namespace_name=\"gpu-operator\" AND resource.labels.container_name=\"nvidia-dcgm-exporter\"" --limit=10 --project=${project_id}

Verificare i log utilizzando la console Google Cloud (Esplora log)

Puoi anche verificare l'importazione dei log utilizzando la console Google Cloud :

  1. Apri Esplora log nella console Google Cloud :
    • Vai a https://console.cloud.google.com/logs/query (assicurati di selezionare il tuo progetto ${GCP_PROJECT_ID}).
  2. Nella casella Query, inserisci la seguente query per visualizzare i log vLLM:

    resource.type="k8s_container"
    resource.labels.namespace_name="<NAMESPACE_NAME>"
    resource.labels.container_name="vllm-container"
    

    (sostituisci <NAMESPACE_NAME> con il tuo spazio dei nomi effettivo, ad esempio your-custom-namespace).

  3. Fai clic su Esegui query. Dovresti visualizzare le voci di log del contenitore vLLM.

  4. Per verificare i log dell'esportatore GPU, esegui questa query:

    resource.type="k8s_container"
    resource.labels.namespace_name="gpu-operator"
    resource.labels.container_name="nvidia-dcgm-exporter"