AIBrix v0.8.0 在 2026 年 10 月 12 日发布。从 v0.7.0 算起,这个版本合入 443 个 commit,来自 104 位贡献者。

光看功能清单,容易把它当成一次“又加了一堆东西”的例行升级。但把这些改动串起来看,v0.8.0 其实在回答同一个问题:当推理集群里跑的不再是“一个模型配一组 Pod”,基础设施该怎么变?

v0.7.0 解决的是“可组合”——Console、Batch API、多引擎支持、P/D 分离、高可用网关,这些能力拼成了一个能自助使用的平台。v0.8.0 往前走了一步:模型的生命周期不再绑定 Pod 的生命周期;路由从“看请求量”变成“看推理工作量”;Agent 多轮对话和视频生成这类不典型的负载,也各自有了对应的处理路径。

下面按“问题 → 方案 → 代价”的顺序拆开讲。

这一版改了什么

先看全景,再往下拆细节。

三条主线:

  1. 模型不再必须独占 Pod。新增 ModelClaim,把模型的可用性从 Pod 生命周期里解耦出来;ModelWarmup 负责在 Pod 落地之前先把节点准备好。
  2. 路由开始考虑推理本身的代价。副本级的 RPS/在途上限、按输出 token 吞吐和 KV 余量打分、least-request-top-k,以及 Redis 支撑的会话粘滞。
  3. 网关能吃下更长的请求。异步作业注册表加上视频路由,把“提交—跟踪—取结果”这条链路接进了同一个网关。

其余散落在 Batch、StormService、LoRA、引擎 API 兼容性、可靠性上的改动,放在「其他改进」一节统一收。

老问题:模型被钉死在 Pod 上

Kubernetes 管推理负载的粒度是 Pod。这个粒度对训练和常驻的大模型服务都没问题,但有一类场景很别扭:模型很多,而且大部分时间在发呆。

模型广场、短视频的 AI 特效、Hugging Face 那种“点开某个模型页面就能试一下”的服务,都属于这类。几百个模型排在货架上,用户点哪个,哪个就来一波流量,剩下时间基本闲置。

在“模型 = Pod”的模型下,怎么选都是错的:

  • 不缩容到 0:每个模型至少留一张卡,24 小时占着,只在等人来用。
  • 缩容到 0:冷启动。调度 Pod、拉镜像、加载权重、编译并预热引擎,几十秒到几分钟不等。用户刚点完“试试”,等不了这个。

冷启动:从“收到请求”到“引擎能返回第一个 token”之间,除了真正推理之外的所有开销。对 LLM 服务来说,大头通常是镜像拉取、权重加载和 CUDA graph 捕获/引擎编译,而不是模型加载本身。

还有个更根本的问题:GPU 上跑的共享方案(time-slicing、MPS、MIG、vGPU)都工作在引擎下面。它们看得到进程和显存,看不到模型、权重和 KV Cache。所以它们只能把一张卡切成几块,没法把一个空闲模型的 KV Cache 让给隔壁更忙的邻居,也没法把空闲模型的权重挪开。

AIBrix 的选择是把共享做在引擎上面。

ModelClaim:把模型从 Pod 里拿出来

这是 v0.8.0 最大的一个改动,官方标注 Experimental。

三个角色

  • 暖池(warm pool):一个普通的 GPU Pod Deployment,带一个 pool 标签。Pod 提前起来,但里面不加载模型。
  • ModelClaim:描述“要服务哪个模型”——权重在哪、用哪个引擎、可以放到哪个池、引擎参数、以及一个实例需要多少显存。它自己不要 GPU,因为 GPU 归池子。
  • ModelClaim 控制器:给每个 claim 挑一个 Pod,让 Pod 上的 AIBrix runtime 起一个引擎。同时负责休眠、唤醒、以及给每个引擎设 KV 上限。

引擎是独立进程,各有各的 KV Cache。一个引擎崩了,runtime 重启它,同 Pod 上其他引擎不受影响。

这里能成立,靠的是两个上游项目的能力:

kvcached 让 KV Cache 变成弹性的。vLLM 引擎启动时会一口气把大部分显存预留成 KV Cache;kvcached 改成按需映射,于是同一张卡上可以跑多个引擎。

vLLM 的 sleep mode 让换出变快。引擎休眠时把权重挪到 host 内存、释放 KV Cache,需要时几秒内唤醒,不用冷启动。

两个项目各解决一半问题,但没人把它们串起来。kvcached 让多个引擎共用一张卡,可每个引擎仍然以为自己能独占整张卡;sleep 能腾出显存,但总得有人决定“哪个模型睡、腾出来的显存给谁、它要醒的时候还有没有地方”。ModelClaim 就是这个控制面。

