GPUStack v2.1.1 彻底解决多节点推理无法启动问题的全过程

GPUStack v2.1.1 彻底解决多节点推理无法启动问题的全过程

5 min read

技术博客
GPUStack
多节点 vLLM
Tesla V100
故障排查

GPU 集群运维备忘录

彻底解决 GPUStack v2.1.1 多节点推理无法启动的问题
在 2 节点 4×V100 上运行 Qwen2.5-32B 的完整记录 #

在使用 GPUStack v2.1.1 + vLLM backend、以 2 台 GPU worker(各配备 Tesla V100-PCIE-32GB × 2 GPU)进行多节点分布式推理时,我们接连遇到了各种不同的问题。从 Ray 集群连接失败、Gloo 通信错误、/dev/shm 不足,到 V100 特有的 CUDA 内核错误——本文按时间顺序记录所有故障与应对方法。

GPU-Worker-A: / Tesla V100×2 | GPU-Worker-B: / Tesla V100×2 | GPU-Server: GPUStack Server | GPUStack v2.1.1 / vLLM 0.17.1 / CUDA 12.9

配置概览 #

管理节点(GPU-Server)负责运行 GPUStack Server,推理任务分布在 2 台 GPU worker 上执行。模型存放在 NFS 共享的 /models 中。最初尝试的是 Qwen3.5-35B-A3B(VLM),最终确认 Qwen2.5-32B-Instruct 可以稳定运行。

目标模型 #

Qwen2.5-32B-Instruct (float16)
tensor-parallel×2 / pipeline-parallel×2

GPU 配置 #

Tesla V100-PCIE-32GB × 4 GPU
(2 节点 × 2 GPU)
计算能力 7.0

最终结果 #

以 16./s 稳定运行
max-model-len:8192
已应用变通方案

问题与解决方案完整概览 #

问题 1

Ray Placement Group 无限等待 #

启动模型时,Waiting for creating a placement group 会从 10 秒 → 30 秒 → 150 秒 → 630 秒无限持续下去,模型始终无法启动。

WARNING: Tensor parallel size (4) exceeds available GPUs (2).
INFO: Waiting for creating a placement group of specs for 630 seconds.
specs=[{'node:': 0.001, 'GPU': 1.0}, {'GPU': 1.0}, {'GPU': 1.0}, {'GPU': 1.0}]

原因:Ray 仅在 head 节点一侧的容器内运行,另一台 worker 节点的 GPU 无法加入 Ray 集群。

验证命令:在 vllm runner 容器内执行 ray status --address=<HEAD_IP>:41000。
如果出现 Ray 版本不匹配错误(2.54.0 vs 2.48.0),则可能是 GPUStack 镜像版本不一致所致。

问题 2

由于 /etc/hosts 中存在 127.0.1.1 条目导致 Gloo 通信失败 #

Ray 节点之间可以互相连接,但模型加载完成后,分布式环境初始化(Gloo 的 connectFullMesh)失败。

(RayWorkerWrapper pid=1722) ERROR failed to connect, retry=4, retryLimit=3,
  local=[127.0.0.1]:35509, remote=[127.0.1.1]:51638$1,
  error=SO_ERROR: Connection refused

RuntimeError: Gloo connectFullMesh failed with timed out connecting:
  SO_ERROR: Connection refused, remote=[127.0.1.1]:51638$1

原因:Ubuntu/Debian 的 cloud-init 默认会将 127.0.1.1 hostname 写入 /etc/hosts。Gloo 会参照这一条目,将本节点自身的 IP 判定为 127.0.1.1(回环地址),从而尝试连接其他节点并被拒绝。

解决方法:在各节点上,将 127.0.1.1 在 /etc/hosts 中的条目修正为实际 IP 地址。

# On GPU-Worker-A
sudo sed -i 's/127.0.1.1\s*GPU-Worker-A/ GPU-Worker-A/' /etc/hosts

# On GPU-Worker-B
sudo sed -i 's/127.0.1.1\s*GPU-Worker-B/ GPU-Worker-B/' /etc/hosts
说明:在本环境中,cloud-init(manage_etc_hosts=True)已自动设置为实际 IP,因此无需修正。请直接在 runner 容器的 /etc/hosts 中确认不存在 127.0.1.1。

问题 3

Qwen3.5-35B-A3B 的 Visual Encoder 在 V100 上无法工作 #

解决 Gloo 问题后,模型加载成功,但在 profile_run 阶段立即崩溃。

