当前位置: 首页 > news >正文

Multi-Node LLM Serving-vLLM+Ray(Docker)

Multi-Node LLM Serving-vLLM+Ray(Docker)

vLLM+Ray(Docker) 双节点离线一键部署完整方案

适配:vllm/vllm-openai镜像、离线禁 HF 联网、双 8 卡 = 16 张量并行、MiniMax-M2.5-AWQ、脚本挂载启动、自动等待 Worker 就绪再拉起 vLLM

环境预设

  • Head 节点 IP:192.168.1.10
  • Worker 节点 IP:192.168.1.11
  • 宿主机模型路径:/data/models/minimax-m2.5-awq
  • 宿主机脚本目录:/data/vllm_scripts
  • 网卡名称替换为你实际网卡(示例ens160)
  • Ray 端口:6379;vLLM 服务端口:8000;Ray Dashboard:8265

两台宿主机统一准备脚本文件

  1. 创建脚本目录

    mkdir -p /data/vllm_scripts && cd /data/vllm_scripts

  2. Ray Head 启动脚本 start_ray_head.sh

#!/bin/bash
set -e# 基础环境变量
export VLLM_HOST_IP=192.168.1.10
#export NCCL_SOCKET_IFNAME=ens160
#export GLOO_SOCKET_IFNAME=ens160# 启动Ray Head
echo "=== 启动Ray Head节点 ==="
ray start --head \--node-ip-address=192.168.1.10 \--port=6379 \--dashboard-host=0.0.0.0 \--num-gpus=8 \--num-cpus=128# 轮询等待2个Active节点(适配新版ray status无Total Nodes行)
MAX_WAIT=100
COUNT=0
TARGET_NODE=2
echo "=== 等待Worker节点接入集群 ==="
while [ $COUNT -lt $MAX_WAIT ]; doNODE_COUNT=$(ray status 2>/dev/null | grep -A 10 "Active:" | grep "node_" | wc -l)if [ "${NODE_COUNT}" -eq "${TARGET_NODE}" ]; thenecho "✅ Worker已上线,节点总数:${NODE_COUNT}"breakfiCOUNT=$((COUNT+1))echo "⏳ 当前节点数: ${NODE_COUNT}, 等待进度${COUNT}/${MAX_WAIT}"sleep 3
done# 等待超时退出
if [ $COUNT -ge $MAX_WAIT ]; thenecho "❌ 等待超时,Worker未接入,终止启动"exit 1
fi# 后台启动vLLM离线推理服务
# 注:也可使用 `vllm serve` 简写命令启动,等价于下面 python -m 方式
echo "=== 启动vLLM OpenAI服务 ==="
python -m vllm.entrypoints.openai.api_server \--model /data/models/minimax-m2.5-awq \--local-files-only \--tensor-parallel-size 16 \--pipeline-parallel-size 1 \--host 0.0.0.0 \--port 8000 \--gpu-memory-utilization 0.95 \--max-model-len 196608 \--distributed-executor-backend ray \--enforce-eager > /tmp/vllm_run.log 2>&1 &# 等待vLLM服务就绪
echo "=== 等待vLLM服务启动 ==="
VLLM_WAIT=0
VLLM_MAX_WAIT=60
while [ $VLLM_WAIT -lt $VLLM_MAX_WAIT ]; doif curl -s http://localhost:8000/v1/models > /dev/null 2>&1; thenecho "✅ vLLM服务已就绪"breakfiVLLM_WAIT=$((VLLM_WAIT+1))echo "⏳ vLLM启动中... ${VLLM_WAIT}/${VLLM_MAX_WAIT}"sleep 5
doneif [ $VLLM_WAIT -ge $VLLM_MAX_WAIT ]; thenecho "❌ vLLM服务启动超时,请检查日志: /tmp/vllm_run.log"exit 1
fi# 容器常驻不退出
echo "=== 所有服务启动完成,容器持续运行 ==="
tail -f /dev/null
  1. Ray Worker 启动脚本 start_ray_worker.sh