账本:不要重复承诺显存

先说一个反面例子。两个 1.5B 的模型共用一张 95 GiB 的 H20,如果只有 kvcached 没有账本,两个引擎各自都认为自己那 80 GiB 的 KV 池是自己的,加上 weights footprint,两者合计“有权使用” 174 GiB——平时谁都不报错,直到两边同时长起来。

所以每个 claim 必须声明两个数:

1
2
3
4
spec:
perGPU:
maximumFootprint: 30Gi # KV 之外的最大占用:权重、CUDA graph、workspace
kvFloor: 10Gi # 能对外服务所需的最小 KV Cache

声明多了安全但浪费,声明少了危险。控制器拿这两个数做账本,保证同一张卡上的承诺总量不超过实际显存。装不下的 claim 会直接说出原因——比如“最多能拿到 15.1 GiB”,而不是傻等。

KV 上限:一张卡怎么按需切开

光有账本管不住引擎自己长。所以控制器还给每个引擎设一个 KV limit,而且是同一张卡上的所有引擎一起算:已经握着的不回收,醒着的至少保住自己的 floor,剩下的按需求分——忙的拿得多,闲的拿得少,睡着的拿 0。

在一张 95.1 GiB 可用的 H20 上实测,这套分配是这么变的:

时刻model-a 的 KV limitmodel-b 的 KV limit
只有 model-a65.1 GiB—
model-b 加入17.5 GiB17.5 GiB
model-a 变忙22.6 GiB12.5 GiB
model-a 休眠保留自己的 reservation25.1 GiB
model-a 唤醒17.5 GiB17.5 GiB

重算间隔大约 10 秒;模型加入、离开、失败、休眠、唤醒时立刻重算一次。

休眠:怎么把 40 GiB 的预约压到 1.3 GiB

模型空闲超过池子的 sleepAfterSeconds 就自动进入 vLLM sleep mode 的 level 1:权重挪到 host 内存,KV Cache 大部分释放。H20 上,睡着的 8B 引擎实际只占 1.0 到 1.3 GiB,而它的 reservation 是 40 GiB。

默认策略下,睡着的模型保留整个 reservation,好处是它随时能醒——没人能抢它的位置。代价是 40 GiB 里有将近 39 GiB 白躺着。

池子可以选择另一个策略:noWakeReserveWhileAsleep,让睡着的模型释放 reservation,账本上只按它实际占的算。于是一张只能同时跑两个 8B 模型的卡,可以塞下三个。

那还要不要保证醒得回来?要。唤醒时先把完整的 reservation 放回账本,别的模型抢不走,再开引擎。

唤醒:网关不排队,客户端自己重试

这块的设计挺有意思,值得单独说:休眠中的模型收到请求,网关不会挂着这个请求等引擎醒,而是立刻返回 503 加 Retry-After,让客户端自己再试。

各个状态对应网关的响应:

模型状态网关响应
可路由正常转发到引擎
休眠中 / 启动中 / 唤醒中503,Retry-After: 10
尚未放置或已经失败503,Retry-After: 10
等空间唤醒,或等别人腾空间503,Retry-After: 20
正在迁移到别的 Pod503,Retry-After: 30
配置需要改,或任何卡都装不下503,不带 Retry-After
网关不认识这个模型400

唤醒前控制器要确认卡上装得下:先把邻居引擎压到各自分到的份额,再唤醒。H20 上的实测:

  • 模型保留了自己的 reservation:请求后 4 秒可路由。
  • 需要先让邻居休眠腾地方:9 秒(含把一个邻居休眠的时间)。
  • 正在服务的邻居永远不会被休眠掉。实在腾不出空间,就把 claim 迁到别的能装下的 Pod,在那边重新起引擎;连这样的 Pod 都没有,唤醒就等着,状态写明 WaitingForRoom。

实测与代价

单节点 8 张 H20、39 个模型(1.5B 到 32B)的压力测试里,每张卡放 5 个左右的模型,其中大约 3 个是醒着的。睡着的 8B 模型在卡上留 1.7–3.2 GiB,而它的权重单独就要约 15 GiB。只要卡上有空间,一个睡着的模型大约 4 秒后就能重新服务。

代价也说清楚:

  • 只支持 vLLM,SGLang 还没接。
  • 一个 claim 目前只跑一个引擎。
  • 这是 experimental 特性,别急着往生产关键路径上放。
  • 客户端必须实现 503 + Retry-After 的重试逻辑。这是设计的一部分,不是临时妥协——网关宁可立刻返回,也不愿意攒着一堆请求在内存里等引擎。

ModelWarmup:把准备工作挪出关键路径

