没有 IB、没有 RoCE、没有 NVLink——三无环境下的跨服务器大模型部署实战。上一篇讨论了能不能跑结论是能。这篇把完整过程写出来。塔式、机架式环境的可以尝试下。4090、5090、A100 除了显存大小其他一模一样。先看一眼环境两台服务器配置完全一致组件型号GPU2× NVIDIA A40 48GB × 2 台 4 卡CPUIntel Xeon Gold 64 核内存1TB系统Ubuntu 24.04 LTS内联网口4×10Gens6f0/ens6f1/ens7f0/ens7f1管理、业务网口1Gens16f0连接网络机器间互联方式4 根网线直连不过交换机没有 IB、没有 RoCE、没有 NVLink——三个没有是这篇文章存在的前提。要是什么都有照着 NVIDIA 官方文档跑就完了不用看了。第一步把线接明白四根内联线两台机器一对一插上。不经过交换机——交换机多一层延迟对你没好处。机器 A 机器 B ens6f0: 10.13.12.1/30 ←──→ ens6f0: 10.13.12.2/30 ens6f1: 10.13.12.5/30 ←──→ ens6f1: 10.13.12.6/30 ens7f0: 10.13.12.9/30 ←──→ ens7f0: 10.13.12.10/30 ens7f1: 10.13.12.13/30 ←──→ ens7f1: 10.13.12.14/30配完要写进系统文件重启才不丢。Ubuntu 用 netplan# /etc/netplan/99-cluster-mesh.yaml network: version: 2 renderer: networkd ethernets: ens6f0: dhcp4: no; dhcp6: no; link-local: [] addresses: [10.13.12.1/30] mtu: 9000 ens6f1: dhcp4: no; dhcp6: no; link-local: [] addresses: [10.13.12.5/30] mtu: 9000 ens7f0: dhcp4: no; dhcp6: no; link-local: [] addresses: [10.13.12.9/30] mtu: 9000 ens7f1: dhcp4: no; dhcp6: no; link-local: [] addresses: [10.13.12.13/30] mtu: 9000netplan apply三个要点/30 子网。点对点直连只需要 2 个 IP/30 刚好。给个 /24 也行但没必要还容易跟别的网段冲突MTU 9000。大模型跨节点传的是几 MB 的梯度数据包不是小聊天消息。MTU 1500 一个包要拆成几百个碎片MTU 9000 少拆 6 倍link-local: []。关掉 IPv6 自动地址。不关的话 NCCL 可能自作聪明选了 IPv6 链路然后你发现带宽全走错了第二步装驱动——别用 550网上大部分教程让装 550。我也装了然后 vLLM 在 MoE 算子编译阶段疯狂报错。换了 580 全好了。550580CUDA12.412.6MoE 融合算子部分编译失败正常FlashAttention 3不支持支持原因很简单vLLM 0.24 PyTorch 2.5 用了不少新 CUDA 特性550 驱动层不支持580 原生支持。不需要装 cuda-toolkit。很多新手上来apt install cuda-toolkit-12-6装完十几 GB然后发现屁用没有——Docker 容器自带完整 CUDA 运行时。宿主机只需要两样apt install nvidia-driver-580 nvidia-container-toolkit nvidia-smi # 看到 Driver Version: 580.xx 就完事了第三步下载模型模型文件放/data/models/两台机器都要有——vLLM 每张卡都要读权重文件Worker 上没有模型就干瞪眼。# 机器 A 上下载 我是在魔塔官网下载的https://www.modelscope.cn/models python3 -c from modelscope import snapshot_download snapshot_download(Qwen/Qwen3-Coder-Next, local_dir/data/models/Qwen3-Coder-Next) # 148GB去喝杯咖啡下载完同步到机器 B。走内联比外网快得多rsync -avP /data/models/Qwen3-Coder-Next/ root10.13.12.2:/data/models/Qwen3-Coder-Next/不要傻傻在机器 B 上再下一遍。内联 10G 跑满 1GB/s148GB 两分多钟。modelscope 下载撑死 200MB/s还要看运气。模型名换成你自己的。Qwen、DeepSeek、LLaMA 流程一样Modelscope / HuggingFace 都行关键是两台路径必须一致。第四步启动脚本NCCL 变量不能在命令行临时export——重启丢换终端丢迟早会忘。正确做法写进 Docker 启动脚本作为-e参数钉死。机器 A — Head/data/start_vllm.sh#!/bin/bash docker rm -f vllm-head 2/dev/null ​ docker run -d --name vllm-head --network host --gpus all --shm-size16g \ -v /data/models:/data/models \ -e NCCL_SOCKET_IFNAMEens6f0,ens6f1,ens7f0,ens7f1 \ -e NCCL_IB_DISABLE1 -e NCCL_NETSocket \ -e NCCL_CROSS_NIC1 -e NCCL_MIN_NCHANNELS4 -e NCCL_MAX_NCHANNELS4 \ -e NCCL_SOCKET_NTHREADS8 -e NCCL_NSOCKS_PERTHREAD4 \ -e NCCL_BUFFSIZE4194304 -e NCCL_NTHREADS16 \ -e NCCL_DEBUGWARN -e GLOO_SOCKET_IFNAMEens16f0 \ --entrypoint bash vllm-ray:latest \ -c ray start --head --port6379 --num-gpus2 --disable-usage-stats; sleep 5; \ vllm serve /data/models/Qwen3-Coder-Next --served-model-name Qwen3-Coder-Next \ --tensor-parallel-size 4 --host 0.0.0.0 --port 8000 --max-model-len 40960 \ --gpu-memory-utilization 0.95 --dtype bfloat16 --enable-prefix-caching \ --enable-auto-tool-choice --tool-call-parser qwen3_coder --distributed-executor-backend ray机器 B — Worker/data/start_vllm_worker.sh#!/bin/bash docker rm -f vllm-worker 2/dev/null ​ docker run -d --name vllm-worker --network host --gpus all --shm-size16g \ -v /data/models:/data/models \ -e NCCL_SOCKET_IFNAMEens6f0,ens6f1,ens7f0,ens7f1 \ -e NCCL_IB_DISABLE1 -e NCCL_NETSocket \ -e NCCL_CROSS_NIC1 -e NCCL_MIN_NCHANNELS4 -e NCCL_MAX_NCHANNELS4 \ -e NCCL_SOCKET_NTHREADS8 -e NCCL_NSOCKS_PERTHREAD4 \ -e NCCL_BUFFSIZE4194304 -e NCCL_NTHREADS16 \ -e NCCL_DEBUGWARN -e GLOO_SOCKET_IFNAMEens16f0 \ --entrypoint bash vllm-ray:latest \ -c sleep 3; ray start --address192.168.13.28:6379 --num-gpus2 --disable-usage-stats; sleep 999999注意 vLLM 参数必须写成一行——bash -c里面多行反斜杠续接非常容易断裂。我当时卡了半小时。断掉的表现是World size (4) GPUs (2)因为参数没传进去TP 回了默认值。第五步NCCL 变量——每条都有血的教训变量作用不设的后果NCCL_SOCKET_IFNAME锁定走哪些网口最致命。默认可能只走管理网口4×10G 全废NCCL_IB_DISABLE1禁用 IB/RoCE反复尝试 IB 初始化超时卡死NCCL_CROSS_NIC1多网口负载均衡4 根线只有一根干活NCCL_MIN/MAX_NCHANNELS4通道数锁为 4对应 4 根线不多不少NCCL_BUFFSIZE41943044MB 环形缓冲太小通信轮次暴增TTFT 翻倍GLOO_SOCKET_IFNAMERay 控制面走管理网控制面跟 NCCL 抢带宽两边都慢验证docker logs vllm-head 21 | grep -i nccl.*nic # 应该全是 ens6/ens7不能出现 ens16第六步启动ssh 机器A bash /data/start_vllm.sh sleep 10 ssh 机器B bash /data/start_vllm_worker.sh然后等。不是等几秒——等 3 到 4 分钟。这 4 分钟里发生的事模型加载 ~25s → torch.compile ~50s → CUDA graph 捕获 ~30s → NCCL Ray 初始化。不去喝咖啡也得找点别的事干盯着屏幕只会觉得时间特别长。# 验证 curl http://机器A_IP:8000/v1/models # → {object:list,data:[{id:Qwen3-Coder-Next,...}]} ​ nvidia-smi # 四卡各占 ~44GB ray status # 2 节点 4 GPU重启避坑# 两机器都执行漏一步就可能报 ActorHandleNotFoundError docker rm -f vllm-head vllm-worker ray stop --force pkill -9 -f ray rm -rf /tmp/ray /dev/shm/*ray*我漏过/dev/shm/*ray*查了两天才发现 Ray 把共享内存里的旧 session 当成了当前 session。日志看起来一切正常但就是起不来——这种 bug 的调试体验极差。总结步骤核心接线直连 /30MTU 9000netplan 持久化驱动580不装 toolkitDocker 自带模型modelscope 下载rsync 同步变量写进-e参数跟容器同寿NCCL锁 4 线关 IB验证网口重启/tmp/ray/dev/shm全清4090/5090/A100 一样适用调tensor-parallel-size和--dtype就行。下一篇预告网关篇——怎么把推理服务变成 Claude Code 和 Dify 能接的 Agent 后端。