Multi-node replicas¶
How to run one model replica across two 8-card nodes, and what changes on Kubernetes when a replica is a group of pods instead of one pod.
Most models here fit one node; prefer that whenever a recipe offers it. Two nodes are for checkpoints that do not fit 8 cards in the format you want to serve (for example FP8 experts of a 700B to 1T model), or for a KV pool larger than one node holds.
Two ways to split a model¶
| Pipeline parallel (PP 2 x TP 8) | Tensor parallel 16 | |
|---|---|---|
| What crosses the nodes | one hidden-state row per token, between stages | every layer's all-reduce |
| Link | the ordinary pod or host network (gloo) | RoCE scale-out ports on both nodes, configured for HCCL |
| Software | the pipeline-parallel fix, --no-async-scheduling |
stock collectives; an executor that spans nodes |
| Placement | any two whole nodes | only node pairs whose scale-out links reach each other |
| Verified here | yes, on v0.26.0 and v0.30.0 (below) |
no |
Pipeline parallelism is the one to start with: it needs no fabric, and any two free nodes form a replica. Its cost is a pipeline bubble at low concurrency and the loss of async scheduling. Tensor parallelism across nodes is faster per stream when the fabric exists, but it ties each replica to a cabled pair.
The replica is the group¶
Two pods that form one engine behave like one pod with two halves:
- Restart together. A stage cannot rejoin a running pipeline (or a running tensor-parallel group). If either pod dies, the other hangs on its next transfer. Recreate the whole group.
- Route to the leader only. The node with rank 0 runs the API server; the other node runs headless and has no HTTP port. The Service selects the leader.
- Probe the leader. The leader's
/healthreflects the whole engine: a lost stage stops its steps. The worker gets no HTTP probes; group restart covers it. - Scale and roll by group. An autoscaler or rollout adds or removes whole groups. With
maxSurge 0, a rollout of a single group drops the model to zero replicas while it restarts. - Schedule whole nodes. Each pod requests all 8 cards, which keeps the two stages on different nodes without an anti-affinity rule. Both pods must be placed before either can start; a group with one pod Pending holds 8 cards idle.
LeaderWorkerSet expresses these rules directly
(size: 2, RecreateGroupOnPodRestart, LWS_LEADER_ADDRESS for the master address). An
AIBrix StormService with a pod group of two, or a
Ray cluster per replica for builds that use Ray, are alternatives with the same rules.
Example¶
kubernetes/manifests/vllm-two-node-pipeline.yaml
is a LeaderWorkerSet for PP 2 x TP 8. The two vllm serve commands inside are the verified
ones; the LeaderWorkerSet around them was not applied on a cluster, so treat it as a starting
point. The essentials:
python3 fixes/apply_all.py --profile v0.30.0 pipeline-parallel || exit 1
export GLOO_SOCKET_IFNAME=eth0 VLLM_HOST_IP=<this pod's IP>
# leader
vllm serve <model> --tensor-parallel-size 8 --pipeline-parallel-size 2 --no-async-scheduling \
--distributed-executor-backend mp --nnodes 2 --node-rank 0 --master-addr <leader IP> --master-port 29555 ...
# worker: the same with --node-rank 1 --headless
Measured¶
Qwen3-30B-A3B-Instruct-2507 at TP 2 on each of two nodes (PP 2), against TP 2 on one node,
pods on the pod network, --no-async-scheduling, Gaudi software 1.24.1.
| Check | Result |
|---|---|
| Greedy answers, 12 prompts | identical to one node, both releases |
| Teacher-forced top-1 tokens, 8,441 positions | identical (NLL 1.4425 both) |
| Needles at 12K | 3 of 3 |
Decode per stream, and in brackets the aggregate (all tokens over the wall time, prefill included), in tok/s, 2K cached prefix, 128 new tokens. Measured as: same two pods, separate server starts for one node and two nodes, one run each.
| Release | Streams | One node, TP 2 | Two nodes, PP 2 x TP 2 |
|---|---|---|---|
v0.30.0 |
1 | 36.2 (31.5) | 30.4 (26.4) |
v0.30.0 |
4 | 34.1 (119.3) | 28.2 (109.2) |
v0.30.0 |
8 | 31.5 (235.0) | 25.1 (179.3) |
v0.26.0 |
1 | 36.1 (31.6) | 30.2 (26.2) |
v0.26.0 |
4 | 34.1 (121.2) | 27.3 (105.6) |
v0.26.0 |
8 | 31.8 (237.3) | 23.1 (166.1) |
A model this small loses about 17% per stream to the stage hop and the pipeline bubble; the point of two nodes is fitting what one node cannot hold. For a large model on this path, see Two-node pipeline parallel.