#!/bin/bash
set -e# 基础环境变量
export VLLM_HOST_IP=192.168.1.11
#export NCCL_SOCKET_IFNAME=ens160
#export GLOO_SOCKET_IFNAME=ens160# 等待Head节点Ray服务就绪
echo "=== 等待Head节点Ray服务 ==="
HEAD_WAIT=0
HEAD_MAX_WAIT=30
while [ $HEAD_WAIT -lt $HEAD_MAX_WAIT ]; doif ray status --address=192.168.1.10:6379 > /dev/null 2>&1; thenecho "✅ Head节点Ray服务已就绪"breakfiHEAD_WAIT=$((HEAD_WAIT+1))echo "⏳ 等待Head节点... ${HEAD_WAIT}/${HEAD_MAX_WAIT}"sleep 3
doneif [ $HEAD_WAIT -ge $HEAD_MAX_WAIT ]; thenecho "❌ Head节点Ray服务未就绪,终止启动"exit 1
fi# 接入Head Ray集群
echo "=== Worker节点连接Ray集群 ==="
ray start --address=192.168.1.10:6379 \--node-ip-address=192.168.1.11 \--num-gpus=8 \--num-cpus=128# 验证Worker已加入集群
echo "=== 验证Worker节点状态 ==="
ray status# 容器常驻,持续保活Ray Worker进程
echo "=== Ray Worker就绪,进入常驻状态 ==="
tail -f /dev/null
  1. 赋予脚本执行权限
    chmod +x /data/vllm_scripts/*.sh

节点容器启动命令(一键拉起)

  1. Ray Worker 节点 先执行(必须优先启动)
# Ray Worker 节点(必须优先启动)
docker run -d \--name vllm-ray-worker \--privileged \--net=host \--shm-size=64g \-v /data/models:/data/models \-v /data/vllm_scripts:/opt/scripts \-v /etc/localtime:/etc/localtime \-e HF_DATASETS_OFFLINE=1 \-e TRANSFORMERS_OFFLINE=1 \-e HF_HUB_OFFLINE=1 \-e HF_HUB_DISABLE_TELEMETRY=1 \-e HF_HUB_LOCAL_FILES_ONLY=1 \-e VLLM_NO_USAGE_STATS=1 \-e VLLM_DISABLE_UPDATES=1 \vllm/vllm-openai \/opt/scripts/start_ray_worker.sh
# Ray Head 节点(自动等待 Worker 再启 vLLM)
docker run -d \--name vllm-ray-head \--privileged \--net=host \--shm-size=64g \-v /data/models:/data/models \-v /data/vllm_scripts:/opt/scripts \-v /etc/localtime:/etc/localtime \-e HF_DATASETS_OFFLINE=1 \-e TRANSFORMERS_OFFLINE=1 \-e HF_HUB_OFFLINE=1 \-e HF_HUB_DISABLE_TELEMETRY=1 \-e HF_HUB_LOCAL_FILES_ONLY=1 \-e VLLM_NO_USAGE_STATS=1 \-e VLLM_DISABLE_UPDATES=1 \vllm/vllm-openai \/opt/scripts/start_ray_head.sh

校验 & 运维操作集

  1. 查看 Ray 集群状态
# Head容器内查看双节点
docker exec vllm-ray-head ray status

Active 列表出现 2 个 node_id、资源总量 16GPU 即集群正常。

  1. 查看启动全流程日志
# Head完整启动日志(Ray+等待+vLLM启动)
docker logs -f vllm-ray-head
# Worker Ray日志
docker logs -f vllm-ray-worker
  1. 查看 vLLM 推理实时日志

docker exec -it vllm-ray-head tail -f /tmp/vllm_run.log

  1. 接口测试验证服务
curl http://192.168.1.10:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model":"minimax-m2.5-awq",
"messages":[{"role":"user","content":"测试多节点长上下文推理"}]
}'curl http://192.168.1.10:8000/v1/models
  1. 启停销毁命令
# 停止容器服务
docker stop vllm-ray-head vllm-ray-worker
# 彻底删除容器重建
docker rm -f vllm-ray-head vllm-ray-worker
  1. 手动进入容器调试
# Head进入交互终端
docker exec -it vllm-ray-head bash
# Worker进入交互终端
docker exec -it vllm-ray-worker bash

关键配置说明

  1. 显存与 Token 最大化
    --gpu-memory-utilization 0.95 极限榨取显存,搭配196608模型原生最大上下文;若出现 OOM,下调至 0.90 稳定生产。

  2. 离线保障
    容器环境变量 + vLLM --local-files-only 双重锁死,完全不会访问 huggingface 外网。

  3. 常驻原理
    Worker 用tail -f /dev/null保活 Ray 进程;Head 同方式保活,vLLM 后台异步运行不阻塞常驻 PID1。

  4. 通信兼容
    NCCL/GLOO 双通信网卡绑定,解决跨节点多卡张量并行通信超时问题。

  5. Ray 适配修复
    脚本改用统计node_行数判断节点数,兼容无Total Nodes输出的 Ray 新版本。

Todo

  • 采用.env存储环境变量、常量
  • 增加容器管理sh,控制检测、启、停容器
  • vllm port 8001
http://www.rkmt.cn/news/1513177.html

相关文章:

  • MCF51QW256嵌入式MCU硬件加密与低功耗设计实战解析
  • 舒扬|四川华锐净化工程有限公司 个人简介 - 哈尺大哥
  • 2026武汉沙发翻新换皮换布上门服务哪家靠谱?匠阁/御匠/锦修/优势推荐指南 - 我叫一
  • 2026年洛阳快递泡沫箱厂家靠谱推荐:保温缓冲包装箱、防震泡沫箱、生鲜冷链专用箱优质源头工厂精选 - 品牌发掘
  • 2026杭州沙发翻新换皮换布上门服务哪家靠谱?匠阁/御匠/锦修/优势推荐指南 - 我叫一
  • 2026年泡沫轻质包装制造企业实力解析:精密包装与防震缓冲的源头工厂抉择 - 品牌发掘
  • 【分享】16.3 写给35+的人:你不是被嫌弃了,你是被错误定价了
  • 2026广州沙发翻新换皮换布上门服务哪家靠谱?匠阁/御匠/锦修/优势推荐指南 - 我叫一
  • 基于MPC8275与PM4351的E1接口子卡设计:从硬件到驱动的完整实现
  • 异构SoC BSC9131:微基站核心处理器的架构解析与工程实践
  • MonkeyCode免费策略深度解读:AI编程工具如何做到永久免费
  • 托运寄电动车哪个快递最省钱?实测对比+省钱技巧 - 快递物流资讯
  • 2026年泡沫护角行业竞争格局深度分析报告 - 品牌发掘
  • Flask蓝图拆分的图书作者CRUD系统,SQLite本地存储+前后端分离结构
  • 解析自动穿丝中走丝机床的PLC梯形图逻辑与故障诊断
  • 【线性双端口电路模拟器】使用网络分析的线性电路模拟器,适用于模拟和射频电路,包括嘈杂的双端口研究附Matlab代码
  • 缺失数据处理实战指南:从机制识别到7种落地方法
  • 物联网智能锁赋能网约房、民宿行业:筑牢安全防线,轻量化降本增效
  • i.MX28 EVK嵌入式开发:从硬件架构到原型实战全解析
  • 别再死记硬背了!用几个真实代码片段,帮你彻底搞懂TypeScript的interface和type
  • 3个步骤告别Mac数字垃圾:Pearcleaner深度清理实战指南
  • 2026年HDPE双壁波纹管选购指南:湖南源头工厂实力对比与选型建议 - GrowthUME
  • 如何精准控制Windows电脑风扇:FanControl完全配置指南
  • 2026年6月最新解读:东莞精密模具定制服务商全面测评与优质供应商推荐 - GrowthUME
  • PyTorch模型部署实战:model.eval()和torch.no_grad()到底该用哪个?(附代码对比)
  • 选题毫无头绪?博导推荐这几个AI论文软件
  • 2026重庆iPhone 17屏幕维修深度解析:从超薄玻璃到微米级贴合的技术博弈
  • 2026实测:微信视频号视频保存到手机相册方法,视频号视频无法直接下载怎么办
  • 别再只学K8s了!从Docker原理到etcd集群搭建,这份云原生底层核心知识清单请收好
  • String 与new String有什么区别