第一章-H20双机16卡DeepSeek-V4-Flash-vLLM生产部署实践

第一章-H20双机16卡DeepSeek-V4-Flash-vLLM生产部署实践

Deng YongJie's blog 2 2026-03-28

H20 双机 16 卡 DeepSeek-V4-Flash vLLM 生产部署实践

这篇文章整理的是一个 H20 双机 16 卡推理服务的公开版落地经验。目标模型是 DeepSeek-V4-Flash,服务框架使用 vLLM OpenAI-compatible API,分布式执行使用 Ray,运行形态使用 Docker 容器。为了适合公网发布,文中不会出现原始节点名、IP 地址、模型绝对路径、内部镜像仓库、日志路径和内部业务信息,相关位置统一用占位符表示。

vllm-deepseek-docker-ray-architecture

一、为什么不是简单 docker run vllm

单机小模型部署时,一个 vLLM 容器、一个模型路径、一个 API 端口通常就能跑起来。但 DeepSeek-V4-Flash 这类 MoE、FP8、长上下文模型部署到双机 16 卡时,真正的难点在于四层协同:

层级 关键点 失败表现
宿主机层 GPU、驱动、Docker、NVIDIA Container Toolkit 容器看不到 GPU、驱动能力不匹配
网络层 管理网、RoCE 数据面、GID、HCA、ARP/RPF Ray 加入失败、NCCL fallback、跨机慢
分布式层 Ray head/worker、placement group、GPU 资源 worker lost、GPU 资源不足、服务启动卡住
vLLM 层 TP/PP、KV cache、MoE、FP8、tool parser OOM、模型加载失败、首 token 延迟异常

生产部署的目标不是“启动一次成功”,而是要做到环境可检查、参数可复现、日志可定位、服务可压测、失败可回滚。

二、推荐架构

第一条是业务入口链路。业务方访问入口代理或 vLLM API Server,API 使用 OpenAI-compatible 协议,最常用的是 /v1/chat/completions/v1/completions/v1/models/health。生产中建议前面接 Nginx、Envoy 或 HAProxy,用于健康检查、TLS、鉴权、限流和多入口分流。

第二条是 Ray 控制面链路。Ray head 运行在 head 节点,worker 节点加入 Ray 集群。控制面建议绑定管理网,例如 <management-bond>,不要和 RoCE 数据面混用。Ray 看到的 GPU 资源应该是双机共 16 张卡。

第三条是 NCCL 数据面链路。跨机 Tensor Parallel 或 Pipeline Parallel 通信依赖 RoCE/RDMA。容器必须能看到 /dev/infiniband,NCCL 需要绑定正确的 HCA 列表、GID index 和 socket interface。日志中应能看到 Using network IBGDRDMA 等证据,避免静默退回 TCP/socket。

这里要先区分两种生产形态:如果目标是一个跨双机的单模型副本,vLLM 主流写法是每节点内做 TP、节点间做 PP,例如 2 台 8 卡节点使用 TP=8, PP=2。如果模型单机 8 卡就能放下,也可以部署两个独立 TP=8, PP=1 副本,再由入口代理分流;这属于服务级副本扩展,不是一个跨 16 卡的 vLLM engine。

生产上还要把多节点通信放在隔离网络里。Ray、PyTorch Distributed、NCCL、KV cache 传输都不应该直接暴露到公网;对外只暴露经过鉴权、限流和审计的 API 入口。

三、部署前环境检查

检查项 目标
OS / Kernel 双节点版本一致,内核参数可控
GPU 每台 8 卡可见,nvidia-smi -L 正常
Driver / CUDA capability 满足目标 vLLM 镜像和模型要求
Docker 支持 --gpus all,容器内可见 GPU
NVIDIA Container Toolkit 版本一致,runtime 正常
/dev/infiniband 宿主机和容器内均可见
RoCE GID 目标 GID index 为 RoCE v2
ARP / RPF 多网卡场景下避免回包路径异常
模型目录 本地可读,权重、tokenizer、config 完整
镜像能力 包含 vLLM、Ray、PyTorch、RDMA 工具

容器 GPU 检查可以用类似命令:

docker run --rm \
  --gpus all \
  --network=host \
  --ipc=host \
  <cuda-or-vllm-image> nvidia-smi

RDMA 工具建议至少包含:

ibv_devinfo
ibdev2netdev
show_gids

如果官方 vLLM 镜像没有这些工具,可以做一个很薄的派生镜像,只增加 rdma-coreiproute2curlnet-tools 等诊断工具。

四、容器运行方式

双机推理服务建议使用 host network,减少容器网络对 Ray、NCCL、RoCE 的干扰。典型容器形态如下:

docker run -d \
  --name <vllm-ray-container> \
  --gpus all \
  --network=host \
  --ipc=host \
  --shm-size=256g \
  --ulimit memlock=-1:-1 \
  --ulimit stack=67108864 \
  --cap-add IPC_LOCK \
  --device=/dev/infiniband \
  -v /dev/infiniband:/dev/infiniband \
  -v <model-path>:<model-path>:ro \
  -v <log-dir>:<log-dir> \
  -e NCCL_NET=IB \
  -e NCCL_SOCKET_IFNAME=<management-bond> \
  -e NCCL_IB_GID_INDEX=<gid-index> \
  -e NCCL_IB_HCA=<hca-list> \
  -e NCCL_ASYNC_ERROR_HANDLING=1 \
  -e NCCL_IB_DISABLE=0 \
  -e GLOO_SOCKET_IFNAME=<management-bond> \
  -e VLLM_HOST_IP=<node-management-ip> \
  <vllm-image> sleep infinity