File "vllm/model_executor/layers/conv.py", line 236, in _forward_conv
    x = F.conv3d(
        ^^^^^^^^^
RuntimeError: GET was unable to find an engine to execute this computation

原因:Qwen3.5-35B-A3B 是一个 Vision Language Model,其 Visual Encoder 的 Conv3D 缺少针对 V100(计算能力 7.0)编译的 cuDNN 算法。这无法通过 VLLM_DISABLE_MULTIMODAL=1 之类的环境变量来规避。由于 vLLM 在 profile_run 阶段始终会初始化 Visual Encoder,这是一个结构性限制。

解决方法:将模型切换为 Qwen2.5-32B-Instruct(纯文本模型)。由于它没有 Visual Encoder,因此不会出现该问题。

问题 4

对话过程中因 /dev/shm 不足导致引擎崩溃 #

模型可以启动,但一发送对话消息,引擎就会崩溃。

WARNING (raylet) store_runner.cc:83: System memory request exceeds memory available in /dev/shm.
  The request is for 10200547328 bytes, and the amount available is 9663676416 bytes.
  If you are inside a Docker container, you may need to pass an argument with the flag '--shm-size'

CUDA error: no kernel image is available for execution on the device

原因:Docker 默认的 /dev/shm 大小为 64MB。Ray 的 pipeline_parallel 在节点间通信中会大量使用共享内存,推理过程中会将其耗尽。启动 gpustack-worker 容器时未指定 --shm-size。

解决方法:以 --shm-size=16g 重新启动 gpustack-worker 容器。

docker stop gpustack-worker && docker rm gpustack-worker

docker run -d --name gpustack-worker \
  --restart=unless-stopped \
  --privileged \
  --network=host \
  --shm-size=16g \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume /models:/models \
  --volume /var/lib/gpustack-data:/var/lib/gpustack \
  --runtime nvidia \
  gpustack/gpustack:v2.1.1 \
  --server-url http://<SERVER_IP> \
  --token <TOKEN> \
  --cache-dir /models
说明:GPUStack v2.1.1 的“Mirrored Deployment”功能会将 gpustack-worker 的设置带入 runner 容器,但 --shm-size 不会被继承。这是 GPUStack 一侧的问题,需要通过下文所述的环境变量加以补充。

问题 5

Runner 容器的 shm 未被继承,RayChannelTimeoutError 持续出现 #

即使重启 gpustack-worker 后,对话过程中引擎依然会崩溃。

ray.exceptions.RayChannelTimeoutError: System error:
  If the execution is expected to take a long time,
  increase RAY_CGRAPH_get_timeout which is currently 300 seconds.
  Otherwise, this may indicate that the execution is hanging.

原因:vllm/ray runner 容器每次都是由 GPUStack 重新创建的,因此不会跨容器继承 gpustack-worker 的 --shm-size 设置。runner 容器自身的 shm 仍保持在 64MB。

解决方法:在 GPUStack UI 的模型设置中的 Environment Variables 里添加以下内容。

RAY_CGRAPH_get_timeout=600
RAY_memory_store_capacity=17179869184

问题 6

generation_config 的 repetition_penalty 内核与 V100 不兼容,导致循环输出 #

对话会输出异常文本,出现符号(♡♡♡……)循环重复的情况。或者推理会因 CUDA 内核错误而崩溃。

torch.AcceleratorError: CUDA error: no kernel image is available for execution on the device
# ↑ Occurs during apply_penalties (repetition_penalty) execution

WARNING: Default vLLM sampling parameters have been overridden by the model's
  generation_config.json: {'repetition_penalty': 1.05, 'temperature': 0.7, ...}

原因:用于 repetition_penalty(该设置来自 Qwen2.5 的 generation_config.json)的 CUDA 内核并未针对 V100 编译。

解决方法:在 GPUStack UI 的模型设置 → Backend Parameters 中添加:

--generation-config vllm

这会忽略模型的 generation_config.json,转而使用 vLLM 的默认设置。

最终稳定运行配置汇总 #

gpustack-worker 启动命令(两节点通用) #

docker run -d --name gpustack-worker \
  --restart=unless-stopped \
  --privileged \
  --network=host \
  --shm-size=16g \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume /models:/models \
  --volume /var/lib/gpustack-data:/var/lib/gpustack \
  --runtime nvidia \
  gpustack/gpustack:v2.1.1 \
  --server-url http://<SERVER_IP> \
  --token <TOKEN> \
  --cache-dir /models

GPUStack UI 模型设置 #

Backend Parameters:

--tensor-parallel-size 2
--pipeline-parallel-size 2
--distributed-executor-backend ray
--max-model-len 8192
--enforce-eager
--generation-config vllm

Environment Variables:

RAY_CGRAPH_get_timeout=600
RAY_memory_store_capacity=17179869184

运行验证结果 #

Qwen2.5-32B-Instruct(float16)在 4×Tesla V100-PCIE-32GB(2 节点配置)上以 16./s 稳定运行。每块 GPU 的显存使用率为 93–96%。max-model-len 为 。

V100(计算能力 7.0)特有的限制 #

❌ 不可用 #

  • Flash Attention 2(需要计算能力 8.0 以上)→ 回退为 Triton ATTN
  • bfloat16(→ 自动转换为 float16)
  • Custom AllReduce(不支持 NVLink P2P)
  • SymmMemCommunicator
  • VLM Conv3D(Qwen3.5-35B-A3B 等)
  • generation_config 的 repetition_penalty 内核

✅ 可用 #

  • Triton ATTN backend(Flash Attention 的替代方案)
  • NCCL 通信(nccl==2.27.5)
  • Ray 分布式执行(pipeline + tensor parallel)
  • torch.compile / CUDA Graphs(建议通过 enforce-eager 禁用)
  • Qwen2.5 等纯文本模型的推理

故障排查清单 #

  • 使用 ray status 确认所有节点的 GPU 均已被识别(在容器内执行)
  • 确认各节点 /etc/hosts 中的 hostname 解析为实际 IP,而非 127.0.1.1
  • 为 gpustack-worker 容器指定 --shm-size=16g 或更大的值
  • 在模型设置的 Environment Variables 中添加 RAY_CGRAPH_get_timeout=600 和 RAY_memory_store_capacity=17179869184
  • 在 V100 环境中,向 Backend Parameters 添加 --generation-config vllm 以忽略 generation_config.json
  • VLM(Vision Language Model)在 V100 上无法使用,请使用纯文本模型
  • 在 V100 上可考虑添加 --enforce-eager(避免与 CUDA Graph 相关的不稳定性)
  • 如果显存紧张,可通过 --gpu-memory-utilization 0.85 调整 KV cache 分配

参考资料 #

本文是生产环境中故障排查的记录。IP、token 等信息已做抽象化处理。部分问题可能不会出现在 V100 以外的 GPU 环境中。随着 vLLM 与 GPUStack 版本的更新,情况可能会发生变化。

Updated on 2026年6月9日

What are your feelings

  • Happy
  • 常规
  • Sad

©2020 BESTNET.LLC . All Rights Reserved.