土法炼钢兴趣小组的算法知识备份

【大模型基础设施工程】21:推理服务化

文章导航

分类入口
architectureai-infra
标签入口
#llm#infra#serving#triton#ray-serve#kserve#bentoml#lora#mooncake#pd-disaggregation#serverless-gpu

目录

前两篇讲了 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。生产化至少要回答下面这些问题:

  1. 多模型共存:Qwen3-72B、DeepSeek-V3、Qwen3-Embedding、bge-reranker-v2 要不要共享 GPU?如何调度?
  2. 多租户隔离:A 团队一次灌 10k QPS,不能打垮 B 团队的线上服务。
  3. 弹性伸缩:工作日白天 120 副本,凌晨 12 副本。扩容要几分钟?权重 140 GB 怎么拉?
  4. 流量路由:长上下文请求 ≥ 32k token 走专用池;短请求(< 2k)走共享池;带 prefix cache 的要做 session affinity。
  5. 金丝雀 / 灰度:新微调版本上线先切 1% → 5% → 100%,发现 KV cache 命中率掉了要一键回滚。
  6. 模型热切换:不停机加载/卸载 LoRA adapter、不停机切主模型版本。
  7. 可观测:每个请求的 TTFT、ITL、token/s、队列长度、GPU SM 利用率、HBM 占用、NCCL 带宽都要能查到。
  8. 灾备:一个可用区挂了,业务要能在 60s 内切到另一个可用区。权重要提前同步。
  9. 冷启动:从 Pod 调度 → 拉镜像 → 下载权重 → 加载到 HBM → warmup 首包,通常 5–15 分钟。
  10. 成本追踪:按 tenant 计 token 成本,按模型 / 按业务线分摊 GPU 账单。
  11. 协议兼容:OpenAI Chat Completions API 几乎是事实标准,Anthropic Messages、Gemini generateContent、国产厂商自有 API 都要能接。
  12. 合规与安全:输入 PII 脱敏、输出内容审核、审计日志保留期。

前面 111213 篇关心的是”单 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 年末我们团队亲历的事故(细节脱敏):

教训:推理服务的稳定性,80% 来自路由和拓扑的正确性,20% 才是引擎参数

二、服务层工具选型

2.1 Nvidia Triton Inference Server

Triton 是老牌推理服务框架,设计目标是”模型无关”,支持 TensorRT、TensorRT-LLM、vLLM、PyTorch、ONNX、Python、FIL 等多个 backend。它的几个杀手级特性:

LLM 场景下,Triton 主要作为 TensorRT-LLM 的官方 servertensorrtllm_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(任务 / 集群)深度集成。适合:

缺点:对 K8s 原生语义不够好(Ray 自带集群管理),跨语言支持弱,对 SRE 团队”Ray 集群”本身是新的运维对象。

2.3 KServe(K8s CRD 标准)

KServe 脱胎于 KubeFlow 的 KFServing,目标是在 K8s 上用标准 CRD 描述推理服务。核心资源:

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 开发者友好”:用装饰器把推理函数包成 Servicebentoml 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 类似。

什么时候它不够用?

满足这些时就要上 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 慢一个数量级)。

经验公式:

3.2 多机:TP × PP

跨节点时:

典型拓扑: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 拓扑无感知。你需要:

四、自动扩缩容

4.1 指标驱动:KEDA

HPA 默认只能基于 CPU / Memory,不够。KEDA(Kubernetes Event-Driven Autoscaler) 支持 40+ 种 scaler:Prometheus、Kafka、Redis、SQS 等。LLM 场景常用:

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 适合:

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    → 保留

优化手段:

五、模型热加载与多租户 LoRA

5.1 为什么 LoRA 多租户重要

第 19、20 篇讨论了业务层面经常需要”一个基座模型 + 几十到几千个小微调”的模式:某客服场景、某风控场景、某领域术语各一份 LoRA(几十 MB 到几百 MB)。如果为每个 LoRA 起一副 72B 副本,成本爆炸。

解决方案:共享基座 + 动态加载 LoRA adapter

5.2 S-LoRA / Punica / vLLM LoRA

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-v2

5.3 LMCache:跨请求 KV 复用

LMCache 把 KV cache 外置到 CPU 内存 / NVMe / 对象存储,让相同 prefix 在不同副本间也能复用。典型用途:

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 主流方案

6.3 PD 分离架构 SVG

PD 分离架构 SVG

6.4 何时上 PD 分离

不要过早上。判据:

小规模集群,老老实实用 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,要跨节点搬数据。几种典型通道:

七、流量路由

7.1 Session affinity(prefix cache 友好)

前面讲了 KV cache 复用:同一用户同一会话的多轮对话要尽量命中同一副本,否则 prefix cache 失效,每轮都要重算 system prompt + 历史。

做法:

7.2 长短请求分流

混部长请求(输入 32k+、输出 4k+)和短请求(输入 500、输出 100)会严重拖慢短请求的 p99。分流策略:

7.3 成本 / 延迟 SLO 路由

多模型场景下,可以做 model cascade

  1. 先走 4B 小模型。
  2. 置信度低 / 用户明确选了 “deep mode” 再走 72B。
  3. 最终兜底走顶级模型(DeepSeek-V3、GPT-5)。