这里有几个容易踩坑的点。

--network=host 不是为了省事,而是为了让 Ray、vLLM、NCCL 在多网卡环境中更可控。--ipc=host 或足够大的 --shm-size 对 PyTorch/vLLM 也很重要。--device=/dev/infiniband 和卷挂载同时配置,是为了让容器内 RDMA 诊断工具和 NCCL 都能看到设备。

五、Ray 启动顺序

推荐顺序是先容器、再 Ray、再 vLLM。

head 节点:启动容器 -> ray start --head
worker 节点:启动容器 -> ray start --address <head-ip>:6379
head 节点:检查 ray status -> 启动 vLLM API Server

Ray 检查重点不是“命令返回成功”,而是资源视图是否正确。应该看到两台节点 active,并且总 GPU 数为 16。若 Ray 资源不足,vLLM 后续 placement group 会失败或一直等待。

六、vLLM 参数基线

DeepSeek-V4-Flash 是 MoE + FP8 + 长上下文模型,不建议一开始就把上下文和并发拉满。一个更稳的首轮基线可以这样设计:

vllm serve <model-path> \
  --host 0.0.0.0 \
  --port <api-port> \
  --served-model-name DeepSeek-V4-Flash \
  --trust-remote-code \
  --distributed-executor-backend ray \
  --tensor-parallel-size 8 \
  --pipeline-parallel-size 2 \
  --dtype auto \
  --kv-cache-dtype fp8 \
  --max-model-len 65536 \
  --gpu-memory-utilization 0.88 \
  --max-num-seqs 8 \
  --enable-expert-parallel \
  --tokenizer-mode deepseek_v4 \
  --tool-call-parser deepseek_v4 \
  --enable-auto-tool-choice \
  --reasoning-parser deepseek_v4

参数解释:

参数 建议
tensor-parallel-size 对 2 台 8 卡节点,单跨机副本优先设为每节点 GPU 数,即 8
pipeline-parallel-size 对 2 节点跨机副本设为 2,让模型层按 pipeline stage 分布到两台机器
max-model-len 先用 65K,稳定后再扩到 128K/256K
kv-cache-dtype FP8 有利于降低 KV cache 压力
gpu-memory-utilization 先保守,避免碎片和 OOM
max-num-seqs 从小并发启动,逐步增加

如果使用的是深度定制 DSFlash 镜像,可能还有额外 parser、block size 或 speculative decoding 参数。不建议把这类非通用参数写死;先用 vLLM 主线参数跑通,再按镜像说明做专项 A/B。

TP=16, PP=1 也可以作为实验项,即 Tensor Parallel 横跨两台机器。但这会让大量逐层 all-reduce 穿过跨机 RoCE,对网络、NCCL、GDRDMA 和拓扑一致性要求更高。除非跨机互联已经被验证足够稳定,否则它更适合作为压测对照,而不是首轮生产基线。

如果显存不足,优先按下面顺序收敛:降低 max-num-seqs,再降低 max-model-len,最后再调整 gpu-memory-utilization。不要一开始就把显存利用率拉到极限,否则后续排障很难判断是模型、KV cache、碎片还是通信导致的问题。

七、服务验证

服务启动后,最少做三类验证。

健康检查:

curl -fsS http://<api-host>:<api-port>/health
curl -fsS http://<api-host>:<api-port>/v1/models

功能冒烟:

curl http://<api-host>:<api-port>/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "DeepSeek-V4-Flash",
    "messages": [
      {"role": "user", "content": "请用一句话介绍你自己。"}
    ],
    "max_tokens": 128,
    "temperature": 0
  }'

通信证据:

grep -E "Using network IB|GDRDMA|NCCL|Ray" <vllm-log>

如果只看 API 能返回,可能会漏掉 NCCL fallback。跨机推理服务必须确认数据面真的走 RoCE/IB/GDRDMA。

八、生产排障经验

第一,镜像能力要先验收。模型 config 支持 DeepSeek V4 不等于当前镜像一定支持对应 architecture、parser、MoE、FP8 和长上下文。

第二,控制面和数据面要分清。Ray、Gloo、API 健康检查可以走管理网;NCCL 数据面要绑定 RoCE HCA。两者混在一起会导致“能启动但性能不稳定”。

第三,日志要从启动阶段开始保留。TileLang lazy compile、Ray worker lost、NCCL fallback、OOM、KV cache 不足都可能只在特定阶段出现。

第四,长上下文不能只靠 max_position_embeddings 判断。模型配置可能支持极长上下文,但实际可服务长度取决于 KV cache、并发、显存碎片和 batch token 策略。

九、参考资料

十、总结

H20 双机 16 卡部署 DeepSeek-V4-Flash 的关键,是把 Docker、Ray、vLLM、RoCE/NCCL 和模型参数放在同一个工程闭环里。正确的落地方式不是复制一条启动命令,而是先检查环境,再固化容器和网络参数,然后按小并发到大并发、短上下文到长上下文逐步压测。

当服务能稳定通过健康检查、功能冒烟、NCCL 数据面验证和三组 workload 压测后,才适合作为后续拓扑优化和业务接入的基线。