在 GKE 上使用 vLLM TorchTPU 搭配 TPU7x 加速器提供 Qwen3.5-397B

本教學課程說明如何使用單一主機 TPU7x (Ironwood) 加速器和 vLLM TPU 服務框架搭配 TorchTPU (torchtpu),在 Google Kubernetes Engine (GKE) 部署及提供專家混合模型 Qwen3.5-397B (Qwen/Qwen3.5-397B-A17B-FP8)。Qwen3.5-397B 至少需要四個 TPU7x 晶片,因此您可以在啟用資料平行處理和專家平行處理的 2x2x1 拓撲中,在單一 tpu7x-standard-4t 節點上執行工作負載。

目標

  • 設定 GKE 叢集和單主機 TPU7x 節點集區。
  • 在 GKE 部署單一主機 vLLM TorchTPU 伺服器。
  • 向 vLLM TorchTPU 伺服器傳送推論要求。
  • 執行推論基準測試工作負載。
  • 清除所用資源。

費用

在本文件中,您會使用下列Google Cloud計費元件:

您可以使用 Pricing Calculator 根據預測用量估算費用。

完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」一節。

事前準備

  • 您需要 Hugging Face 存取權杖,才能使用本教學課程。您可以前往 Hugging Face 註冊免費帳戶。擁有帳戶後,請產生存取權杖:

    1. 在「Welcome to Hugging Face」頁面,點選帳戶顯示圖片,然後選取「存取權杖」。
    2. 在「存取權杖」頁面,按一下「建立新權杖」。
    3. 選取「Read」權杖類型,並輸入權杖名稱。
    4. 系統會顯示存取權杖。將權杖儲存在安全的地方。

如要取得完成本教學課程所需的權限,請要求管理員在專案中授予您下列 IAM 角色:

如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

您或許也能透過自訂角色或其他預先定義的角色,取得必要權限。

設定環境變數

設定驗證機制:

gcloud auth login
gcloud auth application-default login

設定環境變數:

export PROJECT_ID="YOUR_PROJECT_ID"
export REGION="YOUR_REGION"
export ZONE="YOUR_ZONE"
export CLUSTER_NAME="YOUR_CLUSTER_NAME"
export MACHINE_TYPE="tpu7x-standard-4t"
export NODE_POOL_NAME="np-0"
export RESERVATION_NAME="YOUR_RESERVATION_NAME"
export HF_TOKEN="YOUR_HF_TOKEN"
export NETWORK="YOUR_NETWORK_NAME"
export SUBNETWORK="YOUR_SUBNETWORK_NAME"
export VLLM_IMAGE="YOUR_VLLM_TPU_IMAGE"

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

更改下列內容:

  • YOUR_PROJECT_ID: Google Cloud專案的 ID。
  • YOUR_REGION:要部署叢集的區域,例如 us-central1。
  • YOUR_ZONE:要部署 TPU7x 節點集區的可用區,例如 us-central1-c。
  • YOUR_CLUSTER_NAME:GKE 叢集的名稱,例如 tpu7x-tutorial-cluster。
  • YOUR_RESERVATION_NAME:如果使用預留項目,請提供 TPU7x 預留項目的名稱。
  • YOUR_HF_TOKEN:您的 Hugging Face 存取權杖。
  • YOUR_NETWORK_NAME:Google Cloud 網路的名稱。如果您建立了自訂網路,請指定該網路。否則,請指定 default。
  • YOUR_SUBNETWORK_NAME:Google Cloud 子網路的名稱。如果您建立了自訂子網路,請指定該子網路。否則,請指定 default。
  • YOUR_VLLM_TPU_IMAGE:要使用的 vLLM TorchTPU 映像檔。如要查看公開映像檔,請參閱 vLLM TorchTPU 存放區。

建立 GKE 叢集

