部署实验手册:从一张卡到多节点¶
本页把部署章节收敛成一条可执行路径。示例以 OpenAI 兼容接口为目标,不绑定单一引擎;正式上线时固定容器 digest、模型 revision、驱动和 CUDA 版本。
0. 先画拓扑,再写启动命令¶
部署记录至少包含:
| 类别 | 必填字段 | 为什么重要 |
|---|---|---|
| GPU | 型号、显存、ECC、MIG/vGPU | 决定权重、KV Cache 和隔离方式 |
| 主机 | CPU、内存、NUMA、NVMe | 决定 tokenizer、数据加载和 PCIe 争用 |
| 卡间 | PCIe、NVLink、NVSwitch、拓扑矩阵 | 决定 TP/PP/EP 的通信成本 |
| 跨机 | InfiniBand 或 RoCE、带宽、RDMA、交换机 | 决定多节点集合通信是否可用 |
| 软件 | 驱动、CUDA、NCCL、引擎、量化内核 | 决定算子和通信是否真的支持 |
# 单机拓扑,不要只看 nvidia-smi 的卡数
nvidia-smi topo -m
nvidia-smi -q -d MEMORY,POWER,ECC
# NCCL 通信基线,使用与服务相同的容器和网卡
all_reduce_perf -b 8 -e 4G -f 2 -g 8
适用条件:你准备使用 TP、PP、EP 或跨节点服务。
代价:需要占用完整节点并安装 NCCL Tests。
验证方式:保存拓扑输出、all-reduce 带宽、错误计数和运行时环境。
1. 单卡或单副本基线¶
先用最简单的单进程建立质量和性能基线,避免一开始把网络问题误认为模型问题。
vllm serve <model-revision> \
--served-model-name <model-id> \
--host 0.0.0.0 --port 8000 \
--dtype auto \
--max-model-len 32768 \
--gpu-memory-utilization 0.90 \
--enable-prefix-caching
启动后固定三类样本:短对话、长上下文和工具调用。保存首 token、总时延、峰值显存、输出 schema 和错误日志。
curl http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"<model-id>","messages":[{"role":"user","content":"返回 JSON: {\\"ok\\":true}"}],"max_tokens":64}'
2. 单机多卡:先副本,后并行¶
| 条件 | 先试 | 原因 |
|---|---|---|
| 模型单卡可放下,吞吐不够 | 每卡一个副本 + 网关 | 没有跨卡通信,故障隔离简单 |
| 模型单卡放不下,同机 NVLink/NVSwitch | TP | 每层通信更快,适合容量受限 |
| 卡间只有 PCIe,模型仍可切分 | TP 小规模或 PP | 先测通信,不能假设 PCIe 等价于 NVLink |
| MoE 专家很多 | 官方 EP recipe | token routing 可能成为主瓶颈 |
# 只有在拓扑和显存都验证过后才使用
vllm serve <model-revision> \
--tensor-parallel-size 4 \
--max-model-len 32768 \
--max-num-seqs 64
不要做的事:把四张 PCIe 卡的显存简单相加,然后直接把 TP=4 推向生产。要测 all-reduce、prefill、decode、长短请求混合和卡故障恢复。
3. 多节点:网络先于并行策略¶
多节点服务的最小验收顺序:
- 容器内解析到正确的 RDMA 设备和网卡。
- NCCL 测试在目标带宽范围内稳定运行。
- 所有 worker 同时启动,不能只启动部分 rank 等待超时。
- 模型权重在节点上按 hash 命中,避免上线时同时拉取数百 GB。
- 一个 worker 退出后,网关摘流、控制器重建,旧请求在上限内失败或重试。
export NCCL_DEBUG=INFO
export NCCL_IB_HCA=<rdma-device>
export NCCL_SOCKET_IFNAME=<data-interface>
export NCCL_ASYNC_ERROR_HANDLING=1
环境变量只是一种排障手段,不是性能保证。生产配置应把最终生效值写进镜像或启动清单,避免依赖人工 shell 状态。
4. 容量模型¶
并发上限 = min(
KV Cache 可用 token / 单请求平均活跃 token,
引擎 max_num_seqs,
网关和租户配额,
P95 时延允许的排队长度
)
每成功任务成本 =
(GPU 小时 + CPU/内存 + 存储 + 网络 + 重试成本 + 人工接管成本)
/ 通过验收的任务数
只用 GPU 利用率扩容会漏掉 KV Cache 和队列压力。优先观测活跃 KV token、排队时间、TTFT P95、TPOT、错误率和每成功任务成本。
5. 灰度、回滚和证据¶
revision A (100%)
-> revision B (0%, warm)
-> replay 脱敏流量
-> B 1% / 5% / 25%
-> 质量、严重错误、P95、成本均通过
-> B 100%
灰度时不要同时升级模型、引擎、驱动和 chat template。若必须一起升级,至少拆分两个实验窗口,并保存每个 revision 的权重 hash、镜像 digest、配置、原始输出和失败样本。
故障排查顺序¶
| 现象 | 先检查 | 不要先做 |
|---|---|---|
| OOM | 权重精度、KV Cache、max-model-len、并发 | 直接加 gpu-memory-utilization |
| TTFT 高 | prefill 队列、长短请求混池、CPU tokenizer | 只看 decode tokens/s |
| TP 扩容后变慢 | nvidia-smi topo -m、NCCL 带宽、PCIe 链路 |
盲目增加 TP size |
| 多节点随机超时 | RDMA、MTU、NCCL 异步错误、rank 同步 | 只增加客户端重试 |
| 输出不一致 | revision、模板、采样、量化 kernel | 先责怪模型“退化” |
| 灰度失败 | 失败样本、工具参数、回滚 alias | 用平均分掩盖严重错误 |
部署完成定义¶
[ ] 模型 revision、镜像 digest、驱动和 CUDA 已固定
[ ] 权重 hash 校验和缓存预热已验证
[ ] PCIe/NVLink/NVSwitch/RDMA 拓扑和通信基线已存档
[ ] 单请求、混合流量、峰值和故障演练已完成
[ ] 网关有准入、超时、限流、重试和降级
[ ] 灰度指标和自动回滚条件已写入发布单
[ ] 任务通过率和每成功任务成本可归属到模型版本