在 GKE 上使用 vLLM 运行 Qwen3 推理

本教程介绍如何使用 vLLM 部署框架部署和投放 Qwen3 大语言模型 (LLM)。您可以在 Google Kubernetes Engine (GKE) 上的单个 A4 虚拟机 (VM) 实例上部署该模型。

本教程适用于机器学习 (ML) 工程师、平台管理员和运维人员,以及对使用 Kubernetes 容器编排功能处理推理工作负载感兴趣的数据和 AI 专家。

目标

  1. 使用 Hugging Face 访问 Qwen3。

  2. 准备环境。

  3. 在 Autopilot 模式下创建 GKE 集群。

  4. 创建 Cloud Storage 存储桶。

  5. 为 Hugging Face 凭据创建 Kubernetes Secret。

  6. 为 Cloud Storage 配置工作负载身份联合。

  7. 使用 Qwen3 模型填充 Cloud Storage 存储桶。

  8. 将 vLLM 容器部署到您的 GKE。

  9. 使用 curl 与 Qwen3 互动。

  10. 清理。

费用

本教程使用 Google Cloud的收费组件,包括:

如需根据您的预计使用量来估算费用,请使用价格计算器

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud新手,请 创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 安装 Google Cloud CLI。

  3. 如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI

  4. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  5. 创建或选择 Google Cloud 项目

    选择或创建项目所需的角色

    • 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
    • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予角色
    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替换为您的 Google Cloud 项目名称。

  6. 验证是否已为您的 Google Cloud 项目启用结算功能

  7. 启用所需的 API:

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 获得了此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色

    gcloud services enable container.googleapis.com
  8. 安装 Google Cloud CLI。

  9. 如果您使用的是外部身份提供方 (IdP),则必须先使用联合身份登录 gcloud CLI

  10. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  11. 创建或选择 Google Cloud 项目

    选择或创建项目所需的角色

    • 选择项目:选择项目不需要特定的 IAM 角色,您可以选择已获授角色的任何项目。
    • 创建项目:如需创建项目,您需要拥有 Project Creator 角色 (roles/resourcemanager.projectCreator),该角色包含 resourcemanager.projects.create 权限。了解如何授予角色
    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替换为您的 Google Cloud 项目名称。

  12. 验证是否已为您的 Google Cloud 项目启用结算功能

  13. 启用所需的 API:

    启用 API 所需的角色

    如需启用 API,您需要拥有 serviceusage.services.enable 权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 获得了此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获得此权限。了解如何授予角色

    gcloud services enable container.googleapis.com
  14. 向您的用户账号授予角色。对以下每个 IAM 角色运行以下命令一次: roles/container.admin

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    替换以下内容:

    • PROJECT_ID:您的项目 ID。
    • USER_IDENTIFIER:您的用户 账号的标识符。例如,myemail@example.com
    • ROLE:您向用户账号授予的 IAM 角色。
  15. 登录或创建 Hugging Face 账号

使用 Hugging Face 访问 Qwen3

如需使用 Hugging Face 访问 Qwen3,请按以下步骤操作:

  1. 登录 Hugging Face
  2. 创建 Hugging Face read 访问令牌。 依次点击您的个人资料 > 设置 > 访问令牌 > +创建新令牌
  3. 为令牌指定您选择的名称,然后选择一个角色。您可以为此教程选择的最低角色权限级别为读取
  4. 选择 Create token
  5. 将生成的令牌复制并保存到剪贴板。您将在本教程的后面部分使用该地址。

准备环境

如需准备环境,请设置默认环境变量:

export PROJECT_ID="YOUR_PROJECT_ID"
export RESERVATION_NAME="YOUR_RESERVATION_NAME"
export REGION="YOUR_REGION"
export CLUSTER_NAME="YOUR_CLUSTER_NAME"
export GCS_BUCKET_NAME="YOUR_GCS_BUCKET"
export HUGGING_FACE_TOKEN="YOUR_HF_TOKEN"
export NETWORK="YOUR_NETWORK_NAME"
export SUBNETWORK="YOUR_SUBNETWORK_NAME"

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

