Offene Modellbereitstellung in der Referenzimplementierung von Distributed Cloud (nur Software)

Übersicht

Dieses Dokument dient als Solution Reference Implementation (SRI)-Leitfaden und beschreibt die konkreten Schritte, die zum Bereitstellen, Ausführen und Validieren der Lösung Open Model Serving on Distributed Cloud software only erforderlich sind.

In dieser Anleitung wird die Bereitstellung der optimierten vLLM-Serving-Engine mit Gemma 4 (google/gemma-4-31B-it) in einer reinen Softwarekonfiguration von Distributed Cloud implementiert, die auf eine Einzelknoten-Clusterkonfiguration für die Edge-Bereitstellung ausgerichtet ist und physische NVIDIA-GPU-Ressourcen (z.B. RTX PRO 6000) nutzt.

Diese Anleitung ist für die Ausführung über einen CLI-Terminalclient mit kubectl-Zugriff auf den Cluster mit nur Distributed Cloud-Software vorgesehen.

Ziele

Wenn Sie diese Referenzimplementierung für Lösungen durchführen, erreichen Sie Folgendes:

  • Parameter für die Bereitstellungsumgebung über eine lokale .env-Datei konfigurieren.
  • Stellen Sie einen PersistentVolumeClaim (PVC) mit der StorageClass local-shared bereit, um Modellgewichte beizubehalten.
  • Optimierte vLLM-Bereitstellungs-Engine bereitstellen mit Vertex AI-qualifizierten Containern, die physische nvidia.com/gpu-Ressourcen zuordnen.
  • Gradio-Web-UI bereitstellen, um eine interaktive Chatoberfläche zu erhalten.
  • Lokale Portweiterleitungstunnel einrichten, um die Reaktionsfähigkeit der Bereitstellung über APIs und die Web-UI zu validieren.
  • Observability-Integration prüfen, indem Sie die Aufnahme von Logs und Messwerten (einschließlich GPU-Telemetrie) in Cloud Logging und Cloud Monitoring bestätigen.

Hinweis

Voraussetzungen (Clustereinrichtung)

In diesem Leitfaden wird davon ausgegangen, dass Sie einen laufenden Cluster mit Distributed Cloud-Software only und konfigurierter GPU-Unterstützung haben. Informationen zur Installation des Clusters finden Sie in der offiziellen Dokumentation zu Distributed Cloud (nur Software) für Bare Metal. Die GPU-Konfiguration muss der offiziellen Google CloudDokumentation zum Einrichten und Verwenden von NVIDIA-GPUs entsprechen.

Voraussetzungen für Client-Workstations

Prüfen Sie, ob in Ihrer lokalen Terminalumgebung die folgenden Tools installiert und konfiguriert sind:

  • gcloud CLI:Erforderlich für die Projektkonfiguration und das Abfragen von Logs. Muss authentifiziert sein (gcloud auth login) und für das aktiveGoogle Cloud -Projekt konfiguriert sein, in dem der reine Softwarecluster von Distributed Cloud registriert ist.
  • kubectl:Erforderlich für die Verwaltung von Clusterressourcen. Muss mit dem entsprechenden Kontext konfiguriert werden, um auf den Zielcluster für Distributed Cloud-Software zuzugreifen, z.B. über ein Connect-Gateway oder direkten lokalen Netzwerkzugriff.
  • curl:Erforderlich zum Senden von Testanfragen an den Serving-Endpunkt.
  • jq:Erforderlich zum Parsen der JSON-Ausgabe des Serving-Endpunkts.

Zugriff auf Hugging Face-Modelle

Wenn Sie das Gemma 4-Modell herunterladen und bereitstellen möchten, benötigen Sie Zugriff auf das Hugging Face-Repository:

  1. Hugging Face-Konto:Sie benötigen ein registriertes Konto bei Hugging Face.
  2. Modelllizenz akzeptieren:Rufen Sie die Seite zum Gemma 4 31B IT-Modell auf und stimmen Sie den Lizenzbedingungen zu, um Zugriff auf die eingeschränkten Modellgewichte zu erhalten.
  3. Zugriffstoken generieren:Generieren Sie in den Einstellungen Ihres Hugging Face-Kontos (Einstellungen –> Zugriffstokens) ein Nutzerzugriffstoken mit Leseberechtigungen. Dieses Token wird in Ihrer Konfiguration als HF_TOKEN verwendet.

Zentrale Referenzkonfiguration

Alle Bereitstellungsparameter werden über eine zentrale .env-Datei unter <local-config-dir>/.env verwaltet. Achten Sie darauf, dass diese Datei vorhanden ist und Ihre spezifischen Parameter enthält (Hugging Face-Token, Namespace, Modellname usw.).

Beispiel für die .env-Struktur:

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

Umgebung und Anmeldedaten einrichten

Namespace und Hugging Face-Secret erstellen

Vor der Bereitstellung müssen Sie den Namespace und das Secret für das Hugging Face-Token erstellen:

# 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 -

vLLM-Bereitstellung in Kubernetes

