このチュートリアルでは、Google Kubernetes Engine(GKE)に Mixture of Experts モデルである Qwen3-30B-A3B(Qwen/Qwen3-30B-A3B-FP8)をデプロイして提供する方法について説明します。このデプロイでは、マルチホスト TPU v6e(Trillium)アクセラレータと、TorchTPU(torchtpu)およびプレフィルデコード(PD)分離を備えた vLLM TPU サービング フレームワークを使用します。
このチュートリアルで説明するデプロイ構成では、2 つのマルチホスト ct6e-standard-4t ノードプールをプロビジョニングします。各ノードプールは 2x4 トポロジで配置されます(ノードプールごとに 2 つのノードに 8 つの TPU v6e チップ、合計 16 個の TPU v6e チップ)。Kubernetes JobSet API と Ray を使用して、次のことを行います。
- データ並列処理とエキスパート並列処理を有効にして、分離されたマルチホスト プリフィル サーバーとデコード サーバーを別々の TPU v6e スライスで実行します。
- リクエストを分離プロキシ経由でルーティングする。
より大きな Qwen3.5-397B モデルを使用して TPU7x(Ironwood)アクセラレータで同様のマルチホスト vLLM TorchTPU サービング ワークフローを実行するには、TPU7x アクセラレータでマルチホスト vLLM TorchTPU を使用して GKE で Qwen3.5-397B をサービングするをご覧ください。
目標
- GKE クラスタとマルチホスト TPU v6e ノードプールを設定します。
- モデルの重みを Cloud Storage バケットにステージングします。
- JobSet を使用して、マルチホスト vLLM TorchTPU プリフィル、デコード、プロキシ サーバーをデプロイします。
- サービング ベンチマーク ワークロードを実行し、結果を分析する。
- クリーンアップする。
費用
このドキュメントでは、課金対象である次のGoogle Cloudコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
チュートリアルの環境を設定します。
Google Cloud プロジェクトで Kubernetes Engine API を有効にします。
Google Cloud CLI をインストールして初期化し、
kubectlをインストールします。Cloud Shell を使用する場合、どちらのツールもプリインストールされています。TPU 容量が配置されているリージョンに、プロジェクトの SSD 割り当てと外部 IP アドレス割り当てが十分にあることを確認します。
Google Cloud コンソールで、[割り当てとシステム上限] ページに移動します。
Persistent Disk SSD(GB)でフィルタし、ターゲット リージョンに十分な SSD 割り当てがあることを確認します。
[使用中のリージョン外部 IPv4 アドレス] でフィルタし、ターゲット リージョンに十分な IP アドレスの割り当てがあることを確認します。
Hugging Face アクセス トークンを取得する
このチュートリアルを使用するには、Hugging Face アクセス トークンが必要です。Hugging Face で無料アカウントに登録できます。アカウントを作成したら、アクセス トークンを生成します。
- [Welcome to Hugging Face] ページで、アカウントのアバターをクリックし、[アクセス トークン] を選択します。
- [アクセス トークン] ページで、[Create new token] をクリックします。
- [Read] トークン タイプを選択し、トークンの名前を入力します。
- アクセス トークンが表示されます。トークンを安全な場所に保存します。
必要なロール
このチュートリアルを完了するために必要な権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。
- Kubernetes Engine 管理者(
roles/container.admin) - Compute 管理者(
roles/compute.admin) - ストレージ管理者 (
roles/storage.admin) - サービス アカウント ユーザー(
roles/iam.serviceAccountUser)
ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。
環境変数を設定する
環境変数を設定する手順は次のとおりです。
認証を設定します。
このチュートリアル全体で使用する環境変数をエクスポートします。
次のように置き換えます。
YOUR_PROJECT_ID: 実際のGoogle Cloud プロジェクト ID。YOUR_REGION: クラスタをデプロイするリージョン(us-central1など)。YOUR_ZONE: TPU v6e ノードプールをデプロイするゾーン(us-central1-cなど)。YOUR_CLUSTER_NAME: GKE クラスタの名前。YOUR_RESERVATION_NAME: 予約を使用している場合は、TPU v6e 予約の名前。YOUR_GCS_BUCKET: モデルの重みのステージングに使用する Cloud Storage バケットの名前。YOUR_HF_TOKEN: Hugging Face アクセス トークン。
カスタム vLLM TorchTPU コンテナ イメージを使用している場合は、
VLLM_IMAGE変数のデフォルトのvllm/vllm-torchtpuイメージ URI をイメージの URI に置き換えます。公開イメージについては、vLLM TorchTPU リポジトリをご覧ください。
GKE クラスタを作成する
Standard モードで GKE クラスタを作成し、プリフィルとデコードの分離用に 2 つのマルチホスト TPU v6e ノードプールを接続するには、次の操作を行います。
Workload Identity Federation for GKE を有効にしてリージョン GKE クラスタを作成します。
出力は次のようになります。
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS STACK_TYPE asq-v6e us-central1 1.35.7-gke.1027000 35.226.172.84 e2-standard-4 1.35.7-gke.1027000 3 RUNNING IPV42 つのマルチホスト TPU v6e ノードプールを作成します。各ノードプールには 2 つの
ct6e-standard-4tノードが含まれます(ノードプールごとに2x4トポロジの 8 つの TPU v6e チップ、合計 16 個の TPU v6e チップ)。このチュートリアルでは、Spot 容量(
--spot)を使用します。Spot 容量を使用するインスタンスは、ノードプールの作成後に作成されるまでに時間がかかることがあり、ワークロードの実行中にプリエンプトされる可能性があります。次のフラグを渡して、予約または Flex Start VM を使用してノードプールを作成することもできます。特定の予約: 特定の予約を使用してノードプールを作成します。
TPU 予約の詳細については、Cloud TPU の予約についてをご覧ください。
Flex Start VM: Flex Start 消費オプションを使用してノードプールをプロビジョニングします。
詳細については、TPU と Flex Start VM で小規模なバッチ ワークロードを実行するをご覧ください。
各ノードプールの出力は次のようになります。
NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION np-0 ct6e-standard-4t 100 1.35.7-gke.1027000クラスタと通信するように
kubectl認証情報を構成します。
Cloud Storage にモデルの重みをステージングする
ワークロードの実行用に、モデルの重みを Cloud Storage バケットにステージングします。
均一なバケットレベルのアクセスが有効な Cloud Storage バケットを作成します。
バケットに対する Identity and Access Management(IAM)権限を、デフォルトの Compute Engine サービス アカウントとデフォルトの Kubernetes サービス アカウントに付与します。
Hugging Face アクセス トークンを保存する
hf-secretという名前の Kubernetes Secret を作成します。download_qwen3_30b.yamlマニフェストを取得します。または、次の内容のファイルを
download_qwen3_30b.yamlという名前で作成します。Qwen/Qwen3-30B-A3B-FP8モデルの重みをステージング ボリュームにダウンロードし、Cloud Storage バケットに転送します。このステップが完了するまでに約 5 ~ 10 分かかります。
Pod が起動するまで待ち、ダウンロード Job のログをモニタリングします。
ジョブが完了したら、16 個の
.safetensorsシャードがすべて Cloud Storage バケットにあることを確認します。完了したステージング ジョブを削除します。
マルチホスト vLLM TorchTPU サーバーをデプロイする
ワークロード マニフェスト(v6e_qwen3_server_multihost_slice.yaml)は、3 つの複製されたジョブを含む Kubernetes JobSet リソース(vllm-qwen3-30b-pd-disagg-v6e)を定義します。これらのジョブは、2 つの 2x4 TPU v6e ノードプール間で分離されたプレフィルとデコードのサービングを調整します。
プリフィル サーバー(
prefill): 1 つの2x4TPU v6e ノードプール(ホストあたり 4 つのチップを搭載した 2 つのct6e-standard-4tノード、合計 8 つの TPU コア)で 2 つのレプリカを実行します。Pod は 2 ノードの Ray クラスタを形成し、Qwen/Qwen3-30B-A3B-FP8のポート8000で vLLM TorchTPU を起動します。サーバーは、次のフラグを使用してkv_producerとして構成されたTPURaidenConnectorを使用します。--data-parallel-size=8--tensor-parallel-size=1--enable-expert-parallel--load-format=runai_streamer
デコード サーバー(
decode): 2 番目の2x4TPU v6e ノードプール(合計 8 個の TPU コア)に 2 つのレプリカを実行します。JobSet は、cloud.google.com/gke-nodepoolラベルの Pod アフィニティ ルールとアンチアフィニティ ルールを使用して、プリフィルとデコードを別々のノードプールに分離します。Pod は 2 ノードの Ray クラスタを形成し、kv_consumerとして構成されたTPURaidenConnectorを使用してポート7200で vLLM TorchTPU を起動します。分離プロキシ(
proxy): ポート10000でtoy_proxy_server.pyスクリプトを実行し、プリフィル サーバー(ポート8000)とデコード サーバー(ポート7200)間のリクエスト ルーティングと KV キャッシュ転送を調整します。
分離された vLLM サーバーをデプロイしてモニタリングする手順は次のとおりです。
Kubernetes JobSet CustomResourceDefinition とコントローラをクラスタにインストールします。
サーバー マニフェストを取得します。
または、次の内容で
v6e_qwen3_server_multihost_slice.yamlという名前のファイルを作成します。Cloud Storage バケット名とコンテナ イメージを
v6e_qwen3_server_multihost_slice.yamlファイルに置き換え、マニフェストを適用します。この構成では、プリフィルに 1 つの
2x4TPU v6e スライス(2 つのノード)を使用し、デコードに 1 つの2x4TPU v6e スライス(2 つのノード)を使用します。いずれかのプールのノード数をスケーリングするには、replicasフィールド(replicas: NUM_NODES)を更新します。NUM_NODESは、使用するノード数に置き換えます。アプリケーションの起動が完了するまで、プリフィル Pod とデコード Pod のログをモニタリングします。
最初の実行では、モデルの初期読み込みとコンパイルに約 15 ~ 25 分かかります。
Spot 容量や Flex Start VM などのプリエンプティブル容量を使用している場合、ノードプールの作成後に TPU スライスノードが作成されるまでに時間がかかることがあります。また、ワークロードの実行中にプリエンプトされる可能性があります。詳細については、プリエンプティブル 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.
ベンチマーク ワークロードを実行する
8,192 トークンの入力と 1,024 トークンの出力(8k/1k)ワークロードを使用して、デプロイされた Qwen3-30B-A3B モデルを分離プロキシに対してベンチマークするには、次の操作を行います。
ベンチマーク マニフェストを取得します。
または、次の内容で
v6e_qwen3_benchmark_multihost_slice.yamlという名前のファイルを作成します。ベンチマーク Job マニフェストを適用します。
ベンチマーク Pod の準備が整うまで待ち、ベンチマーク Job のログをモニタリングします。
ベンチマークが完了したら、次のような指標を含む出力を探します。
Output token throughputTotal token throughputTTFTTPOT
クリーンアップ
このチュートリアルで使用したリソースについて Google Cloud アカウントに課金されないようにするには、Kubernetes ワークロード、TPU v6e ノードプール、GKE クラスタ、Cloud Storage バケットを削除します。
Kubernetes ワークロードを削除します。
TPU v6e ノードプールと GKE クラスタを削除します。
ステージングされたモデルの重みを保存する Cloud Storage バケットを削除します。モデルの重みを保持する場合は、この手順をスキップするか、任意の場所にコピーします。
次のステップ
- Cloud TPU での vLLM の詳細を確認する。
- TPU v6e(Trillium)の詳細を確認する。
- Cloud TPU の詳細を確認する。