替换以下内容:

  • YOUR_PROJECT_ID:您要在其中创建 GKE 集群的 Google Cloud 项目的 ID。

  • YOUR_RESERVATION_NAME:您要用于创建 GKE 集群的预留的名称。根据预留所在的项目,指定以下值之一:

    • 预留存在于您的项目中:RESERVATION_NAME

    • 预留存在于其他项目中,并且您的项目可以使用该预留:projects/RESERVATION_PROJECT_ID/reservations/RESERVATION_NAME

  • YOUR_REGION:您要在其中创建 GKE 集群的区域。您只能在预留所在的区域中创建集群。

  • YOUR_CLUSTER_NAME:要创建的 GKE 集群的名称。

  • YOUR_BUCKET_NAME:要创建的区域级 Cloud Storage 存储桶的名称。

  • YOUR_HF_TOKEN:您在上一部分中创建的 Hugging Face 访问令牌。

  • YOUR_NETWORK_NAME:GKE 集群使用的网络。请指定以下某个值:

    • 如果您创建了自定义网络,请指定您的网络名称。

    • 否则,请指定 default

  • YOUR_SUBNETWORK_NAME:GKE 集群使用的子网。请指定以下某个值:

    • 如果您创建了自定义子网,请指定子网的名称。您只能指定与预留位于同一区域的子网。

    • 否则,请指定 default

在 Autopilot 模式下创建 GKE 集群

如需在 Autopilot 模式下创建 GKE 集群,请运行以下命令:

gcloud container clusters create-auto "$CLUSTER_NAME" \
    --project="$PROJECT_ID" \
    --region="$REGION" \
    --release-channel=rapid \
    --network="$NETWORK" \
    --subnetwork="$SUBNETWORK"
创建 GKE 集群可能需要一些时间才能完成。如需验证 Google Cloud 是否已完成集群创建,请前往 Google Cloud 控制台中的 Kubernetes 集群

创建 Cloud Storage 存储桶

如需创建区域 Cloud Storage 存储桶来存储模型,请运行以下命令:

gcloud storage buckets create gs://$GCS_BUCKET_NAME \
    --project=$PROJECT_ID \
    --location=$REGION

为 Hugging Face 凭据创建 Kubernetes Secret

如需为 Hugging Face 凭据创建 Kubernetes Secret,请按以下步骤操作:

  1. 配置 kubectl 以与您的 GKE 集群通信:

    gcloud container clusters get-credentials "$CLUSTER_NAME" \
        --location="$REGION" \
        --project="$PROJECT_ID"
  2. 创建一个 Kubernetes Secret 来存储您的 Hugging Face 令牌:

    kubectl create secret generic hf-secret \
        --from-literal=hf_token="${HUGGING_FACE_TOKEN}" \
        --dry-run=client -o yaml | kubectl apply -f -

为 Cloud Storage 配置工作负载身份联合

如需允许 GKE 安全地访问 Cloud Storage 存储桶,请设置 GKE 工作负载身份联合:

gcloud iam service-accounts create qwen-gcs-sa \
    --project=$PROJECT_ID

gcloud storage buckets add-iam-policy-binding gs://$GCS_BUCKET_NAME \
    --member="serviceAccount:qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/storage.objectAdmin"

kubectl create serviceaccount qwen-ksa \
    --namespace=default

gcloud iam service-accounts add-iam-policy-binding qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com \
    --project=$PROJECT_ID \
    --role=roles/iam.workloadIdentityUser \
    --member="serviceAccount:$PROJECT_ID.svc.id.goog[default/qwen-ksa]"

kubectl annotate serviceaccount qwen-ksa \
    --namespace=default \
    iam.gke.io/gcp-service-account="qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com"

使用 Qwen3 模型权重填充 Cloud Storage 存储桶