Die Bereitstellung besteht aus drei Hauptmanifesten: PVC, Service und Deployment. In diesen Vorlagen werden Umgebungsvariablen verwendet, die zur Bereitstellungszeit ersetzt werden.

Anspruch auf nichtflüchtiges Volume (Persistent Volume Claim, PVC)

Der PVC sorgt dafür, dass Modellgewichte bei Neustarts von Pods beibehalten werden. Dazu wird die Speicherklasse local-shared der Distributed Cloud-Software verwendet.

Erstellen Sie eine Datei mit dem Namen vllm-pvc.yaml und dem folgendem Inhalt:

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

Dienst

Stellt den vLLM API-Server intern auf Port 8000 bereit.

Erstellen Sie eine Datei mit dem Namen vllm-service.yaml und dem folgendem Inhalt:

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

Bereitstellung

Führt den vLLM-Container aus, stellt das Modellcache-Volume bereit und fordert physische GPU-Ressourcen an. Während 96 GB VRAM für nicht quantisierte BF16-Gewichte (~62 GB) ausreichen, ermöglicht diese Referenzimplementierung die Blackwell-FP8-Quantisierung (--quantization=fp8, ~31 GB Gewichte), um den KV-Cache auf 56,53 GiB (61,728 Tokens) zu erweitern und so den gleichzeitigen Durchsatz zu erhöhen.

Erstellen Sie eine Datei mit dem Namen vllm-deployment.yaml und dem folgendem Inhalt:

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

Bereitstellung der Gradio-Benutzeroberfläche

Die Gradio-Benutzeroberfläche bietet eine interaktive Weboberfläche, über die Sie mit dem Modell chatten können. Sie wird im Cluster bereitgestellt und stellt über das interne Kubernetes-Netzwerk eine Verbindung zum vLLM-Dienst her.

Gradio-Bereitstellung

Erstellen Sie eine Datei mit dem Namen gradio-deployment.yaml und dem folgendem Inhalt:

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

Gradio-Dienst

Erstellen Sie eine Datei mit dem Namen gradio-service.yaml und dem folgendem Inhalt:

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

Konfiguration der Beobachtbarkeit

Weitere Informationen zum Konfigurieren von Anwendungs-Logging und -Monitoring finden Sie im offiziellen Leitfaden Anwendungs-Logging und -Monitoring.

vLLM-Monitoring

Damit Google Cloud Managed Service for Prometheus (GMP) vLLM-Messwerte erfassen kann, stellen wir eine PodMonitoring-Ressource bereit, die auf die vLLM-Pods ausgerichtet ist.

Erstellen Sie eine Datei mit dem Namen vllm-pod-monitoring.yaml und dem folgendem Inhalt:

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

GPU-Überwachung

Damit Google Cloud Managed Service for Prometheus (GMP) GPU-Messwerte aus dem NVIDIA DCGM-Exporter erfassen kann, stellen wir eine PodMonitoring-Ressource im Namespace gpu-operator bereit. Weitere Informationen finden Sie unter GPU-Messwerte an Cloud Monitoring senden.

Erstellen Sie eine Datei mit dem Namen gpu-pod-monitoring.yaml und dem folgendem Inhalt:

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

Ausführungsschritte

Manifeste bereitstellen

Wenden Sie die Manifeste auf den Cluster an. Da die YAML-Dateien Platzhalter für Umgebungsvariablen enthalten, verwenden Sie envsubst, um die Variablen aus der Datei .env zu ersetzen, bevor Sie sie anwenden.

  1. Wechseln Sie zu Ihrem Arbeitsverzeichnis, das die YAML-Dateien enthält:

    cd <local-working-dir>
    
  2. Quellen Sie die Umgebungsvariablen:

    source <local-config-dir>/.env
    
  3. Wenden Sie die Manifeste nacheinander an:

    # 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 -
    

Überprüfung

Boot-Sequenz des Monitor-Pods überwachen

Streamen Sie die Containerlogs, um die Startsequenz zu verfolgen:

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

Warten Sie, bis in Ihren Logs das Signal für die aktive Auslieferung angezeigt wird:

INFO: Application startup complete.

Portweiterleitungstunnel einrichten

Wenn Sie den Endpunkt lokal testen möchten, leiten Sie den Dienstport 8000 weiter:

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

Lassen Sie dieses Terminal geöffnet oder führen Sie es im Hintergrund aus.

Endpunkt für die Bereitstellung von Anfragen

Testen Sie in einem separaten Terminal die Reaktionsfähigkeit der API:

1. Liste der Abfragemodelle

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

2. Chat-Vervollständigungen abfragen

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

GPU- und VRAM-Zuweisungen prüfen

Um sicherzustellen, dass das Modell die Hardware effizient nutzt und der Speicherbedarf korrekt ist, können Sie eine GPU-Prüfung durchführen.

GPU über nvidia-smi im Pod prüfen

Rufen Sie den Namen Ihres aktiven vLLM-Pods ab und führen Sie nvidia-smi im Container aus:

# 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