如要以標準模式建立 GKE 叢集,並連結單一主機 TPU7x 節點集區,請完成下列步驟:

  1. 建立區域性 GKE 叢集:

    gcloud container clusters create "${CLUSTER_NAME}" \
        --project="${PROJECT_ID}" \
        --location="${REGION}" \
        --node-locations="${ZONE}" \
        --network="${NETWORK}" \
        --subnetwork="${SUBNETWORK}"

    輸出結果會與下列內容相似:

    NAME                    LOCATION       MASTER_VERSION      MASTER_IP      MACHINE_TYPE    NODE_VERSION        NUM_NODES  STATUS
    tpu7x-tutorial-cluster  us-central1    1.35.7-gke.1027000  34.63.222.246  n2-standard-16  1.35.7-gke.1027000  3          RUNNING
    
  2. 使用預留項目,建立含有一個 tpu7x-standard-4t 節點 (2x2x1 拓撲中的四個 TPU7x 晶片) 的單主機 TPU7x 節點集區:

    gcloud container node-pools create "${NODE_POOL_NAME}" \
        --cluster="${CLUSTER_NAME}" \
        --machine-type="${MACHINE_TYPE}" \
        --location="${REGION}" \
        --node-locations="${ZONE}" \
        --project="${PROJECT_ID}" \
        --num-nodes=1 \
        --reservation-affinity=specific \
        --reservation="${RESERVATION_NAME}"

    除了使用特定預留項目,您也可以傳遞下列旗標,使用 Spot 容量或彈性啟動型 VM 建立節點集區:

    • Spot VM:將 --reservation-affinity 和 --reservation 旗標替換為 --spot,即可使用 Spot 容量。節點集區建立後,使用 Spot 容量的執行個體可能需要一段時間才能建立,且在工作負載執行期間可能會遭到先占。如果 Pod 需要一段時間才能建立,或工作負載在執行期間停止,可能就是這個原因。
    • 彈性啟動型 VM:傳遞 --flex-start 旗標,使用彈性啟動用量選項佈建節點集區。詳情請參閱「使用 TPU 和彈性啟動型 VM 執行小型批次工作負載」。

    輸出結果會與下列內容相似:

    NAME  MACHINE_TYPE       DISK_SIZE_GB  NODE_VERSION
    np-0  tpu7x-standard-4t  100           1.35.7-gke.1027000
    
  3. 設定 kubectl 憑證,以便與叢集通訊:

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

設定憑證

建立名為 hf-secret 的 Kubernetes Secret,用於儲存 Hugging Face 存取權杖:

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

部署 vLLM TorchTPU 伺服器

工作負載資訊清單 (qwen3_5_server.yaml) 定義下列資源:

  • StorageClass (hyperdisk-balanced-qwen3-5) 和 1,500 GiB PersistentVolumeClaim (hd-claim-qwen3-5),由 Google Cloud Hyperdisk Balanced 儲存空間支援,用於儲存下載的模型權重、XLA 編譯快取和 PyTorch 編譯快取。
  • 在單一 TPU7x 節點上排定的 Deployment (vllm-qwen3-5),具有 2x2x1 拓撲 (google.com/tpu: '4')。容器會執行 vllm serve,持續 Qwen/Qwen3.5-397B-A17B-FP8,並使用 --data-parallel-size=8、--tensor-parallel-size=1、--enable-expert-parallel、--kv-cache-dtype=fp8、--max-model-len=9236 和 --max-num-seqs=64。
  • 公開通訊埠 8000 的 ClusterIP Service (vllm-qwen3-5-service)。