这本质是网关层的事(下一篇讲),但服务层要提供不同模型的同构 API 和一致的 metric 口径。

八、模型仓库

权重从哪里来?

最佳实践:私仓 + 哈希校验 + 不可变版本。不要依赖”latest”,上游偶尔会覆盖。

九、K8s 上的 GPU

9.1 GPU 接入

9.2 MIG(Multi-Instance GPU)

A100 / H100 支持把一张卡切成 7 份(1g.10gb、2g.20gb、3g.40gb、7g.80gb)。适合:

不适合:LLM 推理(fragmentation,MIG 之间不能 NVLink)。

9.3 拓扑感知调度

9.4 网络

9.5 KubeFlow / Volcano / Arena

十、Serverless GPU

10.1 商业方案

10.2 适用场景

不适用:核心在线主链路(冷启动风险)、超大模型(权重分发成本)。

十一、国产云厂商托管推理服务

11.1 阿里云 PAI-EAS(Elastic Algorithm Service)

阿里 PAI 平台的推理服务产品。特点:

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 国际对照

十二、灾备与多活

LLM 推理的 DR(Disaster Recovery)有两大难点:权重大 + GPU 稀缺

12.1 跨 region 副本

12.2 降级模型

当主模型(例如 405B)某 region 完全不可用:

  1. 切到同 region 的 降级模型(70B、32B 的 Qwen3、Llama 同能力档)。
  2. 或切到 备 region 主模型(可能延迟增加 50–150 ms)。
  3. 最差情况走 外部 API(Bedrock / 方舟),成本提高但保可用。

这需要网关层能做:SLA 检测 → 自动切流 → 回切,且对客户端保持 API 兼容。

12.3 故障演练

十三、代码示例

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/completions

13.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.9

13.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 基准测试

上线前必做容量评估。推荐工具链:

关键指标至少采集: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 TTFTp99 TPOT(time per output token)、mean_throughput 就是你给 SRE / 业务方承诺 SLO 的依据。

十四、整体架构 SVG

整体架构 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 接入。适合:

不适合:高 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 如何选?

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_percvllm: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 怎么定?

给出一组经验值,作为起点而非教条:

SLO 要和网关、业务双向对齐:业务提诉求 → 服务层给出可行性 → 网关兜底降级路径。

十八、小结

推理服务化的本质,是把 11–16 篇“引擎”变成”云”。你在单机上关心的 paged KV、continuous batching、speculative decoding,到了集群里就变成了自动扩缩、session 路由、PD 分离、多租户 LoRA、跨 region 灾备。引擎是发动机,服务层是底盘。

这一层有三条重要趋势:

  1. KServe + vLLM 成为开源事实默认,国内私有化部署八成以上是这个组合。
  2. PD 分离从论文走向主流,Mooncake 之后,vLLM / SGLang / 各家自研都在做;下一步是 MoE expert 分离。
  3. Serverless GPU 商业化成熟,长尾模型、尖峰流量、batch 任务会越来越多地跑在 Modal / RunPod / 火山方舟这类托管上。
  4. KV cache 成为一等公民:从副本内到跨副本、从 HBM 到冷存,KV 管理正在独立演化出类似”缓存 / 存储”子产品形态(Mooncake Store、LMCache、NIXL)。
  5. 异构硬件混部:同一集群里 H100 / H20 / 昇腾 / MI300 各司其职,上层用统一 API 屏蔽;这对服务层的路由和拓扑感知提出更高要求。

下一篇我们抬高一层,看大模型网关:鉴权、配额、路由、审计、合规、成本——所有和”谁在用、用多少、合不合规”相关的事都在那里。


上一篇工具调用与 MCP 下一篇大模型网关

十九、延伸阅读线索

这些都是本文没法展开但强烈建议读的”下一步”。

参考资料

  1. NVIDIA Triton Inference Server 文档 — https://github.com/triton-inference-server/server
  2. Ray Serve 官方文档 — https://docs.ray.io/en/latest/serve/
  3. KServe 官方文档 — https://kserve.github.io/website/
  4. KEDA 官方文档 — https://keda.sh/
  5. Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving(Moonshot AI, 2024)
  6. DistServe: Disaggregating Prefill and Decoding for Goodput-Optimized LLM Serving(OSDI 2024)
  7. Splitwise: Efficient Generative LLM Inference Using Phase Splitting(Microsoft, ISCA 2024)
  8. S-LoRA: Serving Thousands of Concurrent LoRA Adapters(UCB, 2023)
  9. Punica: Multi-Tenant LoRA Serving(CMU, 2023)
  10. vLLM Production Stack — https://github.com/vllm-project/production-stack
  11. LMCache — https://github.com/LMCache/LMCache
  12. BentoML / OpenLLM — https://github.com/bentoml/OpenLLM
  13. 阿里云 PAI-EAS / 火山 veMLP / 华为 MindIE 官方文档
  14. Volcano / Koordinator / Kueue K8s 调度器文档
  15. Modal / RunPod / Replicate / Fly Machines 产品文档

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。


By .