Erwartete Ausgabe: Die Ausgabe sollte die physische VRAM-Auslastung entsprechend dem Parameter GPU_MEMORY_UTILIZATION angeben. Auf einer Workstation mit einer NVIDIA RTX PRO 6000 (ca. 96 GB VRAM), auf der google/gemma-4-31B-it mit GPU_MEMORY_UTILIZATION=0.95 ausgeführt wird, sollten beispielsweise etwa 95.800 MiB für VLLM::EngineCore zugewiesen sein:

+-----------------------------------------------------------------------------------------+
| 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 |
+-----------------------------------------+------------------------+----------------------+

KV-Cache-Zuweisung in Logs prüfen

Sie können auch die internen Zuweisungs-Protokolle von vLLM prüfen, um die KV-Cache-Größe und die Token-Nebenläufigkeit zu überprüfen:

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

Erwartete Ausgabe:

(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

Dies bestätigt, dass 56,53 GiB VRAM für den Kontext-KV-Cache reserviert sind, was eine große Anzahl gleichzeitiger Tokens ermöglicht.

Gradio-UI-Bereitstellung prüfen

Sobald der Gradio-Pod ausgeführt wird, können Sie auf die Benutzeroberfläche zugreifen, indem Sie einen Portweiterleitungstunnel einrichten.

Status des Gradio-Pods überwachen

Prüfen Sie, ob der Gradio-Pod ausgeführt wird:

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

Erwartete Ausgabe:

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

Portweiterleitungstunnel zu Gradio einrichten

Leiten Sie den Gradio-Dienstport 8080 an Ihren lokalen Port 7860 weiter:

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

Lassen Sie dieses Terminal geöffnet oder führen Sie es im Hintergrund aus:

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

Auf die Web-UI zugreifen

  • Wenn Sie die Anwendung auf einer lokalen Workstation ausführen: Öffnen Sie Ihren Browser und rufen Sie direkt http://localhost:7860 auf.
  • Wenn die Anwendung in Cloud Shell ausgeführt wird:Klicken Sie auf den Button Webvorschau, wählen Sie Port ändern aus, geben Sie 7860 ein und klicken Sie auf Ändern und Vorschau.

Die Gradio-Chatbot-Oberfläche sollte angezeigt werden. Sie können eine Nachricht eingeben, um mit dem Gemma-Modell zu interagieren. Der Gradio-Pod leitet die Anfrage intern an den vllm-service-Endpunkt weiter.

Tunnel bereinigen

So beenden Sie den Portweiterleitungstunnel:

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

Überprüfung des Monitorings

Sobald vLLM bereitgestellt und die PodMonitoring-Ressource angewendet wurde, können Sie prüfen, ob Messwerte in Cloud Monitoring aufgenommen werden.

PodMonitoring-Status prüfen

Prüfen Sie, ob die PodMonitoring-Ressource erstellt wurde und aktiv ist:

kubectl get podmonitoring -n ${NAMESPACE_NAME}

Messwertaufnahme über die Google Cloud Console prüfen

Sie können mit der Google Cloud Console (Metrics Explorer) prüfen, ob Messwerte erfasst werden:

  1. Öffnen Sie den Metrics Explorer in der Google Cloud Console:
    • Rufen Sie https://console.cloud.google.com/monitoring/metrics-explorer auf (achten Sie darauf, dass Sie Ihr Projekt auswählen ${GCP_PROJECT_ID}).
  2. Suchen Sie im Drop-down-Menü Messwert auswählen nach Folgendem und wählen Sie es aus:
    • prometheus.googleapis.com/vllm:num_requests_running/gauge, um vLLM-Messwerte zu überprüfen.
    • prometheus.googleapis.com/DCGM_FI_DEV_GPU_UTIL/gauge, um Messwerte zur GPU-Auslastung zu prüfen.
  3. Sehen Sie sich das Diagramm an, um zu prüfen, ob Datenpunkte aktiv dargestellt werden.

Logging-Bestätigung

Wenn die Arbeitslast ausgeführt wird, können Sie prüfen, ob Logs nach Cloud Logging exportiert werden.

vLLM-Logaufnahme prüfen

Prüfen Sie, ob vLLM-Containerlogs nach Cloud Logging exportiert werden:

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}

Aufnahme von GPU-Exporter-Logs prüfen

Prüfen Sie, ob die Containerlogs des GPU-Exporters nach Cloud Logging exportiert werden:

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}

Logs mit der Google Cloud -Console (Log-Explorer) prüfen

Sie können die Logaufnahme auch mit der Google Cloud Console überprüfen:

  1. Öffnen Sie den Log-Explorer in der Google Cloud Console:
    • Rufen Sie https://console.cloud.google.com/logs/query auf (achten Sie darauf, dass Sie Ihr Projekt auswählen ${GCP_PROJECT_ID}).
  2. Geben Sie im Feld Abfrage die folgende Abfrage ein, um vLLM-Logs aufzurufen:

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

    Ersetzen Sie <NAMESPACE_NAME> durch Ihren tatsächlichen Namespace, z.B. your-custom-namespace.

  3. Klicken Sie auf Abfrage ausführen. Sie sollten die Logeinträge aus dem vLLM-Container sehen.

  4. Führen Sie die folgende Abfrage aus, um die Logs des GPU-Exporters zu prüfen:

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