如需使用 Qwen3 模型权重填充 Cloud Storage 存储桶,请运行一个 Kubernetes 作业,该作业使用 Cloud Storage FUSE CSI 驱动程序将存储桶装载为卷。如果存储桶中尚不存在该模型,作业会从 Hugging Face 下载该模型。

  1. 创建一个名为 qwen3-model-loader.yaml 的文件,其中包含以下内容:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: qwen3-model-loader
    spec:
      template:
        metadata:
          annotations:
            gke-gcsfuse/volumes: "true"
            gke-gcsfuse/cpu-limit: "0"
            gke-gcsfuse/memory-limit: "0"
            gke-gcsfuse/ephemeral-storage-limit: "0"
        spec:
          serviceAccountName: qwen-ksa
          restartPolicy: OnFailure
          containers:
          - name: downloader
            image: python:3.11-slim
            resources:
              requests:
                cpu: "4"
                memory: "16Gi"
                ephemeral-storage: "100Gi"
              limits:
                cpu: "4"
                memory: "16Gi"
                ephemeral-storage: "100Gi"
            command: ["/bin/sh", "-c"]
            args:
            - |
              pip install huggingface_hub
              python3 -c '
              import os
              from huggingface_hub import snapshot_download
              model_id = "Qwen/Qwen3-235B-A22B-Instruct-2507"
              local_dir = "/data/Qwen/Qwen3-235B-A22B-Instruct-2507"
              config_path = os.path.join(local_dir, "config.json")
              if os.path.exists(config_path):
                  print(f"Model already exists at {local_dir}. Skipping download.")
              else:
                  print(f"Downloading model {model_id} to {local_dir}...")
                  snapshot_download(
                      repo_id=model_id,
                      local_dir=local_dir,
                      local_dir_use_symlinks=False,
                      token=os.environ.get("HUGGING_FACE_HUB_TOKEN")
                  )
                  print("Download completed successfully!")
              '
            env:
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_token
            volumeMounts:
            - name: gcs-fuse-volume
              mountPath: /data
          volumes:
          - name: gcs-fuse-volume
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: $GCS_BUCKET_NAME
                mountOptions: "implicit-dirs"
  2. 应用 qwen3-model-loader.yaml 清单以初始化下载作业:

    envsubst < qwen3-model-loader.yaml | kubectl apply -f -
  3. 如需验证作业是否正在运行,请以流式传输方式查看下载作业日志:

    kubectl logs -f job/qwen3-model-loader -c downloader
    
  4. 等待模型下载作业完成:

    kubectl wait \
        --for=condition=Complete \
        --timeout=1800s job/qwen3-model-loader
  5. 如需删除作业,请运行以下命令:

    kubectl delete job qwen3-model-loader --ignore-not-found

将 vLLM 容器部署到 GKE 集群

如需使用 Kubernetes Deployment 部署 vLLM 容器以提供 Qwen3 模型,请执行以下操作:

  1. 创建一个 qwen3-235b-deploy.yaml 文件,其中包含您选择的 vLLM 部署:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-qwen3-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: qwen3-server
      template:
        metadata:
          labels:
            app: qwen3-server
            ai.gke.io/model: Qwen3-235B-A22B-Instruct-2507
            ai.gke.io/inference-server: vllm
            examples.ai.gke.io/source: user-guide
        spec:
          serviceAccountName: qwen-ksa
          containers:
          - name: qwen-inference-server
            image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:20250801_0916_RC01
            resources:
              requests:
                cpu: "10"
                memory: "1000Gi"
                ephemeral-storage: "500Gi"
                nvidia.com/gpu: "8"
              limits:
                cpu: "10"
                memory: "1000Gi"
                ephemeral-storage: "500Gi"
                nvidia.com/gpu: "8"
            command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --load-format=runai_streamer
            - --model-loader-extra-config={"distributed":true}
            - --tensor-parallel-size=8
            - --host=0.0.0.0
            - --port=8000
            - --max-model-len=8192
            - --max-num-seqs=4
            - --dtype=bfloat16
            env:
            - name: MODEL_ID
              value: "gs://$GCS_BUCKET_NAME/Qwen/Qwen3-235B-A22B-Instruct-2507"
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            livenessProbe:
              httpGet:
                path: /health
                port: 8000
              initialDelaySeconds: 200
              periodSeconds: 10
            readinessProbe:
              httpGet:
                path: /health
                port: 8000
              initialDelaySeconds: 200
              periodSeconds: 5
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-b200
            cloud.google.com/reservation-name: $RESERVATION_NAME
            cloud.google.com/reservation-affinity: "specific"
            cloud.google.com/gke-gpu-driver-version: latest
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: qwen3-service
    spec:
      selector:
        app: qwen3-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    ---
    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: vllm-qwen3-monitoring
    spec:
      selector:
        matchLabels:
          app: qwen3-server
      endpoints:
      - port: 8000
        path: /metrics
        interval: 30s
  2. qwen3-235b-deploy.yaml 文件应用于您的 GKE 集群:

    envsubst < qwen3-235b-deploy.yaml | kubectl apply -f -
    由于容器使用 Run:ai Model Streamer 直接从 Cloud Storage 流式传输模型权重,因此启动时间显著缩短。

  3. 如需查看完成状态,请运行以下命令:

    kubectl wait \
        --for=condition=Available \
        --timeout=1800s deployment/vllm-qwen3-deployment
    借助 --timeout=600s 标志,该命令可以监控部署长达 10 分钟。

