vllm多机多卡部署本地环境可行性验证
概览
| 主题 | 状态 | 当日结果 |
|---|---|---|
| Windows 10 + WSL2 多机 vLLM / Ray 可行性验证 | 验证完成 | 使用win10+WSL2 进行 局域网多机多卡部署vllm并不可取 |
Windows 10 + WSL2 局域网多机 vLLM / Ray 可行性验证
1. 任务目标
在不更换现有 Windows 10 系统、不使用 Linux 虚拟机或裸机 Linux、推理通信不经过公网的前提下,验证以下双机分布式推理架构是否可落地:
Node0:Windows 10 → WSL2 Ubuntu → Ray Head + vLLM 主节点 → RTX 2080 Ti
Node1:Windows 10 → WSL2 Ubuntu → Ray Worker + vLLM Worker → RTX 2080 Ti
计划使用 Ray 管理跨主机 GPU,由 vLLM 通过 --distributed-executor-backend ray 和 Tensor Parallel 调用两张显卡。
本次验收条件:
- 两台 WSL2 之间存在稳定、双向、仅走局域网的节点通信路径。
- Ray 可长期保持
2 nodes / 2 GPU,Worker 不因健康检查失败退出。 - Ray 控制面、对象传输和 Worker/Actor 端口均可双向访问。
- 后续 NCCL 能使用低延迟、可直连的局域网接口。
- 以上条件成立后,再进入 vLLM 多机 Tensor Parallel 启动与性能测试。
2. 实际环境
| 项目 | Node0 | Node1 |
|---|---|---|
| 角色 | Ray Head、vLLM 主节点 | Ray Worker、vLLM Worker |
| Windows IP | 192.168.xxx.184/24 |
192.168.xxx.243/24 |
| WSL2 IP | 172.22.xxx.216/20 |
172.23.xxx.66/20 |
| WSL2 NAT 子网 | 172.22.xxx.0/20 |
172.23.xxx.0/20 |
| GPU | RTX 2080 Ti | RTX 2080 Ti |
| 原始 vLLM 镜像 | vllm/vllm-openai:latest |
vllm/vllm-openai:v0.24.0 |
| 补充 Ray 后镜像 | vllm/vllm-openai:latest |
vllm/vllm-openai:v0.24.0 |
网络关系如下:
Node0 WSL2 172.22.xxx.216/20
│ WSL2 NAT
Node0 Windows 192.168.xxx.184/24
│
├──────── 本地局域网 ────────┤
│
Node1 Windows 192.168.xxx.243/24
│ WSL2 NAT
Node1 WSL2 172.23.xxx.66/20
两台 Windows 位于同一个 192.168.xxx.0/24 局域网;两台 WSL2 分别位于两段不同的私有 NAT 子网。
3. 原部署流程复核
原部署方案包括以下阶段:
- Windows 10 安装 WSL2 Ubuntu。
- 验证 Windows 和 WSL2 中的 NVIDIA 驱动。
- 在 WSL2 内安装 Docker 与 NVIDIA Container Toolkit。
- 验证 Docker GPU,并部署 vLLM 镜像。
- 在宿主 WSL2 Conda 环境安装 Ray。
- Node0 启动 Ray Head,Node1 使用 Node0 Windows IP 加入集群。
- 设置
VLLM_HOST_IP、NCCL_SOCKET_IFNAME=eth0。 - 启动 vLLM Ray 后端和多机 Tensor Parallel。
复核后确认,多机部分存在一个需要先验证的前置条件:Node1 虽然可以通过 Node0 Windows IP 主动访问 GCS,但 Ray 向集群登记的节点地址仍是各自 WSL2 IP。Ray 和 NCCL 不仅需要 Worker 主动连接 Head,还需要集群组件按登记地址进行反向、双向直连。因此,不能仅用 6379 端口可访问或 ray status 短暂显示两个节点作为网络验收依据。
4. 分层验证过程
4.1 基础 GPU、Docker 与 vLLM 单机能力
先验证与跨主机网络无关的基础链路:
Windows NVIDIA 驱动
→ WSL2 GPU
→ Docker GPU
→ vLLM 单机推理
验证结果:
- Windows NVIDIA 驱动正常。
- WSL2 中可以识别 RTX 2080 Ti。
- Docker 可以访问 GPU,NVIDIA Container Toolkit 正常。
vllm/vllm-openai:v0.24.0单机启动成功。
结论:GPU、WSL2 GPU 支持、Docker GPU 映射和 vLLM 单机能力均可用,不是本次多机验证的阻塞点。
4.2 补齐 vLLM 容器内的 Ray 依赖
vLLM 使用以下参数时:
--distributed-executor-backend ray
容器报错:
No module named 'ray'
定位结果:宿主 WSL2 的 Conda/Python 环境与 Docker 容器隔离,在宿主机安装 Ray 不代表 vLLM 容器内存在 Ray。
处理方式:
FROM vllm/vllm-openai:v0.24.0
RUN pip install ray
构建得到:
vllm-ray:v0.24.0
4.3 Ray 集群初始联机与健康状态观察
Node0 启动 Ray Head:
ray start \
--head \
--node-ip-address=172.22.xxx.216 \
--port=6379
Node1 加入:
ray start \
--address=192.168.xxx.184:6379 \
--node-ip-address=172.23.xxx.66
初始现象:
2 nodes
2 GPU
几十秒后退化为:
1 node
1 GPU
Node1 raylet 日志先显示服务正常启动:
ObjectManager server started
NodeManager server started
随后出现:
Received address and liveness notification for node, IsAlive = 0
最终退出:
[Timeout] Exiting because this node manager has mistakenly been marked as dead by the GCS:
GCS failed to check the health of this node for 5 times.
阶段结论:
- Node1 Ray Worker 能启动,并能主动访问 Node0 GCS。
- Node1 GPU 能短暂注册到集群。
- GCS 无法按 Node1 登记的
172.23.xxx.66地址完成反向健康检查。 ray status短暂出现2 nodes / 2 GPU不能作为集群稳定性验收结果。
4.4 固定 Ray 关键端口,排除随机端口干扰
排查中观察到 Ray 随机使用过 36935、39669、40791、46771 等端口。为提高防火墙、代理和抓包的可诊断性,将 Node1 关键端口固定:
ray start \
--address=192.168.xxx.184:6379 \
--node-ip-address=172.23.xxx.66 \
--node-manager-port=50101 \
--object-manager-port=50102 \
--min-worker-port=50110 \
--max-worker-port=50120
监听检查:
ss -lntp | grep -E "50101|50102"
结果:
LISTEN *:50101 users:(("raylet"...))
LISTEN *:50102 users:(("raylet"...))
Raylet 工作正常,固定端口参数生效;当前问题不是 Node Manager 或 Object Manager 未监听,而是远端无法访问 Ray 登记的 WSL2 地址。
4.5 Windows portproxy 验证
在 Node1 Windows 建立 TCP 端口代理:
192.168.xxx.243:50101 → 172.23.xxx.66:50101
192.168.xxx.243:50102 → 172.23.xxx.66:50102
已确认:
IP Helper服务运行正常。- Windows 确实监听
192.168.xxx.243:50101/50102。 - Node1 Windows 能访问本机 WSL2 对应服务。
- 排查并清理了误绑定到 Node0 地址
192.168.xxx.184的残留代理项。
该方案没有解决 Ray 健康检查,原因如下:
- Node1 向 GCS 登记的仍是
172.23.xxx.66:50101/50102,其他 Ray 组件不会自动改为访问 Windows 地址192.168.xxx.243。 portproxy是指定端口的 TCP 转发,不是透明三层网络,也不进行 Ray 服务发现地址改写。- 完整 Ray 通信还包括 Runtime Env Agent、Dashboard/Metrics、Worker/Actor 端口和对象传输端口。
- 后续 NCCL 还需要 GPU 节点间的独立数据通道,不能通过少量 TCP 端口代理替代。
4.6 验证每台 Windows 与本机 WSL2 双向通信
为排除单机 WSL2 网络异常,先在两台主机分别验证 Windows 与本机 WSL2。
Node1 Windows → Node1 WSL2:
Test-NetConnection 172.23.xxx.66 -Port 50999
curl.exe --connect-timeout 5 http://172.23.xxx.66:50999/
关键结果:
SourceAddress : 172.23.xxx.1
TcpTestSucceeded : True
HTTP 请求成功返回 WSL2 临时服务的目录内容。
Node1 WSL2 → Node1 Windows:
ping -c 4 172.23.xxx.1
curl --connect-timeout 5 http://172.23.xxx.1:51000/
均成功。Node0 也完成了相同方向验证。
两台主机各自的 Windows ↔ 本机 WSL2 网络正常;问题集中在“跨 Windows 主机访问另一台 WSL2 NAT 子网”。
4.7 双向静态路由与 Windows 转发验证
根据 /20 掩码计算两段 WSL2 子网:
Node0:172.22.xxx.216/20 → 172.22.xxx.0/20
Node1:172.23.xxx.66/20 → 172.23.xxx.0/20
在 Node0 Windows 添加:
目标 172.23.xxx.0/20,下一跳 192.168.xxx.243
在 Node1 Windows 添加:
目标 172.22.xxx.0/20,下一跳 192.168.xxx.184
对应持久路由命令:
# Node0
route -p add 172.23.xxx.0 mask 255.255.240.0 192.168.xxx.243 metric 5 if <LAN接口索引>
# Node1
route -p add 172.22.xxx.0 mask 255.255.240.0 192.168.xxx.184 metric 5 if <LAN接口索引>
- 两台 Windows 的 LAN 接口开启 IPv4 Forwarding。
- 两台 Windows 的
vEthernet (WSL)开启 IPv4 Forwarding。 - 设置全局
IPEnableRouter=1。 - 配置对应防火墙规则。
- 重启后复核 WSL2 地址、持久路由和接口 Forwarding 均保持正确。
Node1 WSL2 的路由选择结果:
172.22.xxx.216 via 172.23.xxx.1 dev eth0 src 172.23.xxx.66
说明 Linux 已将跨节点流量交给本机 Windows WSL 网关。
但实际跨主机测试仍失败:
ping -c 4 172.22.xxx.216
curl -v --connect-timeout 5 http://172.22.xxx.216:50998/
结果:
4 packets transmitted, 0 received, 100% packet loss
curl: (28) Failed to connect ... Timeout was reached
4.8 目标 WSL2 抓包,确定报文停止位置
Node1 发起上述请求时,在 Node0 WSL2 执行:
sudo tcpdump -ni eth0 'host 172.23.xxx.66 and (icmp or tcp port 50998)'
结果:抓包无任何输出。
这是本次验证的决定性证据:
- 源 WSL2 路由选择正确。
- 两台 Windows 的局域网地址互通。
- Windows 持久路由、接口转发和全局转发均已配置。
- 目标 WSL2 完全收不到请求报文。
因此故障位置不在目标 Linux 应用监听、Ubuntu 防火墙、Linux 返回路由或 Ray 端口,而是在 Windows 10 WSL/HNS NAT 的跨主机转发边界。当前环境没有形成 Ray/NCCL 所需的透明、双向三层网络。
4.9 Tailscale 仅作为覆盖网络对照实验
为验证“只要两个 WSL2 获得稳定的可达地址,节点间即可互通”,在两台 WSL2 上进行了 Tailscale 对照实验:
| 节点 | Tailscale IP |
|---|---|
| Node0 WSL2 | 100.125.171.86 |
| Node1 WSL2 | 100.125.164.50 |
双向 tailscale ping 成功,但实际路径为:
via DERP(sin)
延迟约:
95–99 ms
Node1 tailscale netcheck 关键结果:
UDP: true
IPv4: yes, 23.129.164.114:51114
MappingVariesByDestIP: false
PortMapping: <空>
Nearest DERP: Singapore
该实验验证了覆盖网络可以绕过 WSL2 NAT 的地址可达性问题,但当前实际通信经过公网中继,不符合“仅使用本地局域网”的约束;同时该延迟也不适合 vLLM Tensor Parallel / NCCL 的高频通信。因此只保留为网络根因的对照证据,不作为部署方案。
4.10 其他路线评估
在明确静态路由边界后,还评估了以下替代方向:
| 路线 | 判断 | 本次处理 |
|---|---|---|
继续扩展 portproxy |
无法提供透明三层网络,端口与地址维护成本高 | 不继续投入 |
| 本地 OpenVPN TCP 覆盖网络 | 理论上可在局域网内创建共同地址空间 | 配置复杂,且 TCP-over-TCP 不适合优先承载 NCCL;本次未实施 |
| Hyper-V Linux VM | 可能改善网络,但会改变现有运行结构 | Windows 10 下 GPU 使用方式不满足当前目标,未采用 |
| Windows 11 WSL mirrored networking | 有进一步验证价值 | 需要升级系统,超出本次约束 |
| 原生 Linux | 网络与 GPU 分布式环境更直接 | 会改变现有系统环境,作为未来优先方案保留 |
6. 当前约束下为什么不可行
本次结论针对的是以下条件组合:
Windows 10
+ WSL2 NAT
+ 两台独立 Windows 主机
+ 纯局域网通信
+ 不引入额外本地覆盖网络
+ Ray / NCCL 需要节点间双向直连
在该组合下,当前方案不能完成稳定、实用的多机 vLLM / Ray Tensor Parallel,原因是:
- 两台 WSL2 位于彼此独立的 NAT 子网,默认不能直接路由。
- Ray 向 GCS 注册的是 WSL2 地址,Head、GCS、Raylet、Object Manager 和 Worker/Actor 需要按该地址双向通信。
- Windows
portproxy只能代理指定 TCP 端口,不能把 WSL2 地址转换成整个集群共同可见的节点地址,也不能替代 NCCL 数据网络。 - 双向静态路由、接口 Forwarding、
IPEnableRouter和防火墙均配置后,目标 WSL2 仍完全抓不到报文,说明 Windows 10 WSL/HNS NAT 没有提供所需的透明跨主机转发路径。 - 覆盖网络可以建立可达性,但本次 Tailscale 实际使用公网 DERP 中继,不符合纯局域网要求。
在保持现有 Windows 10 + WSL2 NAT 环境、限定通信只走局域网、且不增加本地覆盖网络的前提下,无法建立 Ray/NCCL 所需的稳定双向节点网络,因此不继续进入 vLLM 多机 Tensor Parallel 与性能测试阶段。
7. 可复用排查经验
7.1 分布式推理应按层验收
后续类似任务建议使用以下顺序:
Windows GPU
→ WSL2 GPU
→ Docker GPU
→ vLLM 单机
→ 容器内 Ray 依赖
→ Windows 与本机 WSL2 双向 TCP
→ 两台 WSL2 双向 L3/TCP
→ Ray 数分钟稳定健康
→ Ray 远程任务与对象传输
→ iperf3 / NCCL 带宽
→ vLLM Tensor Parallel
网络层未验收前,不应把后续现象归因到 vLLM 或模型本身。
7.2 地址比单个端口更重要
分布式框架不仅需要一个“入口地址”,还需要所有节点对服务发现中登记的地址形成一致视图。6379 可访问只能证明 Worker 能发起一次连接,不能证明 Head 能回连 Worker。
7.3 抓包是路由排查的终止证据
当路由表、转发和防火墙均已检查时,应在目标 WSL2 抓包:
- 完全没有请求:继续检查 Windows/HNS/NAT 或中间网络。
- 有请求、没有回复:检查 Linux 监听、防火墙、
rp_filter和返回路由。 - 请求与回复都有:检查中间设备或源端返回路径。
8. 后续边界建议
本次可行性验证已完成,现阶段不继续扩展逐端口 portproxy。
若未来重新启动该方向,建议按以下优先级重新验证:
- 原生 Linux 节点与可路由局域网。
- 升级到支持更合适 WSL 网络模式的系统后,先单独验收两个 WSL2 的双向 L3 直连。
- 若允许增加本地覆盖网络,必须确保节点在局域网内直连,不使用公网中继;随后先执行
iperf3和 NCCL 基准测试。 - 只有 Ray 长时间稳定、远程任务和对象传输通过后,再启动 vLLM Tensor Parallel。
更多推荐



所有评论(0)