概览

主题 状态 当日结果
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 调用两张显卡。

本次验收条件:

  1. 两台 WSL2 之间存在稳定、双向、仅走局域网的节点通信路径。
  2. Ray 可长期保持 2 nodes / 2 GPU,Worker 不因健康检查失败退出。
  3. Ray 控制面、对象传输和 Worker/Actor 端口均可双向访问。
  4. 后续 NCCL 能使用低延迟、可直连的局域网接口。
  5. 以上条件成立后,再进入 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. 原部署流程复核

原部署方案包括以下阶段:

  1. Windows 10 安装 WSL2 Ubuntu。
  2. 验证 Windows 和 WSL2 中的 NVIDIA 驱动。
  3. 在 WSL2 内安装 Docker 与 NVIDIA Container Toolkit。
  4. 验证 Docker GPU,并部署 vLLM 镜像。
  5. 在宿主 WSL2 Conda 环境安装 Ray。
  6. Node0 启动 Ray Head,Node1 使用 Node0 Windows IP 加入集群。
  7. 设置 VLLM_HOST_IPNCCL_SOCKET_IFNAME=eth0
  8. 启动 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 随机使用过 36935396694079146771 等端口。为提高防火墙、代理和抓包的可诊断性,将 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 健康检查,原因如下:

  1. Node1 向 GCS 登记的仍是 172.23.xxx.66:50101/50102,其他 Ray 组件不会自动改为访问 Windows 地址 192.168.xxx.243
  2. portproxy 是指定端口的 TCP 转发,不是透明三层网络,也不进行 Ray 服务发现地址改写。
  3. 完整 Ray 通信还包括 Runtime Env Agent、Dashboard/Metrics、Worker/Actor 端口和对象传输端口。
  4. 后续 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,原因是:

  1. 两台 WSL2 位于彼此独立的 NAT 子网,默认不能直接路由。
  2. Ray 向 GCS 注册的是 WSL2 地址,Head、GCS、Raylet、Object Manager 和 Worker/Actor 需要按该地址双向通信。
  3. Windows portproxy 只能代理指定 TCP 端口,不能把 WSL2 地址转换成整个集群共同可见的节点地址,也不能替代 NCCL 数据网络。
  4. 双向静态路由、接口 Forwarding、IPEnableRouter 和防火墙均配置后,目标 WSL2 仍完全抓不到报文,说明 Windows 10 WSL/HNS NAT 没有提供所需的透明跨主机转发路径。
  5. 覆盖网络可以建立可达性,但本次 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

若未来重新启动该方向,建议按以下优先级重新验证:

  1. 原生 Linux 节点与可路由局域网。
  2. 升级到支持更合适 WSL 网络模式的系统后,先单独验收两个 WSL2 的双向 L3 直连。
  3. 若允许增加本地覆盖网络,必须确保节点在局域网内直连,不使用公网中继;随后先执行 iperf3 和 NCCL 基准测试。
  4. 只有 Ray 长时间稳定、远程任务和对象传输通过后,再启动 vLLM Tensor Parallel。
Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