使用 curl 与 Qwen3 互动

如需验证您部署的 Qwen3 模型,请执行以下操作:

  1. 设置到 Qwen3 的端口转发:

    kubectl port-forward service/qwen3-service 8000:8000
  2. 打开一个新终端窗口。然后,您可以使用 curl 与模型聊天:

    curl http://127.0.0.1:8000/v1/chat/completions \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{
      "model": "Qwen/Qwen3-235B-A22B-Instruct-2507",
      "messages": [
        {
          "role": "user",
          "content": "Describe a GPU in one short sentence?"
        }
      ],
      "stream": false
    }' | jq .
  3. 输出类似于以下内容:

    {
      "id": "chatcmpl-a926ddf7ef2745ca832bda096e867764",
      "object": "chat.completion",
      "created": 1755023619,
      "model": "Qwen/Qwen3-235B-A22B-Instruct-2507",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "A GPU is a specialized electronic circuit designed to rapidly process and render graphics and perform parallel computations.",
            "refusal": null,
            "annotations": null,
            "audio": null,
            "function_call": null,
            "tool_calls": [],
            "reasoning_content": null
          },
          "logprobs": null,
          "finish_reason": "stop",
          "stop_reason": null
        }
      ],
      "service_tier": null,
      "system_fingerprint": null,
      "usage": {
        "prompt_tokens": 16,
        "total_tokens": 36,
        "completion_tokens": 20,
        "prompt_tokens_details": null
      },
      "prompt_logprobs": null,
      "kv_transfer_params": null
    }
    

观察模型性能

如果您想观察模型的性能,可以使用 Cloud Monitoring 中的 vLLM 信息中心集成。此信息中心可帮助您查看模型的重要性能指标,例如令牌吞吐量、网络延迟时间和错误率。如需了解详情,请参阅 Monitoring 文档中的 vLLM

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

为避免因本教程中使用的资源导致您的 Cloud Billing 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除资源

如需删除教程资源,请运行以下命令:

envsubst < qwen3-235b-deploy.yaml | kubectl delete -f -
envsubst < qwen3-model-loader.yaml | kubectl delete -f -
kubectl delete secret hf-secret
kubectl delete serviceaccount qwen-ksa

gcloud iam service-accounts delete qwen-gcs-sa@$PROJECT_ID.iam.gserviceaccount.com \
    --project=$PROJECT_ID --quiet

gcloud storage rm --recursive gs://$GCS_BUCKET_NAME

删除 GKE 集群

如需删除 GKE 集群,请运行以下命令:

gcloud container clusters delete "$CLUSTER_NAME" \
    --region="$REGION" \
    --project="$PROJECT_ID" \
    --quiet

删除项目

删除 Google Cloud 项目:

gcloud projects delete PROJECT_ID

后续步骤