如要部署及監控工作負載,請完成下列步驟:

  1. 擷取伺服器資訊清單:

    curl -O https://raw.githubusercontent.com/GoogleCloudSamples/AIHypercomputerSamples/refs/heads/main/tpu/inference/qwen3-5-397b/qwen3_5_server.yaml

    或者,您也可以選擇建立名為 qwen3_5_server.yaml 的檔案,並加入下列內容:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: hyperdisk-balanced-qwen3-5
    provisioner: pd.csi.storage.gke.io
    parameters:
      type: hyperdisk-balanced
    reclaimPolicy: Delete
    volumeBindingMode: WaitForFirstConsumer
    allowVolumeExpansion: true
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: hd-claim-qwen3-5
      namespace: default
    spec:
      storageClassName: hyperdisk-balanced-qwen3-5
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1500Gi
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-qwen3-5
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: vllm-qwen3-5
      template:
        metadata:
          labels:
            app: vllm-qwen3-5
        spec:
          nodeSelector:
            cloud.google.com/gke-tpu-accelerator: tpu7x
            cloud.google.com/gke-tpu-topology: 2x2x1
          tolerations:
          - key: "cloud.google.com/gke-spot"
            operator: "Equal"
            value: "true"
            effect: "NoSchedule"
          containers:
          - name: vllm-tpu
            image: $VLLM_IMAGE
            command: ["vllm", "serve"]
            args:
            - --host=0.0.0.0
            - --port=8000
            - --model=Qwen/Qwen3.5-397B-A17B-FP8
            - --tokenizer=Qwen/Qwen3.5-397B-A17B-FP8
            - --max-model-len=9236
            - --max-num-batched-tokens=1024
            - --max-num-seqs=64
            - --no-enable-prefix-caching
            - --gpu-memory-utilization=0.9
            - --data-parallel-size=8
            - --tensor-parallel-size=1
            - --async-scheduling
            - --language-model-only
            - --enable-auto-tool-choice
            - --tool-call-parser=qwen3_coder
            - --reasoning-parser=qwen3
            - '--limit-mm-per-prompt={"image": 0, "video": 0}'
            - --kv-cache-dtype=fp8
            - --enable-expert-parallel
            - --download-dir=/data
            - --block-size=128
            env:
            - name: MODEL_IMPL_TYPE
              value: "vllm"
            - name: DP_SCHED_ENABLED
              value: "1"
            - name: ONEHOT_MOE_PERMUTE_THRESHOLD
              value: "32768"
            - name: VLLM_ENGINE_READY_TIMEOUT_S
              value: "9600"
            - name: VLLM_ENGINE_ITERATION_TIMEOUT_S
              value: "1800"
            - name: USE_MOE_SPARSE_CORE
              value: "1"
            - name: TPU_MOE_SKIP_PADDED_TOKENS
              value: "1"
            - name: VLLM_CACHE_ROOT
              value: "/data/vllm_cache"
            - name: VLLM_TORCH_COMPILE_CACHE_DIR
              value: "/data/torch_compile_cache"
            - name: XLA_CACHE_DIR
              value: "/data/xla_cache"
            - name: HF_HOME
              value: /data
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            ports:
            - containerPort: 8000
            resources:
              limits:
                google.com/tpu: '4'
              requests:
                google.com/tpu: '4'
            readinessProbe:
              tcpSocket:
                port: 8000
              initialDelaySeconds: 15
              periodSeconds: 10
            volumeMounts:
            - mountPath: "/data"
              name: data-volume
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - emptyDir:
              medium: Memory
            name: dshm
          - name: data-volume
            persistentVolumeClaim:
              claimName: hd-claim-qwen3-5
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: vllm-qwen3-5-service
      namespace: default
    spec:
      selector:
        app: vllm-qwen3-5
      type: ClusterIP
      ports:
      - name: http
        protocol: TCP
        port: 8000
        targetPort: 8000
  2. 將 vLLM TorchTPU 伺服器資訊清單套用至叢集:

    envsubst '$VLLM_IMAGE' < "qwen3_5_server.yaml" | kubectl apply -f -
  3. 監控伺服器部署記錄,直到應用程式啟動完成:

    kubectl wait --for=jsonpath='{.status.phase}'=Running pod -l app=vllm-qwen3-5 --timeout=900s
    kubectl logs deployment/vllm-qwen3-5 -c vllm-tpu -f

    Pod 下載模型權重並編譯模型時,初始服務啟動作業可能需要約 20 到 30 分鐘。

    如果您使用 Spot 或彈性啟動等先占式運算資源,建立節點集區後,可能需要較長時間才能建立 TPU 切片節點,而且這些節點可能會在工作負載執行期間遭到先占。如果 Pod 啟動時間比預期長,或工作負載中途停止,可能就是這個原因。詳情請參閱「Spot VM 先占」。如要確認 TPU 切片節點是否已建立,請參閱「查看節點的狀態和條件」。

    請等到記錄回報 Application startup complete 後,再傳送流量:

    (APIServer pid=1) INFO:     Started server process [1]
    (APIServer pid=1) INFO:     Waiting for application startup.
    (APIServer pid=1) INFO:     Application startup complete.
    
  4. 開啟第二個終端機工作階段。

  5. 在第二個終端機工作階段中,將本機通訊埠 8000 轉送至 vllm-qwen3-5-service:

    kubectl port-forward service/vllm-qwen3-5-service 8000:8000

    在這個終端機工作階段中,讓通訊埠轉送功能保持運作。

