在 Distributed Cloud 纯软件参考实现上打开模型部署

概览

本文档是解决方案参考实现 (SRI) 指南,介绍了部署、提供和验证分布式云纯软件开放模型服务解决方案所需的具体步骤。

本指南介绍了如何部署优化的 vLLM 服务引擎,以在 Distributed Cloud(纯软件)单节点集群配置(面向边缘部署)上运行 Gemma 4 (google/gemma-4-31B-it),并利用物理 NVIDIA GPU 资源(例如 RTX PRO 6000)。

此演练旨在通过 CLI 终端客户端执行,该客户端具有对 Distributed Cloud 纯软件集群的 kubectl 访问权限。

目标

完成此解决方案参考实现后,您将能够:

  • 通过本地 .env 文件配置服务环境参数。
  • 使用 local-shared 存储类别部署永久性卷声明 (PVC) 以持久保存模型权重。
  • 部署优化的 vLLM 服务引擎,利用 Vertex AI 合格的容器,映射物理 nvidia.com/gpu 资源。
  • 部署 Gradio Web 界面以提供互动式聊天界面。
  • 建立本地端口转发隧道,以通过 API 和 Web 界面验证服务响应速度。
  • 通过确认日志和指标(包括 GPU 遥测数据)已提取到 Cloud Logging 和 Cloud Monitoring 中,验证可观测性集成。

准备工作

前提条件(集群设置)

本指南假设您已配置一个正在运行的 Distributed Cloud 纯软件集群,且该集群支持 GPU。如需安装集群,请参阅官方适用于裸金属的 Distributed Cloud(纯软件)文档。GPU 配置必须符合设置和使用 NVIDIA GPU 的官方 Google Cloud文档。

客户端工作站前提条件

确保您的本地终端环境已安装并配置以下工具:

  • gcloud CLI:用于项目配置和查询日志。必须经过身份验证 (gcloud auth login),并且配置为 Distributed Cloud 纯软件集群注册的有效Google Cloud 项目。
  • kubectl:管理集群资源所必需的工具。必须配置适当的上下文,才能访问目标 Distributed Cloud 软件专用集群(例如,通过连接网关或直接本地网络访问)。
  • curl:必需,用于向服务端点发送测试请求。
  • jq:用于解析来自服务端点的 JSON 输出。

Hugging Face 模型访问权限

如需下载和部署 Gemma 4 模型,您必须有权访问 Hugging Face 代码库:

  1. Hugging Face 账号:确保您在 Hugging Face 上注册了账号。
  2. 接受模型许可:前往 Gemma 4 31B IT 模型页面,同意许可条款,即可获取门控模型权重。
  3. 生成访问令牌:从您的 Hugging Face 账号设置(设置 -> 访问令牌)中生成具有读取权限的用户访问令牌。此令牌将用作配置中的 HF_TOKEN。

中央参考配置

所有部署参数均通过位于 <local-config-dir>/.env 的中央 .env 文件进行管理。确保此文件存在,并且包含您的特定参数(Hugging Face 令牌、命名空间、模型名称等)。

.env 结构示例:

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

设置环境和凭据

创建命名空间和 Hugging Face Secret

在部署之前,您必须创建命名空间和 Hugging Face 令牌 Secret:

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

在 Kubernetes 上部署 vLLM

部署包含三个主要清单:PVC、Service 和 Deployment。 这些模板使用在部署时替换的环境变量。

永久性卷声明 (PVC)

PVC 可确保模型权重在 Pod 重启后持久保存,它使用 Distributed Cloud 纯软件 local-shared 存储类别。

创建一个名为 vllm-pvc.yaml 的文件,其中包含以下内容:

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

服务

在内部通过端口 8000 公开 vLLM API 服务器。

创建一个名为 vllm-service.yaml 的文件,其中包含以下内容:

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

部署

运行 vLLM 容器,装载模型缓存卷,并请求物理 GPU 资源。虽然 96 GB 的 VRAM 可以容纳未量化的 BF16 权重(约 62 GB),但此参考实现支持 Blackwell FP8 量化(--quantization=fp8,约 31 GB 权重),从而将 KV 缓存扩展到 56.53 GiB(61,728 个令牌),以实现更高的并发吞吐量。

创建一个名为 vllm-deployment.yaml 的文件,其中包含以下内容:

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

Gradio 界面部署

Gradio 界面提供了一个交互式网页界面,用于与模型对话。它部署在集群内,并通过内部 Kubernetes 网络连接到 vLLM 服务。

Gradio 部署

创建一个名为 gradio-deployment.yaml 的文件,其中包含以下内容:

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 服务

创建一个名为 gradio-service.yaml 的文件,其中包含以下内容:

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

可观测性配置

如需详细了解如何配置应用日志记录和监控,请参阅官方应用日志记录和监控指南。

vLLM 监控

为了让 Google Cloud Managed Service for Prometheus (GMP) 能够抓取 vLLM 指标,我们部署了一个以 vLLM pod 为目标的 PodMonitoring 资源。

创建一个名为 vllm-pod-monitoring.yaml 的文件,其中包含以下内容:

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 监控

