This tutorial shows you how to deploy and serve
Qwen3-Coder-30B-A3B (Qwen/Qwen3-Coder-30B-A3B-Instruct-FP8),
a mixture of experts coding model, on Google Kubernetes Engine (GKE). The deployment
uses multi-host TPU v6e (Trillium) accelerators and the
SGLang serving framework with
TorchTPU (torchtpu) and prefill-decode (PD) disaggregation.
In the deployment configuration that's described in this tutorial, you provision
two multi-host ct6e-standard-4t node pools, each arranged in a 2x4
topology (eight TPU v6e chips across two nodes per node pool, for a total of 16
TPU v6e chips). You use the Kubernetes LeaderWorkerSet API to do the following:
- Run disaggregated multi-host prefill and decode servers on separate TPU v6e slices with tensor parallelism and expert parallelism enabled.
- Route requests through an SGLang disaggregation router.
To run a similar multi-host SGLang TorchTPU serving workflow on TPU7x (Ironwood) accelerators with the larger Qwen3-Coder-480B model, see Serve Qwen3-Coder-480B on GKE with multi-host SGLang TorchTPU and PD disaggregation on TPU7x accelerators.
Objectives
- Set up your GKE cluster and multi-host TPU v6e node pools.
- Configure credentials and install the LeaderWorkerSet controller.
- Deploy the multi-host SGLang prefill, decode, and router workloads.
- Send an inference request to the SGLang router service.
- Run a serving benchmark workload.
- Clean up.
Costs
In this document, you use the following billable components of Google Cloud:
To generate a cost estimate based on your projected usage, use the pricing calculator.
When you finish the tasks that are described in this document, you can avoid continued billing by deleting the resources that you created. For more information, see Clean up.
Before you begin
Set up your environment for the tutorial:
Install and initialize the Google Cloud CLI, and install
kubectl. If you use Cloud Shell, both tools are preinstalled.Enable the Kubernetes Engine API, Compute Engine API, Cloud TPU API, and Artifact Registry API in your Google Cloud project:
Ensure that your project has sufficient disk quota and external IP address quota in the region where your TPU capacity is located:
In the Google Cloud console, go to the Quotas & System Limits page.
Verify that you have at least 400 GiB of available Google Cloud Hyperdisk Balanced quota across the four 100 GiB ephemeral volumes that are used for model caching by the prefill and decode Pods.
Filter by In-use regional external IPv4 addresses and verify that you have sufficient IP address quota in your target region.
Get a Hugging Face access token
You need a Hugging Face access token to use this tutorial. You can sign up for a free account at Hugging Face. After you have an account, generate an access token:
- On the Welcome to Hugging Face page, click your account avatar and select Access tokens.
- On the Access tokens page, click Create new token.
- Select the Read token type and enter a name for your token.
- Your access token is displayed. Save the token in a safe place.
Required roles
To get the permissions that you need to complete this tutorial, ask your administrator to grant you the following IAM roles on your project:
- Kubernetes Engine Admin (
roles/container.admin) - Compute Admin (
roles/compute.admin) - Service Account User (
roles/iam.serviceAccountUser)
For more information about granting roles, see Manage access to projects, folders, and organizations.
You might also be able to get the required permissions through custom roles or other predefined roles.
Ensure that your Compute Engine default service account has the following Identity and Access Management (IAM) roles on your project:
- Kubernetes Engine Default Node Service Account
(
roles/container.defaultNodeServiceAccount) - Artifact Registry Reader
(
roles/artifactregistry.reader)
Set up your environment variables
Export the environment variables that you use throughout this tutorial:
Replace the following:
YOUR_CLUSTER_NAME: the name of your GKE cluster.YOUR_PROJECT_ID: the ID of your Google Cloud project.YOUR_REGION: the region where you want to deploy your cluster, such asus-central1.YOUR_ZONE: the zone where you want to deploy your TPU v6e node pools, such asus-central1-b.YOUR_RESERVATION_NAME: if you're using a reservation, the name of your TPU v6e reservation.YOUR_HF_TOKEN: your Hugging Face access token.
If you're using a custom SGLang TorchTPU container image, replace
lmsysorg/sglang:v0.1.0-tpu in the SGLANG_IMAGE variable with the URI of your
image.
Create the GKE cluster
To create a GKE cluster in Standard mode and attach two multi-host TPU v6e node pools for prefill and decode disaggregation, complete the following steps:
Create a regional GKE cluster that uses
e2-standard-4nodes for the default node pool, which provides sufficient CPU and memory resources for the LeaderWorkerSet controller and the SGLang disaggregation router:Create two multi-host TPU v6e node pools, each containing two
ct6e-standard-4tnodes (eight TPU v6e chips in a2x4topology per node pool, for a total of 16 TPU v6e chips):Instead of using a specific reservation, you can also create the node pools using Spot capacity or Flex-start VMs:
Spot VMs
Provision the node pools using Spot capacity by replacing the
--reservation-affinity=specificand--reservation="${RESERVATION}"flags with the--spotflag:Instances using Spot capacity might take time to be created after the node pool is created, and they might be preempted during workload runs.
Flex-start VMs
Provision the node pools using the Flex-start consumption option:
For more information, see Run a small batch workload with TPUs and Flex-start VMs.
Configure
kubectlcredentials to communicate with your cluster:
Configure credentials and install LeaderWorkerSet
To prepare your cluster for the multi-host SGLang deployment, complete the following steps:
Create a Kubernetes Secret named
hf-secretto store your Hugging Face access token:Install the LeaderWorkerSet CustomResourceDefinition and controller on your cluster:
Deploy the multi-host SGLang server
The workload manifest (qwen3-coder-30b-multihost-disagg-v6e-2x4.yaml) defines
the following resources to coordinate disaggregated prefill and decode serving
across the two 2x4 TPU v6e node pools:
StorageClass (
hyperdisk-balanced-tpu): provisions ephemeral 100 GiB ReadWriteOnce volumes backed by Google Cloud Hyperdisk Balanced storage. Each of the four prefill and decode Pods mounts its own volume at/datato store the downloadedQwen/Qwen3-Coder-30B-A3B-Instruct-FP8checkpoints locally.Prefill pool (
sglang-prefill-serviceandsglang-tpu-prefill): runs a LeaderWorkerSet, which contains one leader Pod and one worker Pod, pinned exclusively to one2x4TPU v6e node pool. This node pool has eight TPU chips, which provide eight TensorCores. The LeaderWorkerSet uses theleaderworkerset.sigs.k8s.io/exclusive-topologyannotation set to"cloud.google.com/gke-nodepool". The Pods launchsglang.launch_serverwith the following flags, exposing port8000and bootstrap port8998:--disaggregation-mode=prefill--tensor-parallel-size=8--ep-size=8
Decode pool (
sglang-decode-serviceandsglang-tpu-decode): runs a LeaderWorkerSet ofsize: 2pinned to the second2x4TPU v6e node pool (eight TPU chips, which provide eight TensorCores). The LeaderWorkerSet launchessglang.launch_serverwith the following flags:--disaggregation-mode=decode--tensor-parallel-size=8--ep-size=8
Disaggregation router (
sglang-routerandsglang-service): runs a CPU deployment that executes thesglang_router.launch_routermodule with the--pd-disaggregationflag and exposes a ClusterIP Service on port8000. The router directs prompts and coordinates KV cache transfer between thesglang-prefill-serviceandsglang-decode-serviceservices.
To deploy and monitor the multi-host SGLang servers, complete the following steps:
Download the workload manifest:
Alternatively, create a file named
qwen3-coder-30b-multihost-disagg-v6e-2x4.yamlwith the following content:Apply the workload manifest to your cluster:
Verify that the router, prefill, and decode Pods are created:
When all Pods are ready, the output is similar to the following:
NAME READY STATUS RESTARTS AGE sglang-router-6d87cb8c7d-gv4wr 1/1 Running 0 39m sglang-tpu-decode-0 1/1 Running 0 40m sglang-tpu-decode-0-1 1/1 Running 0 40m sglang-tpu-prefill-0 1/1 Running 0 40m sglang-tpu-prefill-0-1 1/1 Running 0 40mMonitor the prefill and decode leader Pod logs until startup has completed:
Initial model download, weight loading, and compilation take approximately seven to ten minutes on the first run.
If you're using preemptible capacity such as Spot capacity or Flex-start VMs, it might take longer after node pool creation for your TPU slice nodes to be created, and they might be preempted during workload runs. For more information, see Preemptible VM instances. To check whether your TPU slice nodes have been created, see Check the node's status and conditions.
Wait until both the prefill and decode leader Pod logs output the following message and
kubectl get podsshows1/1in theREADYcolumn for all Pods:The server is fired up and ready to roll!Open a second terminal session and forward local port
8000tosglang-service:Leave port forwarding running in this terminal session.
Send inference requests
Return to your first terminal session and send a chat completion request to the
/v1/chat/completions endpoint exposed by the SGLang router:
Run a benchmark workload
To benchmark the deployed Qwen3-Coder-30B-A3B model using a 1,024-token input
and 1,024-token output (1k/1k) workload from the sglang-router Pod, run the
following command:
After the benchmark has completed, look for output that contains metrics such as the following:
Output token throughputTotal token throughputTTFTTPOT
Clean up
To avoid incurring additional ongoing charges to your Google Cloud account for the resources used in this tutorial, delete the following resources:
Delete the SGLang prefill, decode, and router workloads:
Delete the TPU v6e node pools and the GKE cluster:
What's next
- Learn more about SGLang.
- Learn more about TPU v6e (Trillium).
- Learn more about Cloud TPU.