傳送推論要求

返回第一個終端機工作階段,並向 /v1/chat/completions 端點傳送對話完成要求:

curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "Qwen/Qwen3.5-397B-A17B-FP8",
        "messages": [
            {"role": "user", "content": "Hello! Tell me a joke."}
        ],
        "max_tokens": 512,
        "temperature": 0.7
    }' | jq .

執行基準工作負載

如要使用 InferenceX 基準套件,以 8,192 個輸入詞元和 1,024 個輸出詞元 (8k/1k) 的工作負載,對已部署的 Qwen3.5 397B 模型進行基準測試,請完成下列步驟:

  1. 擷取基準測試資訊清單:

    curl -O https://raw.githubusercontent.com/GoogleCloudSamples/AIHypercomputerSamples/refs/heads/main/tpu/inference/qwen3-5-397b/qwen3_5-benchmark-8k1k.yaml

    或者,您也可以建立名為 qwen3_5-benchmark-8k1k.yaml 的檔案,並在當中加入下列內容:

    apiVersion: v1
    kind: Pod
    metadata:
      name: qwen3-5-bench-8k1k
      namespace: default
    spec:
      restartPolicy: OnFailure
      terminationGracePeriodSeconds: 60
      containers:
      - name: vllm-bench
        image: $VLLM_IMAGE
        command: ["/bin/bash", "-c"]
        args:
        - |
          while ! curl http://vllm-qwen3-5-service:8000/ping; do sleep 30 && echo 'Waiting for server...'; done
          apt-get update && apt-get install -y git && \
          git clone https://github.com/SemiAnalysisAI/InferenceX.git /ubench/inferencex && \
          cd /ubench/inferencex && \
          git checkout 89ce6098ef2bc4576a735c43f39c7d972b091cfc && \
          python3 /ubench/inferencex/utils/bench_serving/benchmark_serving.py \
            --backend=vllm \
            --percentile-metrics='ttft,tpot,itl,e2el' \
            --host=vllm-qwen3-5-service \
            --port=8000 \
            --model=Qwen/Qwen3.5-397B-A17B-FP8 \
            --tokenizer=Qwen/Qwen3.5-397B-A17B-FP8 \
            --dataset-name=random \
            --random-input-len=8192 \
            --random-output-len=1024 \
            --random-range-ratio=1.0 \
            --num-prompts=2560 \
            --num-warmups=512 \
            --max-concurrency=256 \
            --ignore-eos
        env:
        - name: HUGGING_FACE_HUB_TOKEN
          valueFrom:
            secretKeyRef:
              key: hf_api_token
              name: hf-secret
  2. 套用基準測試 Pod 資訊清單:

    envsubst '$VLLM_IMAGE' < "qwen3_5-benchmark-8k1k.yaml" | kubectl apply -f -
  3. 監控基準測試記錄:

    kubectl logs -f qwen3-5-bench-8k1k

    基準測試約需 25 到 30 分鐘才能完成。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶持續收取本教學課程所用資源的額外費用,請刪除 Kubernetes 工作負載、TPU 節點集區和 GKE 叢集:

  1. 刪除 vLLM TorchTPU 伺服器 Deployment、Service、PersistentVolumeClaim 和基準測試 Pod:

    kubectl delete -f qwen3_5_server.yaml --ignore-not-found || true
    kubectl delete secret hf-secret --ignore-not-found || true
  2. 刪除 TPU7x 節點集區和 GKE 叢集:

    gcloud container node-pools delete "${NODE_POOL_NAME}" \
        --cluster="${CLUSTER_NAME}" \
        --location="${REGION}" \
        --project="${PROJECT_ID}" \
        --quiet || true
    
    gcloud container clusters delete "${CLUSTER_NAME}" \
        --location="${REGION}" \
        --project="${PROJECT_ID}" \
        --quiet || true

後續步驟