ModelWarmup 解决的是另一半问题:即使模型能秒级唤醒,节点本身还是冷的。

它的做法很直接——让运维指定一批节点,提前拉好容器镜像,并且执行自定义的准备动作。这些动作本来都压在 Pod 的启动路径上,现在提前做掉,等 Pod 真被调度过来,启动只剩下加载权重和引擎初始化。

同样标注 experimental,API 和能力都还在演进。但对“已知接下来要跑哪几个模型”的场景,这是一个成本很低、收益很直接的优化。

关键路径(critical path):从用户发出请求,到这个请求必须开始被处理之间的必经步骤。关键路径上的任何耗时都直接变成用户等待时长;能挪出关键路径的工作,都是白赚的延迟优化。

会话粘滞:给 Agent 负载做路由

为什么 Agent 特别吃这一套

Agent 应用发出来的不是一个孤立的 prompt,而是一串有关联的请求:规划、调工具、看结果、再规划,一轮一轮往下走。

如果每一轮都独立路由,就会丢掉本来能用的局部性——处理过前几轮的那个副本,很可能 KV Cache 里还留着这段会话的上下文。把它换到另一个副本,前面那些前缀就得重新 Prefill 一遍。

AIBrix v0.8.0 的做法是 Redis 支撑的 session-key pinning:应用给一个 session id,AIBrix 把这个 session 绑到一个后端副本上(#2742)。

Session affinity(会话粘滞):把同一个会话的请求持续送到同一个后端。对普通 Web 服务它主要影响本地缓存和连接复用;对 LLM 推理,它直接影响 KV Cache 命中率,也就是 TTFT 和 GPU 算力浪费。

为什么非得用 Redis

因为网关是多副本部署的,本身不存状态。如果绑定关系只存在某一个网关副本的内存里,下一次请求被负载均衡到另一个副本就失效了。

映射放进共享存储之后,请求从任何一个网关副本进来,都能落到同一个后端:

这一版还顺手把分布式 pinning 的协议打磨了一遍:首次抢占要安全、刷新行为、以及选中的后端需要被绕开时怎么重新绑定(#2765、#2768、#2773)。

结果是 AIBrix 有了给多轮对话和 Agent 负载做路由的基础,判据是三个东西的组合:

会话粘滞 + 前缀缓存局部性 + 副本负载

而不是把每个请求都当第一次见。

异步多模态:视频生成进网关

视频生成和文本生成的差别不是“慢一点”,而是量级不同。一次生成动辄几十秒到几分钟,套在同步的 request-response 模型里,连接、超时、重试全都别扭。

v0.8.0 把这条路补上了:支持 vLLM-Omni 的视频生成(#2686),网关里增加了异步作业注册表和视频路由路径(#2740)。

请求的生命周期从 请求 → 推理 → 响应 变成了 提交 → 路由 → 异步执行 → 跟踪 → 取结果。这个变化不只是加个队列那么简单:

长作业在网关里有归属、能被追踪,同时走的还是那套控制面和 OpenAI 兼容入口——不用为视频单独搭一套服务。

路由开始算“推理成本”

这是 v0.8.0 里我比较喜欢的一类改动:都不大,但都在把网关从“请求级负载均衡”推向“推理感知的流量管理”。

副本级容量上限。 路由 profile 可以定义每个副本的 RPS 和在途请求上限,定义在 deployment 级别,每个副本继承(#2726)。这样总容量跟着副本数走,超过阈值的副本会被网关直接跳过。

RPS / 在途请求(in-flight):RPS 限制的是速率,在途限制的是“同时还没返回的请求数”。对 LLM 来说,一个长上下文请求可能占住一个副本好几十秒,所以在途数往往比 RPS 更接近真实压力。

按推理工作量做负载均衡。 打分的输入不再只是连接数,而是输出 token 吞吐、已提交的工作量、可用 KV 容量这些信号;P/D 路由里的 decode 打分也加上了 token load(#2771、#2842)。异构卡混布、序列长度方差大的场景下,这比“看谁请求少”准得多。

P/D 分离(Prefill/Decode disaggregation):把 LLM 推理的两个阶段拆到不同的实例上。Prefill 是一次性处理整个输入,算力密集;Decode 是逐个吐 token,吃显存带宽。两者资源画像差别很大,分开部署、各自扩缩容更划算——代价是 KV Cache 要在实例之间搬。

更稳的 least-request。 新的 least-request-top-k:不是永远挑负载最小的那一个副本,而是从最闲的一小撮里挑(#2918)。听起来是小改动,解决的却是很现实的抖动——多个网关副本各自算一次最小值,很容易同时盯上同一个刚就绪的副本,把它瞬间打爆。它同时也是 AIBrix 自动混合路由里负责负载的那个分量。

外部路由:网关不垄断决策

还有一个 experimental 的方向:允许路由决策由 AIBrix 之外的系统产生,AIBrix 继续提供服务发现、流量管理和周边基础设施。

目标很明确,让运维可以自己组合:

AIBrix 基础设施 + 你选的推理引擎 + 你选的路由策略

不用为了用其中一层,把整套服务栈都换成同一家的实现。对于已经在别处投了路由系统的团队,这个口子比“再写一个 Router 实现”实用得多。

其他改进

剩下的改动比较零散,但对真在生产里跑的人,可能比前面几个大特性更实在。挑重点:

Batch 推理更能扛弹性伸缩。 新增自适应 AIMD 并发控制(#2530)、容量感知并发,作业和算力供给窗口对齐(#2575),另外修了重试、输出持久化、分发错误、取消、作业加载等一批问题。

AIMD(加性增、乘性减):拥塞控制里的经典策略——稳的时候线性加一点并发,一旦碰到瓶颈就成倍往下砍。用在 Batch 上,效果是“后端能扛就多吃一点,扛不住就快速退让”,比固定并发数更适合共享、会变的算力池。

多机推理与 StormService。 加了 drain-aware 的 RoleSet 滚动更新和缩容(#2651)、进度 deadline(#2604)、历史节点替换调度(#2628)、部署模式处理(#2617),并加强了与 Volcano gang scheduling 的集成(#2672、#2733)。

Gang scheduling(成组调度):要么整组 Pod 一起调度成功,要么一个都不启动。多机推理里一个实例可能横跨几个节点,任何一半失败都毫无意义,还会白占资源——所以必须成组拉起。

LoRA 与 ModelAdapter。 Console 里可以直接管理 Kubernetes 上的 ModelAdapter(#2514);服务侧补了多 LoRA 示例、per-adapter 的网关指标、更完整的 ModelAdapter 状态上报(#2624),以及一批加载、选 Pod、reconcile、校验相关的修复。

引擎 API 覆盖面更广。 网关扩了 SGLang 的 /v1/decisions、/v1/systemone、/v1/score,原生 vLLM 的 /classify,以及 Messages API 路径(含 /v1/messages/count_tokens);TensorRT-LLM 侧加了 generation-first 的并行 P/D 路由(#2794)。

路由与 P/D 的可靠性。 token load 状态可以跨网关副本共享(#2868);模型发现变成可选项,同时继续暴露 ready 的后端(#2913、#2915);P/D 路由补上了 decode 无响应、prefill 失败后留下静默 decode 流这些失败路径(#2859、#2860、#2933)。

可验证性。 新增安装冒烟流水线(#2730)、StormService + Volcano gang scheduling 的 e2e 用例、ModelRouter 生命周期测试(#2743),Helm、CRD、RBAC、webhook 也跟着 API 一起对齐。

这类改动的曝光度远不如新特性,但决定了“敢不敢升级”。AIBrix 的 API 面这一年扩得很快,把测试和安装流程补齐,重要性一点不低于加功能。

判断一下:这次该不该升级

你的场景关注点
长尾模型多、流量稀疏(模型广场、特效、试玩)ModelClaim + ModelWarmup,收益最直接;但先按实验特性对待
Agent、多轮对话,网关多副本Redis session pinning
长上下文、序列长度方差大、异构卡token load / KV 余量打分、least-request-top-k
长耗时多模态生成异步作业注册表 + vLLM-Omni
已经在用别的路由系统外部路由(实验)

两个提醒:

  • ModelClaim 和 ModelWarmup 都是 experimental,API 还会变,别直接上关键业务。想尝鲜可以先拿非核心的模型池试。
  • 用了 ModelClaim 之后,客户端必须能正确处理 503 + Retry-After。这不是可以忽略的细节——把重试漏掉,用户看到的就是间歇性失败。

最后

AIBrix 从一堆“可扩展 LLM 推理的 K8s 积木”起步,v0.7.0 把它们拼成了可自助使用的平台。v0.8.0 的信号是下一阶段的方向:调度和流量管理要开始互相知道对方在干什么。

官方也提到了正在做的 omni-modal 与多阶段服务(#1966、#2962)——Encode、Prefill、Decode 这些阶段可以按各自的资源和延迟特征分别放置、扩缩、路由。真做成了,网关面对的就不只是“选一个副本”,而是一条由多个异构阶段组成的流水线。

项目在 GitHub,v0.8.0 的完整说明见 官方 release 公告,ModelClaim 的设计细节见 ModelClaim: Engine-Aware GPU Sharing for Long-Tail Models。