为了让 Google Cloud Managed Service for Prometheus (GMP) 能够从 NVIDIA DCGM Exporter 抓取 GPU 指标,我们在 gpu-operator 命名空间中部署 PodMonitoring 资源。如需了解详情,请参阅将 GPU 指标发送到 Cloud Monitoring。

创建一个名为 gpu-pod-monitoring.yaml 的文件,其中包含以下内容:

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

执行步数

部署清单

将清单应用到集群。由于 YAML 文件包含环境变量占位符,因此请先使用 envsubst 替换 .env 文件中的变量,然后再应用这些变量。

  1. 前往包含 YAML 文件的工作目录:

    cd <local-working-dir>
    
  2. 加载环境变量:

    source <local-config-dir>/.env
    
  3. 按顺序应用清单:

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

验证

监控 pod 启动序列

流式传输容器日志以跟踪启动顺序:

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

等待,直到您在日志中看到“active serving ready”信号:

INFO: Application startup complete.

建立端口转发隧道

如需在本地测试端点,请转发服务端口 8000:

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

保持此终端处于打开状态,或在后台运行此终端。

查询服务端点

在另一个终端中,测试 API 响应速度:

1. 查询模型列表

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

2. 查询对话补全

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 和 VRAM 分配

为确保模型高效利用硬件且内存占用空间正确,您可以运行 GPU 审核。

通过 pod 内的 nvidia-smi 审核 GPU

检索活跃 vLLM pod 的名称,并在容器内执行 nvidia-smi:

# 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

预期输出:输出应报告与 GPU_MEMORY_UTILIZATION 参数匹配的物理 VRAM 利用率。例如,在配备 NVIDIA RTX PRO 6000(约 96 GB VRAM)的工作站上运行 google/gemma-4-31B-it 并使用 GPU_MEMORY_UTILIZATION=0.95 时,您应该会看到分配给 VLLM::EngineCore 的内存约为 95,800 MiB:

+-----------------------------------------------------------------------------------------+
| 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 缓存分配

您还可以检查 vLLM 内部分配日志,以验证 KV 缓存大小和令牌并发性:

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

预期输出:

(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

这确认了 56.53 GiB 的 VRAM 已预留给上下文 KV 缓存,从而支持大量并发令牌。

验证 Gradio 界面部署

Gradio pod 运行后,您可以通过建立端口转发隧道来访问界面。

监控 Gradio pod 状态

确保 Gradio pod 正在运行:

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

预期输出:

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

建立到 Gradio 的端口转发隧道

将 Gradio 服务端口 8080 转发到本地端口 7860:

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

保持此终端处于打开状态,或在后台运行此终端:

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

访问网页界面

  • 如果是在本地工作站上运行:打开浏览器并直接前往:http://localhost:7860
  • 如果是在 Cloud Shell 中运行:使用网页预览按钮,选择更改端口,输入 7860,然后点击更改并预览。

您应该会看到 Gradio 聊天机器人界面。您可以输入消息与 Gemma 模型互动。Gradio pod 会在内部将请求路由到 vllm-service 端点。

清理隧道

如需停止端口转发隧道,请执行以下操作:

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

监控验证

部署 vLLM 并应用 PodMonitoring 资源后,您可以验证指标是否正在被提取到 Cloud Monitoring 中。

验证 PodMonitoring 状态

确保 PodMonitoring 资源已创建且处于活跃状态:

kubectl get podmonitoring -n ${NAMESPACE_NAME}

使用 Google Cloud 控制台验证指标提取

您可以使用 Google Cloud 控制台(Metrics Explorer)验证指标是否正在被提取:

  1. 在 Google Cloud 控制台中打开 Metrics Explorer:
    • 前往 https://console.cloud.google.com/monitoring/metrics-explorer(确保您已选择项目 ${GCP_PROJECT_ID})。
  2. 在选择指标下拉菜单中,搜索并选择:
    • prometheus.googleapis.com/vllm:num_requests_running/gauge 以验证 vLLM 指标。
    • prometheus.googleapis.com/DCGM_FI_DEV_GPU_UTIL/gauge 以验证 GPU 利用率指标。
  3. 观察图表,确认数据点是否正在积极绘制。

日志记录验证

工作负载运行后,您可以验证日志是否已导出到 Cloud Logging。

验证 vLLM 日志注入

验证 vLLM 容器日志是否已导出到 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}

验证 GPU 指标导出器日志提取

验证 GPU 指标导出器容器日志是否已导出到 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}

使用 Google Cloud 控制台(Logs Explorer)验证日志

您还可以使用 Google Cloud 控制台验证日志提取:

  1. 在 Google Cloud 控制台中打开 Logs Explorer:
    • 前往 https://console.cloud.google.com/logs/query(确保您已选择项目 ${GCP_PROJECT_ID})。
  2. 在查询框中,输入以下查询以查看 vLLM 日志:

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

    (将 <NAMESPACE_NAME> 替换为您的实际命名空间,例如 your-custom-namespace)。

  3. 点击运行查询。您应该会看到来自 vLLM 容器的日志条目。

  4. 如需验证 GPU 指标导出器日志,请运行以下查询:

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