llm-d项目详解:Kubernetes上的分布式LLM推理栈
本文最后更新于 2026年6月5日 下午
1. 先说结论
版本说明:本文写于 2026-06-05,主要参考 llm-d 官方仓库 v0.7.0 release 和 v0.7.0 tag 文档。v0.7.0 在 GitHub 上的发布时间是 2026-05-12;我本地阅读的 tag 对应提交是 a47c3bd4e296c54b25f957f314317c974ad4ebbb,提交时间是 2026-05-12 14:40:21 -0400。llm-d 发展很快,尤其是 Router/EPP、KV offload、P/D disaggregation 和 batch gateway 这些模块,生产使用时要以实际安装的 chart、镜像、CRD 版本为准。
一句话概括:
llm-d 不是另一个推理引擎,而是一个运行在 Kubernetes 上、面向生产 LLM serving 的分布式调度和编排层。它把 vLLM/SGLang 这样的 model server、Gateway API Inference Extension、智能路由、KV cache 管理、P/D 分离、流控、扩缩容和批处理组合成一套可部署的推理栈。
更具体地说:
- vLLM 负责单个或一组 GPU 上的模型执行、continuous batching、PagedAttention、prefix cache、KV connector。
- Kubernetes 负责 Pod、Service、资源调度、弹性伸缩、Gateway/API 生态。
- llm-d 在两者之间补上生产推理最缺的一层:请求应该去哪个推理实例、什么时候进去、是否要分成 prefill/decode 两段、如何复用跨请求 KV cache、什么时候扩容、如何保护交互请求不被 batch 请求拖垮。
- llm-d 的核心入口叫 llm-d Router。Router 由两部分组成:Proxy 和 Endpoint Picker,也就是 EPP。
- Proxy 是数据面,通常是 Envoy、Istio、agentgateway 或云厂商兼容 Gateway 的 L7 代理。
- EPP 是决策面,通过
ext-proc协议被 Proxy 调用;它解析请求、做流控、维护端点状态、跑 Filter → Score → Pick 插件链,最后返回应该转发到哪个 model server Pod。 InferencePool是 Kubernetes CRD,作用类似“LLM 优化版 Service”:它定义同一个模型/配置下有哪些 model server Pod 可供 EPP 选择,以及 Gateway 如何连到 EPP。- llm-d 最有价值的能力不是“把 vLLM 部署起来”,而是 把 scale-out 后才出现的问题系统化解决:prefix cache 命中率、长 prompt 和 decode 互相干扰、KV cache 工作集超过 HBM、请求成本差异巨大、多租户公平、SLO-aware routing、异构硬件扩缩容。
- v0.7.0 release 里,项目默认部署体验改成 standalone mode,也就是 Router 自带通用 proxy;生产环境仍然更推荐完整 Gateway 方案。
- v0.7.0 的组件版本并不全等于
0.7.0:例如 release 表里vllm-project/vllmwheel 是v0.19.1,llm-d-inference-scheduler镜像是v0.8.0,llm-d-kv-cache库是v0.8.0。不要把项目 release 号当作所有组件的语义版本。 - v0.7.0 还把 llm-d CUDA 镜像升级到 CUDA 13.0.2;如果使用这些 CUDA 镜像,宿主机需要 NVIDIA driver 580 或更新版本。
先放一张总图:
flowchart LR
C[Client / SDK] --> P[Proxy<br/>Envoy / Istio / agentgateway / cloud LB]
P <-->|ext-proc| E[EPP<br/>Endpoint Picker]
E --> IP[InferencePool<br/>pod discovery]
IP --> M0[vLLM Pod A]
IP --> M1[vLLM Pod B]
IP --> M2[vLLM Pod C]
M0 -.metrics / KVEvents.-> E
M1 -.metrics / KVEvents.-> E
M2 -.metrics / KVEvents.-> E
E -.consult.-> LP[Latency Predictor]
E -.consult.-> KI[KV Indexer]
KI -.block location.-> E
M0 -.offload.-> CPU[CPU RAM / FS / external KV engine]
M1 -.offload.-> CPU
如果只记一个心智模型,可以这样理解:
vLLM / SGLang: 怎么在一个推理实例里高效算模型
Kubernetes: 怎么调度和管理容器、网络、资源
llm-d: 怎么让一组推理实例像一个高性能、可控、可扩展的LLM服务2. llm-d为什么存在
单机 vLLM 很强,但生产 LLM 服务的问题通常不是“某一个 Pod 能不能跑模型”,而是这些问题:
- 同一个模型有 10 个副本,请求应该发给哪个?
- 多轮对话会反复带上同一个系统 prompt 和历史上下文,怎么让后续请求打到已有 prefix cache 的副本?
- 一个 100 token prompt 和一个 100k token prompt 都是一个 HTTP request,普通 round-robin 完全看不出成本差异。
- prefill 是大矩阵计算,decode 更偏显存带宽和 KV 读取;长 prefill 会影响正在 decode 的请求,怎么隔离?
- GPU HBM 不够保存所有 KV cache,能不能把冷 KV 下沉到 CPU RAM 或共享存储?
- batch/offline 请求吞吐优先,chat/agent 请求延迟优先,两类流量共用集群时怎么做公平和保护?
- Kubernetes HPA 只看 CPU/GPU 利用率或普通 QPS 时太迟钝,能不能用 queue depth、running request、KV cache pressure、SLO 这类推理信号扩缩容?
- DeepSeek-R1 这类 MoE 大模型要跨节点 expert parallel,网络、拓扑、P/D 分离和 KV 传输怎么编排?
llm-d 的目标就是把这些生产问题变成可配置、可组合、可观测的架构模块。
这也是为什么它的官方 README 把能力分成几类:
- Intelligent Routing:prefix-cache-aware、load-aware、predicted-latency routing。
- Advanced KV-Cache Management:KV index、KV offload、tiered prefix cache。
- Serving Large Models:P/D disaggregation、wide expert parallelism。
- Operational Excellence:flow control、SLO-aware autoscaling。
- Batch Processing:OpenAI-compatible batch API 和 async processing。
注意这里的关键词是 above model servers。llm-d 不替代 vLLM,而是把 vLLM 这类引擎变成集群级服务。
3. 核心架构:Router、InferencePool、Model Server
llm-d 的 core architecture 主要围绕三个概念:
- llm-d Router
- InferencePool
- Model Server
3.1 llm-d Router
Router 是推理请求的智能入口。它不是一个单体组件,而是由 Proxy 和 EPP 组成:
flowchart LR
Client --> Proxy
Proxy <-->|ext-proc callback| EPP
EPP --> Scheduler[Request Scheduler<br/>Filter / Score / Pick]
EPP --> Flow[Flow Control]
EPP --> Data[Data Layer]
Data --> Pods[Pod / metrics / prefix tree / consultants]
Proxy --> Backend[vLLM / SGLang Pod]
Proxy 做网络数据面的事:
- 接收 HTTP/gRPC 请求。
- TLS、连接管理、HTTPRoute/Gateway 接入。
- 在请求转发前调用 EPP。
- 根据 EPP 返回的端点,把原始请求转发给某个 model server Pod。
EPP 做 LLM-aware 决策:
- 解析 OpenAI HTTP、vLLM gRPC 或自定义协议请求。
- 根据 priority、fairness、saturation 做流控。
- 从 InferencePool 里拿候选 Pod。
- 读取 Pod metrics,例如 queue depth、running requests、KV cache utilization。
- 读取 prefix cache 状态或 KV index。
- 可选调用 latency predictor、KV indexer、tokenizer 这类 consultant sidecar。
- 运行 Filter → Score → Pick 插件链。
- 返回选中的 Pod 地址。
老文档或 release 表里有时还会出现 llm-d-inference-scheduler 这个名字。v0.7 文档明确把术语收敛为:
- llm-d Router:完整入口,包括 Proxy + EPP。
- llm-d Endpoint Picker (EPP):真正做路由智能的组件。
- Request Scheduler:EPP 内部做候选端点过滤、打分、选择的子模块。
3.2 InferencePool
InferencePool 是 Gateway API Inference Extension 里的 CRD。可以把它理解成 “Service + LLM routing metadata”。
它有两个角色:
- 对 EPP:告诉 EPP 怎么发现可选的 model server Pod。
- 对 Gateway controller:告诉 Gateway/Proxy 这个 pool 对应的 EPP 服务在哪里,怎么通过
ext-proc调它。
一个简化的关系是:
HTTPRoute backendRef -> InferencePool
InferencePool selector -> model server Pods
InferencePool endpointPickerRef -> EPP Service
Proxy ext-proc -> EPP
EPP selected endpoint -> concrete Pod IP:portInferencePool 典型做法是用 label selector 选择同一个 namespace 下的 model server Pods。Pod 扩容、缩容、ready 状态变化时,EPP 通过 Kubernetes watch 动态更新候选列表。
这一层很关键,因为 LLM 推理的“负载均衡单位”不再只是 Service 后面的一组 endpoints,而是带有模型、角色、cache、队列、KV 状态的 endpoints。
3.3 Model Server
Model Server 是真正执行模型的引擎。llm-d 默认重点集成 vLLM,也提到 SGLang 等后端。
llm-d 不想重写这些能力:
- GPU/TPU/HPU 上的模型执行。
- PagedAttention。
- continuous batching。
- prefix caching。
- KV cache connector。
- tensor parallel、expert parallel、pipeline/distributed executor。
- OpenAI-compatible API。
llm-d 要的是 model server 对外暴露足够的状态和控制点,让 Router 可以在集群层面做更好的决策。例如:
/metrics暴露 queue depth、running requests、KV cache usage。- vLLM 发出 KVEvents,描述 block stored / removed / all cleared。
- vLLM 支持 KV transfer config,用 NIXL 做 P/D 间 KV 传输。
- vLLM 支持 OffloadingConnector,把 KV cache 下沉到 CPU 或共享存储。
4. 普通请求路径:EPP到底怎么选Pod
在最常见的 aggregated serving 模式下,一个请求只会落到一个 model server Pod 上。请求路径大概是:
sequenceDiagram
participant Client
participant Proxy
participant EPP
participant Data as EPP Data Layer
participant Pod as vLLM Pod
Client->>Proxy: POST /v1/chat/completions
Proxy->>EPP: ext-proc: headers/body
EPP->>EPP: parse request
EPP->>EPP: flow control / admission
EPP->>Data: read endpoints, metrics, prefix state
EPP->>EPP: Filter -> Score -> Pick
EPP-->>Proxy: selected Pod IP:port
Proxy->>Pod: forward original request
Pod-->>Proxy: stream / response
Proxy-->>Client: stream / response
Pod-.->Data: metrics / KV events
EPP 内部的 Request Scheduler 是插件化的:
- Filter:先缩小候选集。例如只选 ready Pod、只选 decode role Pod、只选 prefix cache match 超过阈值的 Pod。
- Score:给候选 Pod 打分。例如 prefix match 高分、queue depth 低高分、KV cache utilization 低高分、预测 TTFT 更低高分。
- Pick:从分数里选最终 Pod。不是所有场景都适合 argmax,weighted random 可以避免所有请求瞬间堆到当前最高分 Pod。
最简单的 optimized baseline 通常组合两类信号:
- Prefix-aware scheduling:请求尽量去已有相同 prefix cache 的 Pod。
- Load-aware scheduling:同时考虑 queue depth、running requests、KV cache utilization,避免热点。
为什么不能只看 cache?
假设 Pod A 有 95% prefix 命中,但它已经排了很多长请求;Pod B 没有 cache,但非常空。对一个短 SLO 请求来说,Pod B 重算 prefill 可能仍然更快。这就是 llm-d 后面引入 predicted latency 的原因:静态权重很难同时兼顾 cache locality 和实时负载。
5. Prefix cache aware routing:llm-d最核心的收益点
LLM 服务和普通 HTTP 服务最大区别之一是:请求之间可能共享大量前缀。
例如 agent 系统里,很多请求都有同一个系统 prompt:
system prompt: 2000 tokens
tool specs: 3000 tokens
history: 1000 tokens
new question: 50 tokens如果第 2 轮、第 3 轮请求被 round-robin 发到不同 vLLM Pod,那么每个 Pod 都要重新 prefill 那几千个共享 token。scale-out 越多,cache 反而越分散。
llm-d 的 prefix-cache-aware routing 目标是:
不要把请求平均发到每个副本;
要把共享 prefix 的请求尽量发到已经保存该 prefix KV cache 的副本。v0.7 文档里有两种实现。
5.1 Approximate prefix cache routing
Approximate 实现比较轻量,不依赖 tokenizer sidecar,也不要求 model server 发 KVEvents。
大概流程:
- EPP 按字符/token 比例估算 token。
- 把 prompt 拆成固定大小 block。
- 用 rolling hash 建一个 prefix hash chain。
- EPP 本地维护一个 LRU:某个 prefix hash 最近被送到哪个 Pod。
- scorer 根据匹配 block 比例给 Pod 打分。
- 请求路由后,EPP 假设这个 Pod 未来会持有这个 prefix。
优点:
- 部署简单。
- 没有 ZMQ、tokenizer、KV indexer 依赖。
- 对简单同质 workload 已经能明显优于 round-robin。
缺点:
- 它看到的是“EPP 认为的 cache 状态”,不是 model server 真实状态。
- Pod 因 HBM 压力 evict 了 KV,EPP 可能不知道。
- 字符估算 token 对多语言、多模态、特殊 tokenizer、LoRA 等场景不够准。
5.2 Precise prefix cache routing
Precise 实现更像生产级全局 KV cache 索引。
组件包括:
- tokenizer / token producer:把请求精确 token 化。
- vLLM/SGLang KVEvents:model server 在 KV block 创建、删除、清空时发事件。
- KV-Cache Indexer:维护全局
block key -> pods / tiers映射。 - precise-prefix-cache-scorer:对候选 Pod 计算最长连续 prefix 命中长度。
这里有一个很重要的细节:KV block 必须是连续前缀才可复用。
假设请求 block 是:
[B0, B1, B2, B3, B4]三个 Pod 的 cache 状态:
Pod A: B0 B1 B2 B3 -- 命中4个连续block
Pod B: B0 B1 -- -- -- 命中2个连续block
Pod C: -- -- B2 B3 B4 命中0个可用prefixPod C 虽然有后面的 block,但没有 B0/B1。由于 causal attention 依赖前序状态,后面的 block 不能单独作为 prefix 命中使用,所以分数是 0。
KVEvents 通常包括三类:
BlockStored:某些 block 已经创建并位于某个设备层级。BlockRemoved:某些 block 被 evict。AllBlocksCleared:某个 Pod 清空所有 KV cache,例如权重 rollout 或重启。
事件传递有两种形态:
- Centralized:所有 model server publish 到 EPP 监听的 ZMQ endpoint。适合单 EPP。
- Pod discovery:每个 model server Pod bind 自己的 ZMQ socket,多个 EPP 副本分别订阅每个 Pod。适合 active-active EPP。
Indexer backend 也有几种:
- In-memory:默认,两级 LRU,延迟最低。
- Cost-aware memory:Ristretto,按字节预算,更适合 entry 大小变化明显的多模态/LoRA 场景。
- Redis / Valkey:外部存储,适合很长生命周期或持久索引,但多一次网络访问。
5.3 Speculative indexing解决什么问题
一个现实问题是:EPP 做出路由决策后,Pod 真正完成 prefill 并发出 BlockStored 事件需要一点时间。
如果两个相同 prefix 的请求几乎同时到来:
t0: request A -> EPP选择Pod 1
t1: request B到达
t2: Pod 1才发出BlockStored事件在 t1 时,KV indexer 还不知道 Pod 1 将持有这个 prefix。request B 可能被发到 Pod 2,导致重复 prefill。
Speculative indexing 的做法是:在路由决策之后,scorer 先在 index 里插入短 TTL 的预测项,表示“这个 Pod 很快会有这些 block”。如果后续 BlockStored 事件到达,预测被确认;如果没有到达,TTL 到期删除。v0.7 文档里的默认 TTL 是 2 秒。
6. KV offloading:把KV工作集扩到HBM之外
Prefix-aware routing 解决“请求该去哪里复用 cache”。KV offloading 解决“cache 能活多久、能放多大”。
GPU HBM 很贵也有限。多轮对话、agent workflow、长上下文请求会让 KV cache 工作集远大于单卡 HBM。如果没有 offloading,vLLM 只能按 LRU 把旧 KV evict 掉,后续请求再来就要重算 prefill。
llm-d 的 KV offloading 方向是把 KV block 下沉到更便宜的层级:
flowchart LR
HBM[GPU HBM<br/>fast / small] --> CPU[CPU DRAM<br/>slower / larger]
CPU --> FS[Shared FS / SSD<br/>larger / cross-node]
FS --> EXT[External KV Engine<br/>LMCache / Mooncake / KVBM]
v0.7 文档里主要讲两类 integration pattern。
6.1 vLLM native OffloadingConnector
Native path 走 vLLM 的 OffloadingConnector。
CPU offloading 可以用类似参数开启:
--kv-offloading-backend native --kv-offloading-size 100含义是给每个 vLLM instance 配一块 CPU RAM 缓冲区。被 GPU HBM evict 的 KV block 不直接丢掉,而是异步搬到 CPU RAM。后续请求命中时,从 CPU 拉回 GPU 通常比重新 prefill 快得多。
CPU offloading 的特点:
- 低复杂度,不需要外部存储服务。
- 每个节点/实例局部有效。
- 适合高频复用、短期冷却、preemption recovery。
- 前提是 CPU memory 资源要真正申请足够,否则 Kubernetes 调度和节点内存压力会出问题。
6.2 llm-d filesystem backend
Storage offloading 用 llmd_fs_backend 接到 vLLM OffloadingConnector。KV block 被存成文件,路径挂在共享文件系统上,例如 Lustre、CephFS、IBM Storage Scale、本地或网络 POSIX filesystem。
简化配置类似:
args:
- "--kv-transfer-config"
- |
{
"kv_connector": "OffloadingConnector",
"kv_role": "kv_both",
"kv_connector_extra_config": {
"spec_name": "SharedStorageOffloadingSpec",
"spec_module_path": "llmd_fs_backend.spec",
"shared_storage_path": "/mnt/kv-cache/",
"block_size": 256,
"threads_per_gpu": 64
}
}
volumeMounts:
- name: kv-cache
mountPath: /mnt/kv-cacheStorage offloading 的价值:
- cache 可以跨 Pod、跨节点共享。
- Pod 重启后 cache 不一定丢。
- 新扩容 Pod 可以读取已有共享 KV,减少冷启动后的 cache miss。
- 工作集上限从 HBM/CPU RAM 扩到共享存储容量。
代价也明显:
- 读路径需要等待存储 I/O。
- 对网络和文件系统吞吐/延迟非常敏感。
- block size 需要调。大 block I/O 更高效,但需要更长 prefix 才能命中。
- 文档明确提到 FS backend 不负责清理/eviction,存储容量管理需要底层系统或外部 controller。
6.3 out-of-tree KV engines
llm-d 也把 LMCache、Mooncake、NVIDIA KVBM 这类外部 KV cache engine 视为 connector pattern。
这类架构一般是:
vLLM/SGLang/TRT-LLM
-> KV connector API
-> third-party connector adapter
-> external KV engine
-> CPU / local disk / remote store它的优势是能力更灵活,能独立做索引、memory management、远程存储、controller、eviction。缺点是部署复杂度、版本兼容和排障成本都更高。
llm-d 在这里的统一点是:只要 connector 能通过 KVEvents 或等价机制把 cache mutation 暴露出来,EPP/KV indexer 就可以继续做 prefix-aware routing。
7. P/D disaggregation:把prefill和decode拆开
LLM 推理有两个阶段:
- Prefill:处理输入 prompt,算出历史 token 的 KV cache。通常更偏 FLOPs-bound。
- Decode:逐 token 生成输出,每步读取历史 KV。长上下文时更偏 memory bandwidth-bound。
Aggregated serving 里,一个 Pod 同时处理 prefill 和 decode。问题是长 prompt prefill 可能阻塞正在进行的 decode,导致交互请求的 ITL/TPOT 抖动。
P/D disaggregation 把两类工作拆到不同实例:
- Prefill worker:专门处理 prompt prefill。
- Decode worker:专门处理 decode。
- 两者之间通过 NIXL/RDMA 传 KV cache。
请求流大概是:
sequenceDiagram
participant Client
participant Proxy
participant EPP
participant Sidecar as Decode Pod Routing Sidecar
participant D as Decode Worker
participant P as Prefill Worker
Client->>Proxy: Request
Proxy->>EPP: ask for endpoints
EPP->>EPP: select D endpoint
EPP->>EPP: decide whether P/D is needed
EPP->>EPP: select P endpoint if needed
EPP-->>Proxy: D endpoint + optional P endpoint
Proxy->>Sidecar: forward request with P header
Sidecar->>P: prefill request, max_tokens=1
P-->>Sidecar: KVTransferParams
Sidecar->>D: decode request with KVTransferParams
D->>P: pull KV cache by NIXL / RDMA
P-->>P: release KV
D-->>Sidecar: decode response
Sidecar-->>Proxy: response
Proxy-->>Client: response
llm-d 里 P/D 不是写死一个策略,而是 EPP 的 disagg-profile-handler 组合两个 profile:
- decode-profile:先选 decode endpoint。
- decider:判断这个请求是否值得走 P/D。例如 decode Pod 上未缓存 suffix 很大时才拆。
- prefill-profile:如果需要 P/D,再选 prefill endpoint。
Pod 角色通过 label 区分:
llm-d.ai/role=prefill
llm-d.ai/role=decode
llm-d.ai/role=prefill-decodeP/D 的收益:
- 长 prefill 不再直接干扰 decode。
- prefill 和 decode 可以用不同 TP/DP/资源形态。
- 对 MoE DP/EP 部署尤其重要,可以减少 pipeline bubble,并让 decode 走更合适的算子格式。
P/D 的前提:
- 节点之间最好有 RDMA。官方文档明确说 NIXL 可以 fallback 到 TCP,但 TCP 主要适合测试和开发,不适合高性能生产。
- KV transfer 协议、model server 参数、sidecar、网络、安全策略都要配对。
- P/D 本身会引入一次或多次额外 RPC 和 KV transfer,短 prompt/短输出不一定划算。
8. Predicted latency scheduling:从启发式走向在线预测
只看 queue depth、running requests、KV utilization 这类指标有一个问题:它们是粗粒度负载,不直接等于这个请求的 TTFT/TPOT。
例如:
- 一个 10 token prompt 和一个 10k token prompt 都让 queue depth 加 1。
- prefix cache 命中率会随 traffic pattern 变化,静态权重很容易漂。
- TTFT 和 TPOT 的优化方向可能冲突。TTFT 偏向 cache locality,TPOT 偏向 spread load。
- 用户可能给每个请求不同 SLO,启发式 scorer 很难回答“这个 Pod 能不能在 300ms TTFT 内完成”。
llm-d 的 Latency Predictor 用在线训练的 XGBoost 模型预测候选 Pod 上的 TTFT 和 TPOT。
架构是:
flowchart LR
Req[Request] --> EPP
EPP --> Pred[Prediction Server]
EPP --> V[vLLM Pod]
V --> Obs[Observed latency]
Obs --> Train[Training Server]
Train --> Vol[Shared model volume]
Vol --> Pred
EPP 在热路径上对每个候选 endpoint 请求预测。预测输入包括:
- KV cache usage。
- input length。
- queue depth。
- running requests。
- prefix cache match。
- input tokens in flight。
- tokens generated。
预测失败时,EPP 会 fallback 到由 KV cache utilization、queue depth、prefix match 组成的启发式组合,而不是直接丢请求。
Latency Predictor 有几个限制要注意:
- 它假设同一个 pool 是 homogeneous 的,也就是 GPU 类型、模型权重、serving 配置一致。
- 异构硬件、混合模型变体、prefill/decode 混在一个 pool 里,会让模型把不同 regime 混为一谈,预测不准。
- 每个请求需要对候选 Pod 做预测,预测服务本身也要扩容。官方文档给出的参考是单个 prediction sidecar 在
c4-standard-192节点上大约支撑 300 QPS 的 prediction work;总预测量近似是cluster QPS × pod count。 - 如果要训练真正的 TTFT/TPOT,streaming mode 和非 streaming mode 要配对;混合 workload 需要谨慎。
预测调度里比较有意思的两个插件:
prefix-cache-affinity-filter:当某些 endpoint prefix match 超过阈值时,倾向保留 cache-warm endpoints;但如果 warm Pod 预测 TTFT 明显更差,可以打破亲和。slo-headroom-tier-filter/latency-scorer:根据SLO - predicted latency计算 headroom,选择刚好满足或最有余量的 endpoint。
这说明 llm-d 的 routing 方向不是简单“cache 优先”或“负载均衡优先”,而是根据请求特征和实时状态动态选择。
9. Flow control:不要让后端被请求淹没
普通负载均衡器通常会尽快把请求转给后端。但 LLM 请求很慢,后端一旦被塞爆,队列延迟会拖垮所有用户。
EPP 的 Flow Control 子系统负责 admission、queue、dispatch:
- SaturationDetector 判断 pool 是否饱和,例如基于 active in-flight requests、queue depth、KV cache utilization。
- 如果饱和,EPP 可以把请求先放在内存队列里,而不是继续打到 model server。
- Priority bands 区分实时交互和低优先级 batch。
- FairnessPolicy 防止一个租户或一个 flow 抢占所有 dispatch 机会。
- OrderingPolicy 决定同一个 flow 内部的顺序,例如 FIFO 或 SLO-based。
可以把它想成 LLM 推理入口的“压力阀”:
没有flow control:
client burst -> proxy -> model servers overloaded -> all requests tail latency explode
有flow control:
client burst -> EPP queue/admission -> controlled dispatch -> latency isolation/fairness这对多租户平台尤其重要。batch summarization、离线 embedding、interactive chat 如果直接共用同一组 GPU,低优先级长任务很容易把实时请求拖慢。
10. Autoscaling:用推理信号扩缩容
LLM serving 的扩缩容不能只看 CPU 或普通 QPS。一个低 QPS 长上下文 workload 可能比高 QPS 短请求更重;KV cache pressure 也会影响是否需要更多副本。
llm-d v0.7 文档里讲两个方向:
10.1 HPA/KEDA
HPA/KEDA 适合简单同质部署。它用 EPP 暴露的 demand-side metrics 扩缩容,例如:
- EPP queue depth。
- active request count。
优点:
- Kubernetes 原生,复杂度低。
- 单模型、同质硬件、每个模型独立扩容时够用。
缺点:
- 对 pending pods 不敏感。
- 对有限 GPU 资源只会先到先得。
- 很难保证强 latency SLO。
- 不能全局优化多个 model variant 的资源分配。
10.2 Workload Variant Autoscaler
WVA 是更复杂的全局优化器。它可以考虑:
- 不同模型。
- 不同硬件。
- 不同 serving topology。
- prefill/decode 角色。
- KV cache utilization。
- model server queue depth。
- SLO 目标。
- accelerator inventory 有限时的公平分配。
它的目标不是“每个 Deployment 自己 HPA”,而是在有限资源里决定:
该在哪些硬件上放哪些模型变体?
每个变体该放几个副本?
怎样满足更多SLO或降低成本?如果是单模型、同构 GPU、部署刚起步,HPA/KEDA 更现实。如果是 model-as-a-service、多硬件、多 quantization、多拓扑,WVA 才开始有价值。
11. Wide Expert Parallelism:大MoE模型的集群形态
DeepSeek-R1 这类 MoE 模型很难靠单节点解决。Wide Expert Parallelism 的思路是用 data parallel + expert parallel,把专家层跨多节点铺开。
llm-d 的 wide-ep guide 以 DeepSeek-R1-0528 为例,默认配置里 prefill data parallelism 是 16、decode data parallelism 是 16、总 GPU 是 32。文档提到验证过的环境包括:
- 32xH200 + InfiniBand。
- GKE 上 32xH200 + RoCE。
- GKE 上 32xB200 + RoCE。
关键依赖是网络。WideEP 里的 DeepEP backend 需要 All-to-All RDMA 连接。如果网络只允许同 rail NIC 通信而不是全互联,会失败。
这里 llm-d 的价值不是发明 EP,而是把这些东西组合进 Kubernetes 可部署路径:
- LeaderWorkerSet 管理多 Pod 组成的一个逻辑推理副本。
- Router/EPP 区分 prefill/decode role。
- P/D disaggregation 用 NIXL 做 KV transfer。
- Gateway/InferencePool 把多副本暴露成统一服务。
- benchmark template 和 monitoring 提供可复现实验路径。
这类部署对普通小模型过重,但对 DeepSeek-R1、GPT-OSS-120B 这类大模型推理是实际需求。
12. Batch Gateway和Async Processor
llm-d v0.7 也覆盖离线/batch 推理。
它有两个组件:
- Batch Gateway:提供 OpenAI-compatible Batch API,例如
/v1/batches、/v1/files,负责提交、追踪、管理 batch inference job。 - Async Processor:从 Redis、Google Pub/Sub 等队列拉取单个 inference request,再发给 llm-d Router,并根据系统指标调整 dispatch rate。
两者可以单独部署,也可以组合。组合时,Batch Gateway 负责 API/job 管理,Async Processor 负责带流控地把任务推进 Router。
这解决的是另一个生产问题:离线任务也想吃 GPU,但不能把在线交互任务打爆。
最合理的形态是:
flowchart LR
User[Batch Client] --> BG[Batch Gateway<br/>OpenAI-compatible]
BG --> Q[Redis / PubSub]
Q --> AP[Async Processor]
AP --> R[llm-d Router]
Chat[Interactive Client] --> R
R --> V[vLLM Pods]
Async Processor 可以根据 Router/EPP 的指标调节发送速度,让 batch workload 成为“可让路”的后台流量。
13. 部署形态:Standalone Mode和Gateway Mode
v0.7 release 提到一个 UX 变化:默认部署改为 standalone mode,用通用 proxy 降低 gateway 配置难度;生产仍建议完整 Gateway。
13.1 Standalone Mode
Standalone Mode 通常是 Router 自带 proxy sidecar。优点是:
- 上手简单。
- 不需要先把 Istio/agentgateway/Gateway provider 全部配好。
- 适合 quickstart、POC、benchmark、单团队集群。
缺点是:
- 和企业已有 ingress/gateway/service mesh 集成较弱。
- TLS、WAF、认证、跨 namespace 路由、统一流量治理等能力要另行处理。
- 大生产环境最后通常还是会接入正式 Gateway。
13.2 Gateway Mode
Gateway Mode 通过 Gateway API / HTTPRoute / InferencePool 接入已有 Gateway provider。
优点:
- Kubernetes-native。
- 适合多团队、多 namespace、多模型服务。
- 能复用 Istio、agentgateway、GKE L7 LB 等基础设施。
- 更接近生产流量治理方式。
缺点:
- 初始配置复杂。
- Gateway API Inference Extension、provider 版本、HTTPRoute、InferencePool、EPP service 引用要全部对齐。
v0.7 release 表里的相关版本包括:
- Gateway API Inference Extension chart:
v1.5.0。 - Gateway API:
v1.5.1。 - Istio:
1.29.1。 - agentgateway:release 表写的是
v2.2.1。
实际安装时要以对应 guide 和 chart 参数为准。
14. llm-d和KServe、Ray Serve、Triton是什么关系
容易混淆的地方是:llm-d 不是一个通用模型服务框架,也不是训练/推理统一平台。
粗略比较:
| 系统 | 更像什么 | llm-d相对关系 |
|---|---|---|
| vLLM | 单实例/分布式推理引擎 | llm-d 默认重点编排的 model server |
| SGLang | 推理引擎和 serving runtime | llm-d 可集成的 model server |
| Triton | 通用推理服务器 | llm-d 更专注 LLM routing/KV/P-D |
| KServe | Kubernetes 上模型服务 CRD/平台 | llm-d 可以补充 LLM-aware routing 和优化路径 |
| Ray Serve | Python/Ray 生态分布式 serving | llm-d 更 Kubernetes/Gateway/API-native |
| Dynamo | NVIDIA 推理/分布式运行时方向 | llm-d 里引用 NIXL 等能力,定位不完全相同 |
最准确的说法是:
llm-d 是 Kubernetes-native 的 LLM inference serving stack,重点解决多副本、多阶段、多层 KV cache、多租户和高性能路由问题。
15. 什么时候该用llm-d
适合用 llm-d 的场景:
- 你已经在 Kubernetes 上跑 vLLM/SGLang,且需要 scale-out。
- 多轮对话、agent、RAG 有大量共享 prefix,round-robin 导致 cache 命中率低。
- 长 prompt 和短交互请求混跑,decode latency 抖动明显。
- KV cache 工作集明显超过 HBM,想用 CPU RAM 或共享存储延长 cache 生命周期。
- 需要 P/D disaggregation 或 MoE wide EP。
- 多租户、多优先级流量需要 flow control 和 fairness。
- 需要基于 queue depth、KV pressure、SLO 的扩缩容。
- 希望有 benchmarked well-lit path,而不是从零拼 Helm/YAML。
暂时不适合或要谨慎的场景:
- 单机单卡或只有一个 vLLM Pod,Router/EPP 带来的收益有限。
- 只是开发测试,不需要 Gateway、流控、扩缩容。
- Kubernetes 基础设施不成熟,团队还没有能力排查 CRD、Gateway、network policy、RDMA、storage、Prometheus。
- 异构池里想直接用 predicted latency。官方文档明确说 predictor 假设 homogeneous pool。
- 没有 RDMA 却想上高性能 P/D。TCP fallback 只能作为开发测试。
- 对最低复杂度优先的小服务,直接 vLLM + 普通 Service 可能更合理。
16. 读源码/文档时的模块地图
如果要继续深入,可以按这个顺序读:
1. README.md
看项目定位、release news、performance highlights。
2. docs/architecture/README.md
看 Router / InferencePool / Model Server 三件套。
3. docs/architecture/core/router/README.md
看 Router = Proxy + EPP。
4. docs/architecture/core/router/epp/README.md
看 EPP 的 Request Handler、Flow Control、Request Scheduler、Data Layer。
5. docs/architecture/advanced/kv-management/
看 prefix routing、KV indexer、KV offloader。
6. docs/architecture/advanced/disaggregation/
看 P/D 请求编排和 NIXL KV transfer。
7. docs/architecture/advanced/latency-predictor.md
看在线 XGBoost latency prediction。
8. docs/well-lit-paths/
看 optimized baseline、precise prefix cache、tiered prefix cache、P/D、WideEP、autoscaling、batch。
9. guides/
看实际 Helm/Kustomize values 和可运行 recipe。llm-d 官方仓库本身更像 meta repo。很多核心代码在子仓库里:
llm-d/llm-d-inference-scheduler:Router/EPP 相关。llm-d/llm-d-kv-cache:KV index/offload connector 相关库。llm-d/llm-d-latency-predictor:预测延迟的训练和推理服务。llm-d-incubation/batch-gateway:batch gateway。
17. 一个实践落地路径
如果我是从已有 vLLM Kubernetes 服务迁移到 llm-d,会按这个顺序:
17.1 先做optimized baseline
目标不是一开始就上 P/D 和 KV offload,而是先让 Router 接管流量。
验收指标:
- 请求能通过 Router 正常进 vLLM。
- EPP 能发现 InferencePool endpoints。
/metrics能被抓到。- prefix-aware + load-aware routing 相比 round-robin 有收益。
- 故障时能判断是 Proxy、EPP、InferencePool 还是 model server 问题。
17.2 再上precise prefix cache
当 approximate routing 不够准时,引入 tokenizer 和 KVEvents。
重点验证:
- tokenizer 和模型版本一致。
- KVEvents 是否稳定送到 indexer。
- EPP 多副本时事件订阅模式是否正确。
- speculative indexing 是否开启。
- prefix cache hit 对 TTFT 的实际收益。
17.3 然后考虑KV offloading
如果 cache eviction 是瓶颈,先从 CPU offloading 开始。它复杂度低,收益通常更直接。
当需要跨节点共享或持久化时,再考虑 shared filesystem backend。
重点验证:
- CPU memory request/limit 足够。
- GPU-CPU transfer 对 compute 是否有干扰。
- storage offload 的读延迟是否真的低于 recompute。
- block size 是否适合典型 prefix 长度。
- 存储清理/容量上限是否有外部机制。
17.4 最后上P/D、WideEP和WVA
P/D 和 WideEP 是高收益高复杂度功能。上之前要先有:
- 稳定 RDMA。
- 清晰的 prefill/decode workload 特征。
- 完整 tracing/metrics。
- 可重复 benchmark。
- 明确 SLO。
WVA 也是类似。没有多个 model variants 或异构资源时,不要为了“高级”而上。
18. 常见误区
18.1 “llm-d会让单个请求变快”
不一定。llm-d 主要优化的是集群级吞吐、tail latency、cache reuse、资源利用率和服务稳定性。单个冷请求的模型计算仍然由 vLLM/SGLang 决定。
18.2 “有了prefix cache routing就不需要load balancing”
错。cache-warm Pod 可能已经过载。生产路由必须同时看 cache affinity 和 load,甚至进一步看 predicted latency。
18.3 “KV offload一定比重算快”
不一定。CPU RAM 通常有优势,但 shared storage 的收益取决于 prefix 长度、block size、网络和文件系统。短 prompt 从存储拉 KV 可能不划算。
18.4 “P/D分离适合所有模型”
不一定。P/D 的收益来自阶段隔离和资源专用化,但它引入 KV transfer 和 sidecar 编排。短 prompt、低并发、小模型可能得不偿失。
18.5 “Predicted latency可以直接用于异构池”
不建议。v0.7 文档明确说 predictor 假设 homogeneous inference pool。异构硬件或不同 serving 配置混在一起,会让模型学习到错误关系。
18.6 “llm-d就是Helm chart集合”
不是。它确实提供 well-lit path 和部署 recipe,但核心是 Router/EPP 的决策框架、KV cache 管理体系和推理工作负载的控制面。
19. 总结
llm-d 的定位可以总结成三句话:
- 它站在 vLLM/SGLang 之上,解决 scale-out LLM serving 的路由、KV、流控和编排问题。
- 它站在 Kubernetes/Gateway API 之内,用 CRD、Gateway、Pod discovery、metrics、autoscaling 把推理系统变成云原生服务。
- 它的核心价值在生产复杂度:prefix cache 命中、P/D 分离、KV offloading、latency prediction、flow control、autoscaling、batch 和 wide EP 都是单 Pod 推理之外的问题。
如果你的服务还在单实例阶段,先把 vLLM 参数、模型量化、batching、KV cache 调清楚。如果你已经进入多副本、多租户、长上下文、多轮对话、P/D 或大 MoE 模型阶段,llm-d 值得认真研究。
参考
- llm-d GitHub README: https://github.com/llm-d/llm-d
- llm-d v0.7.0 release: https://github.com/llm-d/llm-d/releases/tag/v0.7.0
- llm-d Architecture: https://llm-d.ai/docs/architecture
- InferencePool architecture: https://llm-d.ai/docs/architecture/core/inferencepool
- llm-d Router architecture: https://llm-d.ai/docs/architecture/core/router
- EPP architecture: https://llm-d.ai/docs/architecture/core/router/epp
- KV Cache Management: https://llm-d.ai/docs/architecture/advanced/kv-management
- Prefix-Cache Aware Routing: https://llm-d.ai/docs/architecture/advanced/kv-management/prefix-cache-aware-routing
- KV-Cache Indexer: https://llm-d.ai/docs/architecture/advanced/kv-management/kv-indexer
- KV-Cache Offloading: https://llm-d.ai/docs/architecture/advanced/kv-management/kv-offloader
- Disaggregated Serving: https://llm-d.ai/docs/architecture/advanced/disaggregation
- Latency Predictor: https://llm-d.ai/docs/architecture/advanced/latency-predictor
- Autoscaling: https://llm-d.ai/docs/architecture/advanced/autoscaling
- Batch Inference: https://llm-d.ai/docs/architecture/advanced/batch
- llm-d well-lit paths: https://llm-d.ai/docs/well-lit-paths