7. 安装 LeaderWorkerSet 控制器
LWS 本身需要先安装控制器和 CRD。本文实践中使用 Helm 安装。
CHART_VERSION=0.7.0
mkdir -p ~/lws-offline
helm pull oci://registry.k8s.io/lws/charts/lws
--version $CHART_VERSION
--destination ~/lws-offline
tar -zxvf lws-0.7.0.tgz
helm install lws ./
--namespace lws-system
--create-namespace
--wait --timeout 300s
安装完成后检查控制器,正常情况下可以看到:
kubectl get pods -n lws-system
NAME READY STATUS
lws-controller-manager-xxxxxxxxx-xxxxx 1/1 Running
继续检查 CRD 是否注册成功,如果看到如下的结果,说明 LWS API 已经注册到 Kubernetes 中,可以开始创建 LeaderWorkerSet 资源。
kubectl get crd | grep leaderworkerset
leaderworkersets.leaderworkerset.x-k8s.io
kubectl api-resources | grep -i leader
leaderworkersets lws leaderworkerset.x-k8s.io/v1 true LeaderWorkerSet
8. 部署基于 LWS 的 vLLM 多机推理服务
在本文实践中,使用 LeaderWorkerSet 部署一个基于 Ray + vLLM 的 Qwen3-32B 多机推理服务。
核心 YAML 结构如下:
apiVersion: leaderworkerset.x-k8s.io/v1
kind: LeaderWorkerSet
metadata:
name: vllm
spec:
replicas: 1
leaderWorkerTemplate:
size: 6
restartPolicy: RecreateGroupOnPodRestart
leaderTemplate:
metadata:
labels:
role: leader
spec:
containers:
- name: vllm-leader
image: 10.8.17.100:60066/model/vllm:202511260714
command:
- sh
- -c
- |
bash /workspace/multi-node-serving.sh leader --ray_cluster_size=$(LWS_GROUP_SIZE);
/opt/conda/bin/python3 -m vllm.entrypoints.openai.api_server
--port 8080
--model /workspace/model/Qwen3-32B
--tensor-parallel-size 4
--pipeline_parallel_size 1
resources:
limits:
mars-tech.com/gpu: 4
memory: 96Gi
ephemeral-storage: 50Gi
requests:
mars-tech.com/gpu: 4
cpu: 16
memory: 96Gi
ephemeral-storage: 50Gi
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /dev/shm
name: dshm
- mountPath: /workspace/model
name: localmodelvolume
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
- name: localmodelvolume
persistentVolumeClaim:
claimName: vllm-model-pvc
workerTemplate:
spec:
containers:
- name: vllm-worker
image: 10.8.17.100:60066/model/vllm.202511260714
command:
- sh
- -c
- |
bash /workspace/multi-node-serving.sh worker --ray_address=$(LWS_LEADER_ADDRESS)
resources:
limits:
mars-tech.com/gpu: 4
memory: 96Gi
ephemeral-storage: 50Gi
requests:
mars-tech.com/gpu: 4
cpu: 16
memory: 96Gi
ephemeral-storage: 50Gi
volumeMounts:
- mountPath: /dev/shm
name: dshm
- mountPath: /workspace/model
name: localmodelvolume
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
- name: localmodelvolume
persistentVolumeClaim:
claimName: vllm-model-pvc
同时创建一个 Service,只暴露 leader Pod:
apiVersion: v1
kind: Service
metadata:
name: vllm-leader
spec:
type: NodePort
selector:
leaderworkerset.sigs.k8s.io/name: vllm
role: leader
ports:
- name: http
port: 8080
targetPort: 8080
nodePort: 32064
这个 YAML 中有几个关键点。
replicas: 1 表示创建一个分布式推理 group。
leaderWorkerTemplate.size: 6 表示每个 group 中一共有 6 个 Pod,其中 1 个 leader,5 个 worker。
restartPolicy: RecreateGroupOnPodRestart 表示组内任意 Pod 重启时,整组会重建。这可以避免分布式推理组内部出现 leader / worker 状态不一致的问题。
leaderTemplate 定义 leader Pod,它负责启动 Ray head 和 vLLM API Server。
workerTemplate 定义 worker Pod,它负责连接 leader 的 Ray head 并作为 Ray worker 参与推理。
k8s.v1.cni.cncf.io/networks 是 Multus 网络注解,用于给 leader 和 worker 挂载额外网络。实际环境中,是否需要 Multus、macvlan 或 RDMA 网络,需要结合集群网络设计决定。
/dev/shm 使用 memory 类型的 emptyDir,是为了给推理进程提供更大的共享内存空间。
/workspace/model 挂载模型 PVC,保证 leader 和 worker 都能访问相同的模型文件。
9. 启动状态检查
应用 YAML 后,先检查 StatefulSet:
kubectl get statefulsets
NAME READY AGE
vllm 1/1 4h32m
vllm-0 5/5 3h38m
这里说明:
vllm:
leader StatefulSet,负责 leader Pod
vllm-0:
group 0 的 worker StatefulSet,负责 5 个 worker Pod
继续检查 Pod:
kubectl get pods -n default
-l leaderworkerset.sigs.k8s.io/name=vllm
-L role
返回结果类似:
NAME READY STATUS ROLE
vllm-0 1/1 Running leader
vllm-0-1 1/1 Running
vllm-0-2 1/1 Running
vllm-0-3 1/1 Running
vllm-0-4 1/1 Running
vllm-0-5 1/1 Running
这说明一个完整的 group 已经起来:
vllm-0 leader
vllm-0-1 worker
vllm-0-2 worker
vllm-0-3 worker
vllm-0-4 worker
vllm-0-5 worker
接下来查看 leader 日志:
kubectl logs vllm-0 -n default -c vllm-leader | tail -n 100
重点关注几类信息。
<span style="color: rgba(203, 145, 47, 1);"><strong># 通过日志查看详细的启动流程</strong></span>
kubectl logs vllm-0 -n default
kubectl logs vllm-0 -n default -c vllm-leader | tail -n 80
# 关键信息
<span style="color: rgba(193, 76, 138, 1);"><strong>1. Ray 集群已经拉起来并完成 worker 注册:
</strong></span>Wait for all ray workers to be active. 5/6 is active
2025-12-04 19:45:30,458 INFO worker.py:1694 -- Connecting to existing Ray cluster at address: 192.168.4.142:6379...
2025-12-04 19:45:30,474 INFO worker.py:1888 -- Connected to Ray cluster.<span style="color: rgba(193, 76, 138, 1);">
</span>All ray workers are active and the ray cluster is initialized successfully.
<span style="color: rgba(193, 76, 138, 1);"><strong>2. vLLM OpenAI API 服务器也已经启动流程:
</strong></span>INFO ... vLLM API server version 0.8.5
INFO ... args: ... model='/workspace/model/Qwen3-32B' ...
<span style="color: rgba(193, 76, 138, 1);"><strong>3. 开始初始化 vLLM 引擎,并用这个本地模型:
</strong></span>INFO ... Initializing a V1 LLM engine ... model='/workspace/model/Qwen3-32B', tokenizer='/workspace/model/Qwen3-32B'
<span style="color: rgba(193, 76, 138, 1);"><strong>
4. 模型正在一点点从 PVC / NFS 里读出来并加载到 GPU:
</strong></span>INFO ... Starting to load model /workspace/model/Qwen3-32B...
Loading safetensors checkpoint shards: 6% Completed | 1/17 [00:27<07:13, 27.12s/it]
INFO ... Starting to load model /workspace/model/Qwen3-32B...
Loading safetensors checkpoint shards: 88% Completed | 15/17 [...]
Loading safetensors checkpoint shards: 100% Completed | 17/17 [...]
INFO ... Loading weights took 309.10 seconds
INFO ... Model loading took 61.0347 GiB and 309.859165 seconds
👉 说明 /workspace/model/Qwen3-32B 里的 17 片 model-000xx-of-00017.safetensors已经全部成功读到 GPU 里了,占用大约 61 GiB 显存。这一步完全成功。
<span style="color: rgba(193, 76, 138, 1);"><strong>5. 最后启动完成
</strong></span>INFO: Started server process [8501]
INFO: Waiting for application startup.
INFO: Application startup complete.
# 检查statefulset,一个leader,一个worker
kubectl get statefulsets
NAME READY AGE
vllm 1/1 4h32m
vllm-0 5/5 3h38m
# 确认pod中哪个是leader pod
kubectl get pods -n default
> -l leaderworkerset.sigs.k8s.io/name=vllm
> -L role
NAME READY STATUS RESTARTS AGE ROLE
vllm-0 1/1 Running 0 3h30m leader
vllm-0-1 1/1 Running 0 3h30m
vllm-0-2 1/1 Running 0 3h30m
vllm-0-3 1/1 Running 0 3h30m
vllm-0-4 1/1 Running 0 3h30m
vllm-0-5 1/1 Running 0 3h30m
第一,Ray worker 是否全部注册成功:
Wait for all ray workers to be active. 5/6 is active
Connected to Ray cluster.
All ray workers are active and the ray cluster is initialized successfully.
第二,vLLM API Server 是否开始启动:
vLLM API server version ...
Initializing a V1 LLM engine ...
model='/workspace/model/Qwen3-32B'
第三,模型权重是否成功加载:
Loading safetensors checkpoint shards: 100% Completed
Loading weights took 309.10 seconds
Model loading took 61.0347 GiB
第四,API Server 是否启动完成:
Started server process
Application startup complete.
这些日志说明,Ray 集群已经建立,worker 已经注册,模型已经从 PVC 加载,vLLM API Server 已经启动。至此,LWS + Ray + vLLM 的多机推理服务已经完成启动。
11. 接口验证
服务启动后,可以通过 NodePort 访问 leader 暴露的 OpenAI 兼容接口。先查看模型列表:
curl http://10.8.17.218:32064/v1/models
再调用 Chat Completions 接口:
curl -X POST http://10.8.17.218:32064/v1/chat/completions
-H "Content-Type: application/json"
-d '{
"model": "/workspace/model/Qwen3-32B",
"messages": [
{
"role": "user",
"content": "你好,请简单自我介绍一下"
}
]
}'
如果能够正常返回模型输出,说明外部请求已经可以进入 leader,并由 vLLM 完成推理。在正式环境中,建议进一步通过 Gateway API 或 AI Gateway 暴露统一入口,而不是直接使用 NodePort。NodePort 更适合部署验证和内部调试。
10. 关于网络与 RDMA 的说明
在多机推理中,网络路径非常重要。但本小节只为介绍LWS,所以 YAML 中并未引入过多复杂的参数或环境变量,实际生产环境需要通过可能需要高速的RDMA网络。在具体的实践中,可以把网络分成两个层次理解。
第一层是 Ray 的控制和管理通信。Ray head 与 Ray workers 之间的注册、调度和管理通信通常基于 IP 网络进行。因此,Multus/macvlan 可以用于提供一张独立的高速业务网络,让 leader 和 worker 之间通过该网络互通。
第二层是模型并行相关的数据通信。如果 vLLM 的分布式推理涉及跨 GPU 或跨节点 collective communication,则底层可能涉及 NCCL 等通信库。是否使用 RDMA,不应该仅凭 YAML 中是否申请了 RDMA 资源来判断,而应该结合 NCCL 日志、网卡流量、RDMA counters、容器内 /dev/infiniband 可见性以及实际环境变量进行验证。
11. LWS 与 Ray 的关系
LWS 和 Ray 经常一起出现,但它们不是同一层东西。Ray 是分布式运行时。它负责 worker 管理、任务调度、分布式执行和运行时通信。对于 vLLM 多节点推理来说,Ray 可以作为 worker 组织和执行框架。LWS 是 Kubernetes 工作负载 API。它负责把一组 leader / worker Pod 作为一个整体部署、更新、重启和扩缩容。二者的关系可以理解为:
Kubernetes / LWS:
管 Pod,管 group,管生命周期
Ray:
管进程,管 worker,管分布式执行
vLLM:
管模型,管推理,管 OpenAI API
换句话说,Ray 解决的是“组内怎么运行”,LWS 解决的是“这一组 Pod 在 Kubernetes 中怎么表达和管理”。如果没有 LWS,也可以手工用 StatefulSet、Service、脚本等方式拼出 Ray + vLLM 集群;但这种方式会让 group 生命周期、滚动更新、扩缩容和故障恢复变得更复杂。LWS 的价值,就是把这种常见分布式推理模式抽象成一个更清晰的 Kubernetes API。
12. 小结
LeaderWorkerSet 解决的是 Kubernetes 层面的工作负载表达问题,当一个模型副本不再是一个 Pod,而是一组必须协同工作的 Pod 时,Kubernetes 应该如何部署、更新、重启和扩缩这一组 Pod。对于多机推理来说,这一点非常关键。
LWS 将 leader 和 worker 组织成一个 group,使其具备统一生命周期;通过 scale subresource,让 HPA 可以按 group 数量扩缩容;通过 group-level rolling update,让模型服务可以按组滚动发布;通过 all-or-nothing restart,让分布式推理组在异常时重新恢复一致状态;通过 topology-aware placement,为后续更精细的拓扑放置提供能力基础。
在云原生 AI 平台中,随着模型规模从单机走向多机,工作负载的基本单位也在发生变化:
单 Pod 推理
→ 多 Pod 协同推理
单副本 Deployment
→ group 级推理副本
Pod 级扩缩容
→ group 级扩缩容
Pod 级滚动更新
→ group 级滚动更新
这也是 LWS 在 AI 基础设施中的价值所在。它让 Kubernetes 不再只是“运行很多 Pod”,而是能够以更贴近大模型推理实际形态的方式,管理一组协同工作的推理单元。
