前两篇讲了 Agent 与工具调用,本质是”应用层”。再往下一层,是支撑所有 Agent / Chat / 向量检索 rerank 的推理服务层(Serving Layer)。单机跑一个
vllm serve谁都会,但当你要同时托管 20 个模型、800 个 LoRA、每秒 2 万条请求、SLO p99 < 3s、成本要可预测,工程复杂度会陡然上升一个数量级。这一篇把”把推理引擎做成服务”这件事拆开:服务层选型(Triton / Ray Serve / KServe / vLLM OpenAI Server …)、多 GPU 拓扑、自动扩缩容、LoRA 多租户热加载、PD 分离部署、流量路由、K8s GPU 调度、Serverless GPU、国产云厂商的托管方案,以及灾备多活。
一、为什么”引擎”不是”服务”
1.1 从 demo 到生产的 12 个坑
把
python -m vllm.entrypoints.openai.api_server
跑起来,和把它变成公司级推理平台,中间差的远不只是
Dockerfile。生产化至少要回答下面这些问题:
- 多模型共存:Qwen3-72B、DeepSeek-V3、Qwen3-Embedding、bge-reranker-v2 要不要共享 GPU?如何调度?
- 多租户隔离:A 团队一次灌 10k QPS,不能打垮 B 团队的线上服务。
- 弹性伸缩:工作日白天 120 副本,凌晨 12 副本。扩容要几分钟?权重 140 GB 怎么拉?
- 流量路由:长上下文请求 ≥ 32k token 走专用池;短请求(< 2k)走共享池;带 prefix cache 的要做 session affinity。
- 金丝雀 / 灰度:新微调版本上线先切 1% → 5% → 100%,发现 KV cache 命中率掉了要一键回滚。
- 模型热切换:不停机加载/卸载 LoRA adapter、不停机切主模型版本。
- 可观测:每个请求的 TTFT、ITL、token/s、队列长度、GPU SM 利用率、HBM 占用、NCCL 带宽都要能查到。
- 灾备:一个可用区挂了,业务要能在 60s 内切到另一个可用区。权重要提前同步。
- 冷启动:从 Pod 调度 → 拉镜像 → 下载权重 → 加载到 HBM → warmup 首包,通常 5–15 分钟。
- 成本追踪:按 tenant 计 token 成本,按模型 / 按业务线分摊 GPU 账单。
- 协议兼容:OpenAI Chat Completions API 几乎是事实标准,Anthropic Messages、Gemini generateContent、国产厂商自有 API 都要能接。
- 合规与安全:输入 PII 脱敏、输出内容审核、审计日志保留期。
前面 11、12、13 篇关心的是”单 GPU 把 token 吐得多快”;这一篇关心的是”一整个集群能不能稳定、便宜、可维护地吐 token”。
1.2 分层视图
┌───────────────────────────── Client / Agent ─────────────────────────────┐
│ OpenAI SDK · Anthropic SDK · LangChain · 业务微服务 │
└──────────────────────────────────┬──────────────────────────────────────┘
▼
┌──────────────────── LLM Gateway(下一篇 22)────────────────────────────┐
│ 多租户鉴权 · 限流配额 · 路由 · 审计 · 内容审核 · 成本统计 │
└──────────────────────────────────┬──────────────────────────────────────┘
▼
┌──────────────────── 推理服务层(本篇)──────────────────────────────────┐
│ KServe / Ray Serve / Triton / BentoML / K8s Deployment │
│ 自动扩缩 · 模型仓库 · PD 分离 · LoRA 多租户 · Session Affinity │
└──────────────────────────────────┬──────────────────────────────────────┘
▼
┌──────────────────── 推理引擎(第 13 篇)────────────────────────────────┐
│ vLLM · SGLang · TensorRT-LLM · TGI · MindIE · XServe │
└──────────────────────────────────┬──────────────────────────────────────┘
▼
┌─────────────────── 硬件底座(第 2–4 篇)────────────────────────────────┐
│ GPU · NVLink · IB/RoCE · 昇腾 / 寒武纪 / 燧原 │
└─────────────────────────────────────────────────────────────────────────┘
网关(Gateway)和服务层(Serving)经常被混在一起,其实职责不同:网关关心”谁”和”多少”(身份、配额、合规),服务层关心”在哪”和”怎么跑”(拓扑、实例、KV cache、GPU)。很多团队早期放在一个进程里,规模上来一定会拆。
1.3 一次真实事故的复盘
为了让上面 12 个问题具象化,这里复盘一次 2024 年末我们团队亲历的事故(细节脱敏):
- 背景:单一 vLLM 集群、32 副本 Qwen2.5-72B、TP=4、H100,KV cache 占用 65 GB/副本。
- 触发:业务方上线了一个”长文档问答”功能,平均 prompt 12k token,未上线前平均 800 token。
- 现象:p99 TTFT 从 1.8s 涨到 28s,GPU 利用率反而从 75% 掉到 40%,队列长度暴涨。
- 根因:
- 没做长短分流。长请求把 prefill 填满,短请求被饿。
- 没有 Session affinity,长对话每轮都重算 12k prefix。
- 没开
--enable-prefix-caching,历史 KV 无法复用。 - 扩容基于 CPU 利用率,GPU 爆了但 HPA 没触发。
- 紧急修复:打开 prefix caching、切到
KEDA +
num_requests_waiting扩容、在网关层按 input 长度拆到两个池。 - 长期:上线 LMCache 跨副本 KV 复用;后续在高端客户上线 PD 分离。
教训:推理服务的稳定性,80% 来自路由和拓扑的正确性,20% 才是引擎参数。
二、服务层工具选型
2.1 Nvidia Triton Inference Server
Triton 是老牌推理服务框架,设计目标是”模型无关”,支持 TensorRT、TensorRT-LLM、vLLM、PyTorch、ONNX、Python、FIL 等多个 backend。它的几个杀手级特性:
- Dynamic Batching:非 LLM 模型可按 latency 窗口自动 batch。
- Ensemble / Business Logic Scripting(BLS):在 Triton 里用 Python backend 组合多个模型(ASR → LLM → TTS)。
- Model Repository:基于目录结构的模型版本管理,支持 poll 模式热加载。
- gRPC / HTTP / metrics:自带 Prometheus 指标、可对接 DCGM。
LLM 场景下,Triton 主要作为 TensorRT-LLM 的官方
server(tensorrtllm_backend)使用,适合
Nvidia
全家桶用户。缺点是配置文件(config.pbtxt)偏繁琐、Python
生态不如 Ray Serve 灵活。
目录结构示例:
model_repository/
├── qwen3-72b/
│ ├── config.pbtxt
│ └── 1/
│ └── model.plan # TRT-LLM engine
└── ensemble_rag/
├── config.pbtxt
└── 1/
└── model.py # BLS 脚本
2.2 Ray Serve
Ray Serve 是 Anyscale 出品的 Python-first 服务框架,和 Ray(任务 / 集群)深度集成。适合:
- 异构模型组合:一个 deployment graph 同时挂 LLM、embedding、reranker、CV、音频。
- 有状态 actor:每个副本就是一个 Ray actor,天然适合 vLLM engine 这种需要常驻显存的服务。
- DAG / Fan-out:RAG pipeline
天然可以写成
@serve.deployment+ingress.bind(rag_chain)。 - 自动扩缩:基于 replica 级别的 RPS、队列长度。
缺点:对 K8s 原生语义不够好(Ray 自带集群管理),跨语言支持弱,对 SRE 团队”Ray 集群”本身是新的运维对象。
2.3 KServe(K8s CRD 标准)
KServe 脱胎于 KubeFlow 的 KFServing,目标是在 K8s 上用标准 CRD 描述推理服务。核心资源:
InferenceService:最顶层资源,描述一个服务(transformer + predictor + explainer)。ServingRuntime/ClusterServingRuntime:引擎运行时模板(vLLM、Triton、Hugging Face TGI、TorchServe 等)。- 集成 Knative Serving(scale-to-zero)、Istio(流量切分)、Cert-Manager(TLS)。
KServe 的定位类似”K8s 原生的 SageMaker Endpoint”。对大部分想在 K8s 上跑推理又不想自己写 Operator 的团队,是默认选择。下文有 YAML 示例。
2.4 Seldon Core
Seldon Core 是 KServe 的”兄弟项目”(历史更早),也是 K8s CRD。v2 版本叫 Seldon Core v2,架构更偏流水线和多模型编排(model mesh),适合大量小模型的场景——比如几千个推荐模型。LLM 场景用得少。
2.5 TorchServe
PyTorch 官方的模型服务器。API 简单、对 Torch 生态友好,但 LLM 专用优化(连续批处理、Paged Attention)需要自己造或走 PyTorch / Meta 系的发行版(TorchServe + vLLM)。国内 LLM 场景很少单独用 TorchServe。
2.6 BentoML / Yatai / OpenLLM
BentoML 强调”Python 开发者友好”:用装饰器把推理函数包成
Service,bentoml build 打成 OCI
镜像,bentoml deploy 到 K8s(Yatai)或
BentoCloud。对初创团队、算法同学自助上线小型服务非常友好。OpenLLM
是他们针对 LLM 的子项目,支持 vLLM / TensorRT-LLM。
2.7 vLLM / SGLang 自带 OpenAI Server
这是 2024–2025 年的事实默认:直接起一个
python -m vllm.entrypoints.openai.api_server --model ...,加一个
nginx / Envoy
前面当负载均衡,就是一个”够用”的生产服务。SGLang 的
python -m sglang.launch_server 类似。
什么时候它不够用?
- 需要跨模型 / 跨引擎路由(vLLM + TRT-LLM 混合)。
- 需要深度定制调度(如按 tenant 隔离 KV block pool)。
- 需要 PD 分离、动态 LoRA 切换、模型热升级。
满足这些时就要上 KServe / Ray Serve 之类。
2.8 选型决策表
| 场景 | 推荐 |
|---|---|
| 单模型、快速上线、OpenAI 协议 | vLLM / SGLang 自带 server + Envoy |
| K8s 原生、标准化、需要 GitOps | KServe + vLLM ServingRuntime |
| Python 复杂 DAG、多模型组合 | Ray Serve |
| Nvidia 全家桶、TRT-LLM 重度用户 | Triton + tensorrtllm_backend |
| 算法同学自助打包 | BentoML / OpenLLM |
| 托管省心 | 云厂商(PAI-EAS / 火山 / Bedrock / Vertex) |
三、多 GPU 拓扑
第 6 篇讲了训练并行策略,推理这边简单一些,但同样重要。
3.1 单机多卡:TP 为主
单节点 8×H100 SXM(NVLink 900 GB/s 互联),跑 72B、110B
模型的首选是 Tensor Parallel(TP)。vLLM
里就是 --tensor-parallel-size 8。TP
的通信模式是 all-reduce / all-gather,对 NVLink
友好,跨节点会显著掉性能(IB 200 Gbps ≈ 25
GB/s,比 NVLink 慢一个数量级)。
经验公式:
- 70B fp16 ≈ 140 GB 权重 + KV cache,至少 2×H100-80G(TP=2)。
- 405B fp16 ≈ 810 GB,单机 8×H100-80G 装不下,必须跨机。
- FP8 / INT4 量化后(见 14 篇)可大幅压缩,72B 能单卡 H100 跑起来。
3.2 多机:TP × PP
跨节点时:
- TP 留在机内(NVLink / NVSwitch 域)。
- PP(流水线并行)跨机,用 IB / RoCE。PP 通信量小(只有 stage 边界的激活),对带宽不敏感。
- EP(专家并行) 用于 MoE 模型(DeepSeek V3 / Qwen3-MoE),把 expert 切到不同节点。
典型拓扑:DeepSeek V3 671B 推理,单副本跨 2 机 16 卡
H20,TP=8, PP=2, EP=16。
3.3 副本(DP)扩展
同一个模型配置,多个独立副本,前面挂负载均衡——这是”水平扩容”。副本数由 QPS 决定,不由模型大小决定。
┌── Replica 1 (8×H100, TP=8) ──┐
LB ──┬────┼── Replica 2 (8×H100, TP=8) ──┤──► Clients
│ └── Replica 3 (8×H100, TP=8) ──┘
3.4 拓扑感知调度
K8s 默认调度器对 GPU 拓扑无感知。你需要:
- Nvidia device plugin:把 GPU 当成资源
nvidia.com/gpu。 - NVIDIA GPU Operator:一键部署 device plugin + DCGM + MIG 管理。
- Topology Manager:Kubelet 的特性,尽量把同一个 Pod 的 GPU / CPU / NUMA 放一起。
- 拓扑感知调度器:Volcano、Koordinator、kai-scheduler,理解”这 8 张卡必须在同一个 NVSwitch 域”。
四、自动扩缩容
4.1 指标驱动:KEDA
HPA 默认只能基于 CPU / Memory,不够。KEDA(Kubernetes Event-Driven Autoscaler) 支持 40+ 种 scaler:Prometheus、Kafka、Redis、SQS 等。LLM 场景常用:
- Queue length scaler(通过
Prometheus):
vllm_num_waiting_requests> 阈值就扩容。 - GPU utilization scaler:DCGM 采集
DCGM_FI_DEV_GPU_UTIL。 - 自定义指标:P99 TTFT > 3s、prefill batch 占满时长。
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: vllm-qwen3-scaler
spec:
scaleTargetRef:
name: vllm-qwen3
minReplicaCount: 2
maxReplicaCount: 32
pollingInterval: 15
cooldownPeriod: 120
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
query: |
avg(vllm:num_requests_waiting{service="qwen3"})
threshold: "8"4.2 Knative Serving:scale-to-zero
Knative Serving 能把无流量的模型缩到 0 副本——但 LLM 推理场景慎用。模型权重几十到几百 GB,冷启动 5–15 分钟,用户第一个请求就超时了。Knative 适合:
- 小模型(< 10 GB)、长尾使用。
- 内部批处理任务,延迟不敏感。
- 配合”预热副本”策略(
min-scale=1)的非主力模型。
4.3 冷启动优化
这是 LLM serving 最大的工程痛点之一。一个权重 140 GB 的 Qwen3-72B,冷启动时间分解:
总冷启动 ≈ 10 分钟
├── Pod 调度 + 镜像拉取 ~60s → 镜像加速
├── 权重下载(S3 → 本地 NVMe) ~180s → 本地缓存 / pre-pull
├── 权重 mmap 到 HBM ~120s → fast loader
├── CUDA graph 构建 ~60s → 持久化
├── warmup(生成几条假请求) ~30s → 保留
优化手段:
- PVC / hostPath 缓存:每个节点的 NVMe 上缓存权重,相同模型不再重复下载。
- 镜像加速:Dragonfly、P2P 分发;阿里云用 ACR 镜像加速;AWS 用 SOCI。
- CSI snapshot:权重做成只读卷快照,新副本秒级挂载。
- Pre-pull DaemonSet:节点一上线就后台拉权重,不等 Pod 调度。
- Safetensors 多线程加载 /
torch.load(mmap=True):加载阶段 3–5 倍加速。 - CUDA graph 缓存:vLLM 的
--enforce-eager=False首次构建慢,可落盘复用。 - Over-provision:keep
N+1副本 warm,哪怕有 5% 冗余也值。
五、模型热加载与多租户 LoRA
5.1 为什么 LoRA 多租户重要
第 19、20 篇讨论了业务层面经常需要”一个基座模型 + 几十到几千个小微调”的模式:某客服场景、某风控场景、某领域术语各一份 LoRA(几十 MB 到几百 MB)。如果为每个 LoRA 起一副 72B 副本,成本爆炸。
解决方案:共享基座 + 动态加载 LoRA adapter。
5.2 S-LoRA / Punica / vLLM LoRA
- S-LoRA(UCB 2023):首次提出把多个 LoRA adapter 同时 serve 的系统方案,支持数千个 adapter 并发,核心是统一的内存管理和 batched gather。
- Punica(CMU 2023):SGMV(Segment Gather Matrix-Vector)kernel,让不同 adapter 的 batch 能一把算完。
- vLLM LoRA
Adapter(生产默认):
--enable-lora --max-loras 16 --max-lora-rank 64,请求头带model: qwen3-lora-finance,vLLM 查表命中对应 adapter。Adapter 可以在 S3 / OSS 上,动态拉下来。
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen3-32B \
--enable-lora \
--max-loras 32 \
--max-lora-rank 64 \
--lora-modules \
finance=s3://bucket/loras/finance-v3 \
legal=s3://bucket/loras/legal-v25.3 LMCache:跨请求 KV 复用
LMCache 把 KV cache 外置到 CPU 内存 / NVMe / 对象存储,让相同 prefix 在不同副本间也能复用。典型用途:
- RAG:几十份文档反复命中 → prefix 固定 → 把 KV 存下来。
- System prompt 很长的 agent:每次 reload KV 比 recompute 快 5–20 倍。
- 会话级缓存:用户同一 session 第二轮请求直接复用上一轮 KV。
vLLM v0.6+ 已原生集成
--kv-transfer-config。
六、PD 分离部署(Prefill-Decode Disaggregation)
6.1 为什么要分离
LLM 推理两阶段差异极大:
| 阶段 | 计算特征 | 瓶颈 | 批处理 |
|---|---|---|---|
| Prefill | 一次 prompt、大矩阵乘 | 算力 bound | 喜欢大 batch |
| Decode | 每次一个 token、KV 查表 | 访存 bound | 喜欢小步快 |
同一个 GPU 上混跑,prefill 的尖峰会抢占 decode 的带宽,造成 ITL(inter-token latency)抖动。经典连续批处理用 “chunked prefill” 缓解(见 12 篇),但没根治。
PD 分离 的思路:把 prefill 和 decode 放到不同 GPU 池,prefill 完成后把 KV cache 通过高速网络传给 decode 节点。
6.2 主流方案
- Mooncake(Kimi / 月之暗面):首个生产级 PD 分离系统,KV 存到 CPU 内存池(“KVCache Store”),RDMA / GDS 高速传输,核心创新是 KV-centric 调度(按 KV 亲和性而非请求亲和性分配)。2024 年开源后成为标准参考。
- DistServe(UCSD 2024):最早系统研究 PD 分离的论文,论证在相同 SLO 下吞吐提升 4–8 倍。
- Splitwise(Microsoft):Azure 上的工程落地,同时做节能(prefill 用高算力卡,decode 用高带宽卡)。
- DeepSeek V3 的 PD + MoE 分离:不仅 PD 分离,MoE expert 也分离到专用 EP 节点,prefill 节点、decode 节点、expert 节点三层。
- vLLM v1:原生支持
--kv-transfer-config,可配合 NIXL、Mooncake Store、LMCache 做 KV 传输。
6.3 PD 分离架构 SVG
6.4 何时上 PD 分离
不要过早上。判据:
- Prefill / Decode 算力与带宽需求差异大(长 prompt、短输出的场景,如文档 QA)。
- SLO 对 TTFT 和 ITL 都敏感,chunked prefill 已经调不动。
- 集群 ≥ 数十节点,运维能承担额外复杂度(KV 存储、网络拓扑、调度器)。
小规模集群,老老实实用 vLLM + chunked prefill 就够了。
6.5 PD 比例与异构搭配
PD 分离不是”各 50%“。实测中,比例与负载高度相关:
| 业务形态 | 平均输入 | 平均输出 | 典型 P:D 比 |
|---|---|---|---|
| 短 Chat | 500 | 300 | 1 : 3 |
| 文档 QA | 12k | 500 | 3 : 1 |
| 代码补全 | 6k | 200 | 4 : 1 |
| Agent 多轮 | 8k(含历史) | 1k | 2 : 1 |
工程上,Prefill 池用算力强的卡(H100 SXM)、Decode 池用带宽强成本低的卡(H20 / L20 / MI300X) 能得到最优的 TCO。DeepSeek V3 推理就是这个配方。
6.6 KV 传输介质
KV 从 Prefill 到 Decode,要跨节点搬数据。几种典型通道:
- RDMA (IB/RoCE):最主流,GPUDirect RDMA(GDR)能让 KV 直接从一个 GPU HBM 搬到另一个,经过 CPU bounce 的开销最低。
- NVLink-Network / NVSwitch:同机柜 NVLink Fabric 下,KV 搬运近乎零开销,但受限于机柜物理域。
- NIXL(NVIDIA Inference Xfer Library):统一抽象 RDMA / NVLink / GDS,vLLM v1、Dynamo 都已集成。
- 共享 CPU 内存 + DPDK:成本更低但延迟较高,适合 batch 场景。
七、流量路由
7.1 Session affinity(prefix cache 友好)
前面讲了 KV cache 复用:同一用户同一会话的多轮对话要尽量命中同一副本,否则 prefix cache 失效,每轮都要重算 system prompt + 历史。
做法:
- 一致性哈希(consistent
hashing):
hash(session_id) mod N。 - Envoy/Istio 的
hash_policy: header: x-session-id。 - 自定义路由:按 prompt prefix 指纹路由,用 bloom filter 或 learned router 判断”哪个副本最可能已有这段 KV”。vLLM 的 Sticky Routing extension、SGLang Router 都在做这方面。
7.2 长短请求分流
混部长请求(输入 32k+、输出 4k+)和短请求(输入 500、输出 100)会严重拖慢短请求的 p99。分流策略:
- 两池子:长请求池(大 max_model_len、大 KV cache)vs 短请求池(高并发、小 KV)。
- 按 input token 数路由:网关层估算 token 数(tiktoken / BPE),> 8k 走长池。
- SLO 感知:给每类流量定不同 SLO,动态调权重。
7.3 成本 / 延迟 SLO 路由
多模型场景下,可以做 model cascade:
- 先走 4B 小模型。
- 置信度低 / 用户明确选了 “deep mode” 再走 72B。
- 最终兜底走顶级模型(DeepSeek-V3、GPT-5)。
这本质是网关层的事(下一篇讲),但服务层要提供不同模型的同构 API 和一致的 metric 口径。
八、模型仓库
权重从哪里来?
- HuggingFace Hub:全球事实标准,支持
huggingface-cli download、LFS、safetensors。 - ModelScope(魔搭):阿里牵头的国内镜像 + 原生发布源。Qwen、GLM、百川、面壁等国产模型基本都双发 HF + MS。国内访问 HF 困难时优先用 MS。
- 企业私仓:
- S3 / OSS / COS:最常见,版本以 prefix
区分(
s3://models/qwen3-72b/v1.2.0/)。 - HuggingFace 私有模型:付费企业版支持 SSO + 私仓。
- OCI Artifact:Distribution spec 也能装模型(ORAS 工具),好处是和镜像仓库共用基础设施。
- S3 / OSS / COS:最常见,版本以 prefix
区分(
- Harbor / ACR:把模型做成 OCI 制品,与 K8s / ArgoCD 集成最平滑。
最佳实践:私仓 + 哈希校验 + 不可变版本。不要依赖”latest”,上游偶尔会覆盖。
九、K8s 上的 GPU
9.1 GPU 接入
- nvidia-device-plugin:把
/dev/nvidia*和 GPU 当成 K8s 可调度资源。 - GPU Operator:一键部署 device plugin、DCGM、MIG Manager、node feature discovery。
- 资源请求:
resources.limits.nvidia.com/gpu: 8。
9.2 MIG(Multi-Instance GPU)
A100 / H100 支持把一张卡切成 7 份(1g.10gb、2g.20gb、3g.40gb、7g.80gb)。适合:
- 嵌入模型、小 reranker、安全分类器——用不到整卡。
- 多租户硬隔离(MIG 的 HBM 和 SM 都是物理隔离)。
不适合:LLM 推理(fragmentation,MIG 之间不能 NVLink)。
9.3 拓扑感知调度
- Topology Manager:kubelet 级别,确保同一个 Pod 的 GPU/NIC/CPU 在一个 NUMA。
- Volcano:批处理调度器,支持 gang scheduling(多卡同时起,要么都起要么都不起),LLM 多卡副本必备。
- Koordinator / kai-scheduler:更懂 NVLink / NVSwitch 拓扑。
- Kueue:K8s 原生作业队列,可做 tenant 级 quota。
9.4 网络
- RDMA 共享:
rdma/hcaresource + SR-IOV,让 Pod 能用 IB。 - HostNetwork:省 CNI 开销,但失去网络策略,慎用。
- Multus:给 Pod 加第二张网卡走 RDMA。
9.5 KubeFlow / Volcano / Arena
- KubeFlow:端到端 ML 平台,Pipelines / Training Operator / Notebook。
- Volcano:批处理 + gang scheduling,训练 / 推理都常用。
- Arena(阿里):KubeFlow 的 CLI 封装,国内用户友好。
十、Serverless GPU
10.1 商业方案
- Modal:DX 最好的 Serverless GPU
平台,Python 装饰器
@app.function(gpu="A100")直接上线。冷启动秒级(靠镜像快照 + 权重 FS 层)。 - RunPod:按秒计费的 GPU serverless,A100/H100 在售,适合批处理。
- Replicate:主打开源模型一键 API,按 token/秒双计价,偏 2C。
- Fly Machines:全球 PoP 部署,启动快(Firecracker VM),适合小模型。
- AWS Lambda GPU / SageMaker Serverless Inference:AWS 体系内的 serverless,支持小模型。Bedrock 本身也是 serverless 调用。
- Azure Container Apps(GPU)/ GCP Cloud Run(GPU):两家都在 2024–2025 推出了 Serverless GPU。
10.2 适用场景
- 尖峰流量:营销活动、大 V 发帖后的几分钟。
- 长尾模型:调用量低但必须存在。
- 批处理 / 离线任务:embedding、OCR、图文标注。
不适用:核心在线主链路(冷启动风险)、超大模型(权重分发成本)。
十一、国产云厂商托管推理服务
11.1 阿里云 PAI-EAS(Elastic Algorithm Service)
阿里 PAI 平台的推理服务产品。特点:
- 一键部署 HuggingFace 模型、Qwen 系列 model card。
- 支持 blade / TensorRT-LLM / vLLM 多 backend。
- 深度集成 OSS(模型仓库)、ACK(K8s)、SLB(负载均衡)、ARMS(观测)。
- 灰度发布、金丝雀、蓝绿开箱即用。
11.2 火山引擎 veMLP / 方舟
字节旗下,方舟(Ark)对外主要是大模型 API(豆包、DeepSeek 托管),veMLP 则是底层 ML 平台。火山在 RDMA 网络 / 高性能对象存储(TOS)方面投入很大,PD 分离、KV 外存等特性上线较早。
11.3 腾讯云 TI-ACC / TI-ONE
TI-ONE 是腾讯的 ML 平台,TI-ACC 是推理加速产品,支持混元系列和开源模型。与 TDMQ / COS / TKE 集成。
11.4 华为 MindIE Service
华为 CANN 生态的上层服务框架,把 MindIE 引擎(第 13 篇提到)包成 OpenAI 兼容 API,部署在昇腾 910B/910C 集群上。盘古、通义千问昇腾版、DeepSeek 昇腾版均走这个栈。昇腾集群上的事实标准。
11.5 字节 XServe(内部)
字节内部大模型推理服务平台,外部可以通过火山方舟看到它的能力外溢。强调端到端全链路优化、PD 分离、超大规模多租户。
11.6 国际对照
- AWS Bedrock:Serverless,Claude、Llama、Titan 等;企业要私有化见 SageMaker JumpStart。
- Azure OpenAI / AI Foundry:GPT、o 系列、Llama、Mistral。
- GCP Vertex AI:Gemini、Anthropic、Llama;Model Garden 支持一键部署。
- Databricks Mosaic AI Model Serving:主打企业定制 + 评估闭环。
十二、灾备与多活
LLM 推理的 DR(Disaster Recovery)有两大难点:权重大 + GPU 稀缺。
12.1 跨 region 副本
- 主 region 挂 N 副本,备 region 挂 ⌈N/3⌉ warm 副本(日常承载 10–30% 流量)。
- 切流通过上层网关 / DNS(weighted routing)。
- 权重要提前同步。典型做法:OSS/S3 跨区复制 + 节点本地缓存 + pre-pull DaemonSet。
12.2 降级模型
当主模型(例如 405B)某 region 完全不可用:
- 切到同 region 的 降级模型(70B、32B 的 Qwen3、Llama 同能力档)。
- 或切到 备 region 主模型(可能延迟增加 50–150 ms)。
- 最差情况走 外部 API(Bedrock / 方舟),成本提高但保可用。
这需要网关层能做:SLA 检测 → 自动切流 → 回切,且对客户端保持 API 兼容。
12.3 故障演练
- Chaos Engineering:定期 kill Pod、模拟 GPU ECC 错误、断开 IB 链路。
- 引擎级:kill 一个 TP rank 看 vLLM 能否 graceful restart。
- KV 存储:断开 RDMA 看是否 fallback 到 recompute。
十三、代码示例
13.1 KServe + vLLM
KServe 官方有 vllm-openai ServingRuntime
模板。先定义运行时:
apiVersion: serving.kserve.io/v1alpha1
kind: ClusterServingRuntime
metadata:
name: kserve-vllm-runtime
spec:
annotations:
prometheus.kserve.io/path: /metrics
prometheus.kserve.io/port: "8080"
supportedModelFormats:
- name: huggingface
version: "1"
autoSelect: true
protocolVersions: [v2]
containers:
- name: kserve-container
image: vllm/vllm-openai:v0.9.0
args:
- --model=/mnt/models
- --port=8080
- --served-model-name={{.Name}}
- --tensor-parallel-size=2
- --max-model-len=32768
- --enable-prefix-caching
resources:
limits:
nvidia.com/gpu: "2"
memory: 64Gi
requests:
nvidia.com/gpu: "2"
memory: 32Gi
ports:
- containerPort: 8080
protocol: TCP再定义 InferenceService:
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: qwen3-32b
annotations:
serving.kserve.io/autoscalerClass: keda
spec:
predictor:
minReplicas: 2
maxReplicas: 16
model:
modelFormat:
name: huggingface
runtime: kserve-vllm-runtime
storageUri: s3://my-bucket/models/qwen3-32b/
resources:
limits:
nvidia.com/gpu: "2"
nodeSelector:
nvidia.com/gpu.product: NVIDIA-H100-80GB-HBM3验证:
kubectl apply -f qwen3-32b.yaml
kubectl get isvc qwen3-32b
# 等待 READY=True 后:
ENDPOINT=$(kubectl get isvc qwen3-32b -o jsonpath='{.status.url}')
curl -H 'Content-Type: application/json' \
-d '{"model":"qwen3-32b","messages":[{"role":"user","content":"hello"}]}' \
$ENDPOINT/v1/chat/completions13.2 Ray Serve 多模型 Composition
一个同时挂 Qwen3(主 LLM)、bge-m3(embedding)和一个路由器的 deployment:
import ray
from ray import serve
from fastapi import FastAPI
from pydantic import BaseModel
from vllm import LLM, SamplingParams
from sentence_transformers import SentenceTransformer
app = FastAPI()
class Query(BaseModel):
text: str
mode: str = "auto" # auto | llm | embed
@serve.deployment(
ray_actor_options={"num_gpus": 2},
autoscaling_config={"min_replicas": 1, "max_replicas": 8, "target_ongoing_requests": 4},
)
class Qwen3LLM:
def __init__(self):
self.llm = LLM(model="Qwen/Qwen3-8B", tensor_parallel_size=2, gpu_memory_utilization=0.9)
self.params = SamplingParams(max_tokens=512, temperature=0.2)
async def __call__(self, prompt: str) -> str:
outs = self.llm.generate([prompt], self.params)
return outs[0].outputs[0].text
@serve.deployment(ray_actor_options={"num_gpus": 0.5})
class BgeEmbedding:
def __init__(self):
self.model = SentenceTransformer("BAAI/bge-m3", device="cuda")
async def __call__(self, text: str):
return self.model.encode(text, normalize_embeddings=True).tolist()
@serve.deployment
@serve.ingress(app)
class Router:
def __init__(self, llm, embed):
self.llm = llm
self.embed = embed
@app.post("/infer")
async def infer(self, q: Query):
if q.mode == "embed" or (q.mode == "auto" and len(q.text) < 64):
vec = await self.embed.remote(q.text)
return {"type": "embedding", "vector": vec[:8], "dim": len(vec)}
text = await self.llm.remote(q.text)
return {"type": "text", "answer": text}
llm_handle = Qwen3LLM.bind()
embed_handle = BgeEmbedding.bind()
app_handle = Router.bind(llm_handle, embed_handle)
# ray start --head
# serve run serving:app_handle启动:
ray start --head --num-gpus=3
serve run serving:app_handle
curl -X POST http://localhost:8000/infer -H 'Content-Type: application/json' \
-d '{"text":"解释一下 KV cache","mode":"auto"}'关键点:LLM 是 num_gpus=2(TP=2),embedding
用 num_gpus=0.5(共享半张卡),Ray Serve
自动帮你把两者放到合适的节点,Router 负责路由。
13.3 vLLM 启动带 LoRA 多租户 + KV 外存
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen3-32B \
--tensor-parallel-size 2 \
--enable-prefix-caching \
--enable-lora --max-loras 32 --max-lora-rank 64 \
--lora-modules finance=/models/loras/finance legal=/models/loras/legal \
--kv-transfer-config '{"kv_connector":"LMCacheConnector","kv_role":"kv_both"}' \
--max-model-len 32768 \
--gpu-memory-utilization 0.913.4 SGLang Router:prefix-aware 路由
SGLang 提供的 Router 组件可以做 cache-aware routing,按 prompt prefix 命中哪个副本有 KV 来分发:
# 启动 3 个 SGLang worker
for port in 30000 30001 30002; do
python -m sglang.launch_server --model Qwen/Qwen3-8B --port $port &
done
# 启动 Router(同机或独立)
python -m sglang_router.launch_router \
--worker-urls http://localhost:30000 http://localhost:30001 http://localhost:30002 \
--policy cache_aware \
--cache-threshold 0.5 \
--balance-abs-threshold 32 \
--port 8000
# 请求打到 8000,Router 决定具体发哪个 worker
curl -X POST http://localhost:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"qwen3","messages":[{"role":"user","content":"hello"}]}'相比一致性哈希,cache_aware 在 RAG / agent 场景命中率能高出 15–40 个百分点。
13.5 基准测试
上线前必做容量评估。推荐工具链:
vllm bench serve/benchmark_serving.py:官方脚本,支持 ShareGPT、LongBench、合成 trace。genai-perf(NVIDIA):Triton 体系的标准压测工具,也能压任何 OpenAI 兼容 API。llmperf(Anyscale 维护):多 tenant / 多并发场景的方便封装。k6+ OpenAI plugin:写自定义业务 trace 的首选。
关键指标至少采集:TTFT p50/p99、ITL(每 token 间隔)p50/p99、吞吐(tokens/s)、GPU 利用率、HBM 利用率、prefix cache 命中率、排队时长。
python benchmarks/benchmark_serving.py \
--backend vllm \
--model Qwen/Qwen3-32B \
--dataset-name sharegpt \
--dataset-path ShareGPT_V3.json \
--num-prompts 2000 \
--request-rate 40 \
--host localhost --port 8000 \
--save-result --result-filename qwen3-32b.json输出的 p99 TTFT、p99 TPOT(time
per output token)、mean_throughput 就是你给
SRE / 业务方承诺 SLO 的依据。
十四、整体架构 SVG
十五、GPU 共享与小模型共存
LLM serving 不都是 72B 巨兽。一个典型平台还要跑:embedding(300M–2B)、rerank(500M)、safety classifier(100M)、ASR/TTS。如果每个都独占一张卡,钱包会爆。
15.1 MPS(Multi-Process Service)
Nvidia MPS 允许多个进程共享一块 GPU 的
SM,比默认的时分复用(context switch)开销更低。K8s 里通过
nvidia.com/gpu.shared = true 或 HAMi /
TimeSlicing Plugin 接入。适合:
- 低并发的 embedding 服务。
- Batch 评估任务。
- 共享开发环境。
不适合:高 QPS LLM 主推理(干扰严重,p99 抖动大)。
15.2 MIG vs Time-Slicing vs MPS
| 特性 | MIG | Time-Slicing | MPS |
|---|---|---|---|
| 隔离 | 硬件级 HBM / SM | 无(时分) | SM 共享,显存共享 |
| 卡支持 | A100/H100 | 所有 | 所有 |
| 性能干扰 | 无 | 有 | 有(低) |
| 适合 | 多租户、小模型 | 开发环境 | 低并发推理 |
15.3 HAMi / vGPU
国内常用 HAMi(由第四范式等维护,原 4paradigm/k8s-vgpu-scheduler),可以把一张卡按 显存 + 算力百分比 切给多个 Pod。它是 MPS 之上的调度层,对昇腾、寒武纪也有适配。
十六、上线前 checklist
十七、常见问答(FAQ)
Q1:我刚起步,只有 2–4 张 GPU,还需要上 KServe / Ray Serve 吗?
不需要。直接 vllm serve + systemd / Docker
Compose + 前面一个 nginx 足够撑很久。等团队有 ≥ 10
副本、需要 GitOps、多租户、金丝雀时再迁移。
Q2:Ray Serve 和 KServe 如何选?
- 算法驱动、Python 复杂 DAG、已有 Ray 训练集群 → Ray Serve。
- SRE 驱动、K8s 原生、已有 Istio/Prometheus 栈 → KServe。
- 两者可以混用:KServe 起 LLM,Ray Serve 起 RAG orchestrator。
Q3:prefix caching 和 LMCache 有什么区别?
vLLM 的 --enable-prefix-caching
是副本内的 HBM 级 KV 复用;LMCache
是跨副本 / 分层(HBM → DRAM → NVMe →
对象存储)的 KV
复用。前者零成本开启,后者需要额外网络和存储。
Q4:Triton 和 vLLM OpenAI Server 能共存吗?
可以,且常见。Triton 跑 CV / ASR / TTS / embedding(强 batching),vLLM 跑 LLM。前面用同一个网关屏蔽差异。
Q5:多租户 LoRA 有性能损耗吗?
有。吞吐下降大约 5–15%(依 adapter 数、rank、SGMV kernel 优化程度),但比起每个 LoRA 起一副基座副本节省 10–100 倍显存,性价比极高。
Q6:我能在昇腾 910B 上跑 KServe 吗?
可以。用华为的 MindIE Service 镜像作为 ServingRuntime
即可。注意 device plugin 要换成
ascend-device-plugin,资源名是
huawei.com/Ascend910。
Q7:为什么 GPU 利用率看起来不高但延迟已经爆了?
DCGM 报告的 GPU_UTIL 只看”SM
是否在活动”,不代表算力打满。LLM decode 阶段是访存 bound,SM
大多时候在等 HBM,GPU_UTIL 可能长期
40–60%,但HBM
带宽利用(DCGM_FI_PROF_DRAM_ACTIVE)已经
90%+。排查时同时看算力利用、带宽利用、NCCL
通信时长、vllm:kv_cache_usage_perc、vllm:num_requests_waiting。
Q8:vLLM 升级版本要怎么做?
强烈建议”镜像 + 权重 + 配置”一起锁版本,按 KServe / K8s 标准 RollingUpdate 做滚动。新版本先用 1 副本承接 1% 流量,跑 30 分钟没 error rate / p99 异常再放量。不要在高峰期升级,vLLM 偶尔有 kernel 兼容性回退(如 FlashAttention 版本)。
Q9:如何阻止单个租户把整个集群打爆?
网关层(下一篇)做 QPS / token/s /
并发三维限流;服务层可按 tenant 在 vLLM 启动参数里给
--max-num-seqs
限制,或者干脆给大客户独占副本。
Q10:推理服务的 SLI / SLO 怎么定?
给出一组经验值,作为起点而非教条:
- Availability:99.9%(月度),核心主链路 99.95%。
- TTFT p99:Chat ≤ 2s,RAG ≤ 4s,长文档 ≤ 8s。
- ITL p99:≤ 80 ms(用户视觉上的”流畅”阈值 ≈ 12 token/s)。
- Error rate:< 0.1%(区分用户错误 4xx 与服务错误 5xx)。
- Cost per 1M tokens:按模型分档,定期复盘。
SLO 要和网关、业务双向对齐:业务提诉求 → 服务层给出可行性 → 网关兜底降级路径。
十八、小结
推理服务化的本质,是把 11–16 篇“引擎”变成”云”。你在单机上关心的 paged KV、continuous batching、speculative decoding,到了集群里就变成了自动扩缩、session 路由、PD 分离、多租户 LoRA、跨 region 灾备。引擎是发动机,服务层是底盘。
这一层有三条重要趋势:
- KServe + vLLM 成为开源事实默认,国内私有化部署八成以上是这个组合。
- PD 分离从论文走向主流,Mooncake 之后,vLLM / SGLang / 各家自研都在做;下一步是 MoE expert 分离。
- Serverless GPU 商业化成熟,长尾模型、尖峰流量、batch 任务会越来越多地跑在 Modal / RunPod / 火山方舟这类托管上。
- KV cache 成为一等公民:从副本内到跨副本、从 HBM 到冷存,KV 管理正在独立演化出类似”缓存 / 存储”子产品形态(Mooncake Store、LMCache、NIXL)。
- 异构硬件混部:同一集群里 H100 / H20 / 昇腾 / MI300 各司其职,上层用统一 API 屏蔽;这对服务层的路由和拓扑感知提出更高要求。
下一篇我们抬高一层,看大模型网关:鉴权、配额、路由、审计、合规、成本——所有和”谁在用、用多少、合不合规”相关的事都在那里。
十九、延伸阅读线索
- vLLM production-stack:vLLM 社区维护的生产参考实现,含 Router、Autoscaler、LMCache 集成,Helm Chart 开箱。
- Nvidia Dynamo:2025 年 Nvidia 开源的推理编排框架,定位是”Triton 的下一代”,原生支持 PD 分离、NIXL、多引擎。
- Mooncake 开源仓库:KV Store 实现、跨节点 RDMA 传输、KV-aware 调度都能读到源码。
- Ray Serve
LLM:
ray.serve.llm(Ray 2.40+)原生 LLM 抽象,比自己写 deployment 更方便。 - KServe v0.14+:对 LLM、Hugging Face 模型的一等公民支持,持续迭代。
这些都是本文没法展开但强烈建议读的”下一步”。
参考资料
- NVIDIA Triton Inference Server 文档 — https://github.com/triton-inference-server/server
- Ray Serve 官方文档 — https://docs.ray.io/en/latest/serve/
- KServe 官方文档 — https://kserve.github.io/website/
- KEDA 官方文档 — https://keda.sh/
- Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving(Moonshot AI, 2024)
- DistServe: Disaggregating Prefill and Decoding for Goodput-Optimized LLM Serving(OSDI 2024)
- Splitwise: Efficient Generative LLM Inference Using Phase Splitting(Microsoft, ISCA 2024)
- S-LoRA: Serving Thousands of Concurrent LoRA Adapters(UCB, 2023)
- Punica: Multi-Tenant LoRA Serving(CMU, 2023)
- vLLM Production Stack — https://github.com/vllm-project/production-stack
- LMCache — https://github.com/LMCache/LMCache
- BentoML / OpenLLM — https://github.com/bentoml/OpenLLM
- 阿里云 PAI-EAS / 火山 veMLP / 华为 MindIE 官方文档
- Volcano / Koordinator / Kueue K8s 调度器文档
- Modal / RunPod / Replicate / Fly Machines 产品文档
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【大模型基础设施工程】03:CUDA 生态——cuBLAS、cuDNN、NCCL、Triton、CUTLASS
从 nvcc 到 Triton,把 NVIDIA 软件栈的每一层拆给大模型工程师看,顺便谈谈 ROCm、CANN 为什么一直追不上。
【大模型基础设施工程】01:大模型基础设施全景 —— 训练、推理、RAG、Agent、观测
面向工程师的大模型基础设施开篇地图,覆盖 2022 到 2026 的工程分水岭、五层工程栈、训练与推理的工程差异、中国与全球行业版图以及成本曲线。
【大模型基础设施工程】02:GPU 计算入门——SM、Tensor Core、HBM、NVLink
从 CPU 与 GPU 的架构差异出发,讲清楚 SM、Warp、Tensor Core、HBM、NVLink 的工程含义,并结合 Roofline、FlashAttention 与国产算力栈,给出大模型工程师能直接上手的 GPU 心智模型。
【大模型基础设施工程】04:互联与网络——NVLink、InfiniBand、RoCE 与国产替代
从 NVLink / NVSwitch / NVL72 到 InfiniBand NDR 与 RoCEv2,再到华为 CloudMatrix、阿里 HPN、腾讯星脉,系统梳理万卡集群互联的工程选型与踩坑。