业界如何在 Kubernetes 上跑 vLLM:训练与推理分离的实践

vLLM 已经成为大语言模型推理领域最重要的开源引擎之一,但它本质上是一个 推理与服务系统,而不是一个训练框架。理解这一点之后,很多 Kubernetes 上的架构选择就会变得非常自然:训练用训练栈,推理用 vLLM,二者通过模型产物衔接,而不是混在同一个工作负载里。

如果只问一句“业界如何在 Kubernetes 上跑 vLLM”,最简短的答案是:小规模用 Helm/Deployment 跑单实例或多副本,大模型和多节点场景会引入 KubeRay/Ray Serve,一旦追求更高吞吐或更严格 SLA,就会把路由、数据并行、甚至 prefill/decode 拆开。

一、先说结论:vLLM 主要负责推理,不负责训练

在工程实践里,训练和推理几乎总是两套不同的系统:

  • 训练侧关心的是吞吐、收敛速度、checkpoint、容错恢复
  • 推理侧关心的是 TTFT、ITL、P95/P99 延迟、QPS、稳定性与成本
  • vLLM 的强项是推理执行、KV cache 管理、continuous batching、并行推理和 OpenAI 兼容服务接口
  • 真正的训练通常还是由 PyTorch、DeepSpeed、FSDP、Megatron-LM、Ray Train、Kubeflow Training Operator 等栈承担

所以,Kubernetes 上最常见的真实做法不是“用 vLLM 跑训练和推理”,而是:

  1. 用训练作业产生 checkpoint / adapter / LoRA / 量化产物
  2. 将这些产物保存到对象存储、共享文件系统或模型仓库
  3. 再由推理发布系统把模型拉到 vLLM 服务中

这是一条非常典型的 artifact-based handoff 链路。


二、Kubernetes 上跑 vLLM 的四种主流模式

模式 1:单 Pod 单实例 —— 最容易落地

这是很多团队的起点,也是小中型模型最常见的形态。

特点:

  • 一个 Pod 里直接启动 vllm serve
  • 前面挂 ServiceIngress/Gateway
  • 模型从 PVC、S3、对象存储或 Hugging Face cache 加载
  • 横向扩容时,直接增加 Deployment 副本数

适合:

  • 7B / 14B / 32B 这类模型
  • 单卡或单机多卡能放下的服务
  • 想先快速上线一个可用 API

这种方式和传统 Web 服务最像,运维团队也最容易接受。vLLM 官方仓库里已经提供了 Helm chart,可直接作为 Kubernetes 部署的起点。

模式 2:一个逻辑副本跨多 GPU / 多节点

当模型单卡放不下,或者希望在一个逻辑副本内实现更低延迟时,就会进入分布式推理模式。

在 vLLM 中,最常见的是:

  • TP(Tensor Parallel):把权重切到多张 GPU 上
  • PP(Pipeline Parallel):把层切到多个节点或多个 GPU 上
  • EP(Expert Parallel):MoE 模型中把 expert 分散到不同 GPU

常见经验是:

  • 单机多卡:优先用 TP
  • 多机多卡:常见组合是 TP = 每节点 GPU 数PP = 节点数
  • MoE 模型:会进一步结合 DP 或 EP

在 Kubernetes 上,这种模式经常搭配 KubeRay 或 Ray 集群来管理多节点资源。这样做的好处是:

  • 多节点资源调度更容易统一管理
  • 节点故障、资源发现、日志和观测更体系化
  • 更容易和 Ray Serve / Ray Data 这样的生态集成

模式 3:多个 vLLM 副本 + 外部路由层

这是很多生产环境里比“单个超大实例”更常见的方案。

原因很简单:vLLM 的很多关键状态是 实例本地状态,尤其是:

  • 当前请求队列
  • 等待队列长度
  • 每个实例自己的 KV cache
  • prefix cache 命中情况

因此,大规模线上系统往往不会只用一个简单的四层负载均衡把流量随机打给多个 vLLM Pod,而是会在前面增加一层更“聪明”的路由组件,例如:

  • Ray Serve
  • KServe
  • 自研 inference gateway
  • 带排队与打分能力的 API router

这些路由层会根据实时指标做请求分配,比如:

  • 哪个副本排队更短
  • 哪个副本 KV cache 可能有 prefix 命中
  • 哪个副本当前 GPU 更空闲
  • 某些租户或模型应固定路由到哪些实例

这类架构的核心思想是:不要只扩 Pod,还要让流量调度理解模型服务的内部状态。

模式 4:Prefill / Decode 分离

这是更高阶、也越来越主流的一类部署方式。

LLM 推理并不是一个单一负载:

  • Prefill 更像高吞吐的大计算任务
  • Decode 更像低延迟、依赖 KV cache 的持续小步执行

两者对 GPU、显存、批处理和时延的偏好完全不同,因此很多高阶推理系统会把它们拆成两类服务,分别扩缩容。

graph LR
    C[Client / Gateway] --> R[Router]
    R --> P[Prefill Pods]
    R --> D[Decode Pods]
    P --> K[KV Cache Transfer / Connector]
    K --> D

适合:

  • 超长上下文请求
  • 对 TTFT 和 ITL 有明确 SLA
  • 超大模型 / MoE 模型
  • 希望按阶段分别扩容并精细调度资源

这类架构会更复杂,但在高端生产环境里非常有吸引力,因为它允许把“吞吐优化”和“延迟优化”拆开做。


三、训练侧在 Kubernetes 上通常怎么跑

训练作业和 vLLM 的运行方式完全不同。训练侧最常见的 Kubernetes 形态通常是:

  • Job
  • PyTorchJob
  • MPIJob
  • RayJob
  • 搭配 Kubeflow Training Operator
  • 大规模场景再叠加 Volcano / Kueue 做 gang scheduling

一个典型的训练流水线如下:

graph TD
    D[Dataset / Feature Store] --> T[Training Job]
    T --> C[Checkpoint / Adapter / LoRA]
    C --> E[Evaluation Job]
    E --> R[Model Registry / Object Storage]
    R --> S[Serving Release]

训练侧最关心的几个问题是:

1. Checkpoint 能不能稳定保存

训练作业通常运行很久,而且常常会抢占、重启或因为配额调整中断。所以 checkpoint 是训练体系中的核心,而不是附属品。

2. 是否支持 gang scheduling

对于 8 卡、16 卡训练,如果只调度到一部分资源,作业根本没法正常开始。因此很多训练平台都会要求“要么一起调度成功,要么不要启动”。

3. 数据与存储带宽是否足够

训练对数据吞吐和 checkpoint 写入带宽都很敏感。它面临的是 dataset streaming、样本打乱、断点续训,而不是在线请求分发。

4. 是否支持 spot / preemptible 资源

训练侧常常会用更便宜、可被抢占的 GPU 资源来控制成本;推理侧通常不愿意这样做,因为线上服务需要稳定 SLA。


四、推理侧在 Kubernetes 上通常怎么跑

推理作业更像“常驻服务”,而不是一次性 batch 任务。

最常见的资源对象包括:

  • Deployment:最常见
  • StatefulSet:需要稳定身份或本地缓存时使用
  • RayService:Ray Serve/KubeRay 场景
  • InferenceService:搭配 KServe 时常见

一个常见的推理发布链路是:

graph TD
    M[Checkpoint / LoRA / Quantized Weights] --> O[Object Storage / Model Registry]
    O --> I[Init Container / Model Downloader]
    I --> V[vLLM Pods]
    V --> G[Gateway / Ingress]
    G --> U[Users / Applications]

推理侧真正关心的是:

  • TTFT(Time to First Token)
  • ITL(Inter-Token Latency)
  • P95 / P99 延迟
  • QPS / TPS
  • GPU 利用率
  • KV cache 利用率
  • prefix cache 命中率
  • 排队长度与拒绝率

这也是为什么训练和推理很难共用一套资源调度逻辑。


五、为什么训练和推理要分开跑

1. 目标不同

训练的目标是让模型变得更好;推理的目标是稳定、便宜、快速地把模型能力交付出去。

2. 工作负载完全不同

维度 训练 推理
资源形态 大批处理、长作业 持续在线服务
调度要求 gang scheduling、checkpoint autoscaling、健康检查
关注指标 tokens/sec、loss、收敛 TTFT、ITL、P99、QPS
容错方式 恢复 checkpoint 重试、摘流、滚动升级
资源策略 可接受 spot/preemptible 更强调稳定资源

3. 升级节奏不同

训练环境经常升级:

  • 新的数据集
  • 新的优化器
  • 新的 kernel
  • 新的训练框架版本

推理环境更保守,往往更强调:

  • 稳定镜像
  • 明确回滚
  • 可观测性
  • 小步升级

4. 资源争用非常明显

即使在同一个集群里,只要训练和推理共用 GPU 节点池,也会很容易出现以下问题:

  • 训练作业抢占 GPU
  • 训练数据加载占满网络或存储带宽
  • checkpoint 写入影响推理冷启动
  • 推理服务因为节点波动导致延迟抖动

所以,越往生产走,越倾向于把训练和推理拆成两个 node pool,甚至两个独立集群。


六、业界常见的两种“训练/推理解耦”架构

方案 A:同一集群,不同 node pool

适合刚起步或平台规模还不大的团队。

graph TB
    subgraph Cluster[One Kubernetes Cluster]
        subgraph TrainNS[Namespace: train]
            TJ[PyTorchJob / RayJob]
        end
        subgraph ServeNS[Namespace: serve]
            VS[vLLM Deployment / RayService]
        end
        subgraph Storage[Shared Storage]
            OBJ[Object Storage / PVC / Model Registry]
        end
        TJ --> OBJ
        OBJ --> VS
    end

这种方式的优点是:

  • 架构简单
  • 资源池共享率高
  • 运维门槛较低

缺点也很明显:

  • 相互影响更容易出现
  • 容量规划更难
  • 线上 SLO 容易被训练任务拖慢

方案 B:训练集群和推理集群分离

这是更成熟也更稳妥的企业级做法。

graph LR
    subgraph Train[Training Cluster]
        T1[Distributed Training Jobs]
        T2[Evaluation / Validation]
    end

    subgraph Registry[Artifact Layer]
        A[Checkpoint / Adapter / Quantized Model]
    end

    subgraph Serve[Serving Cluster]
        S1[Model Downloader]
        S2[vLLM Pods]
        S3[Gateway / Router]
    end

    T1 --> T2 --> A --> S1 --> S2 --> S3

这类架构的优势非常明显:

  • 训练和推理各自独立扩容
  • 权限边界更清晰
  • 回滚、灰度、发布更容易管理
  • 可以把训练环境做得更激进,把推理环境做得更保守

七、落地时最值得注意的几个实践点

1. 优先从简单架构开始

如果模型单卡放得下,就先从单副本开始;如果单机多卡能解决,就先别急着上多节点。跨节点分布式推理对网络、调度和观测的要求都会明显上升。

2. 用“模型产物”衔接训练和推理

不要试图让训练进程直接“变身”为推理服务。正确的交接方式应该是:

  • 训练输出 checkpoint / adapter / merged weights
  • 推理流水线读取这些产物
  • 单独构建或更新 vLLM 服务

3. 分离节点池

最少也应该做到:

  • gpu-train 给训练
  • gpu-serve 给推理

并结合:

  • taints/tolerations
  • nodeSelector
  • affinity
  • priorityClass

避免两类工作负载相互干扰。

4. 多节点推理要认真处理网络与共享内存

在多节点 TP/PP/EP 场景中,网络质量会直接决定性能是否可接受。很多团队在 Kubernetes 上跑到这一步时,才真正开始关注:

  • /dev/shm
  • IPC_LOCK
  • RDMA / Infiniband
  • hostNetwork
  • privileged 安全上下文

这些配置不是“锦上添花”,而是多节点高性能推理能否跑稳的基础设施前提。

5. 不要把 Service 命名为 vllm

这是个很容易忽略的坑。vLLM 使用大量 VLLM_* 环境变量,而 Kubernetes 也会为 Service 注入同名前缀环境变量。如果 Service 名字就叫 vllm,可能会造成冲突。


八、如何快速选型

如果你正要设计一套新的架构,可以按下面这张表先做第一轮判断:

场景 推荐模式
小模型、低复杂度、先上线 单 Pod 单实例 + Deployment/Helm
单机多卡、低延迟优先 单实例 + TP
多机大模型 KubeRay/Ray + TP/PP
高并发在线服务 多个 vLLM 副本 + 外部路由
MoE 高吞吐 DP + EP
超长上下文 / 严格 SLA Prefill/Decode 分离
训练平台 PyTorchJob / RayJob / Kubeflow Training
企业级生产 训练集群与推理集群分离

九、总结

从 Kubernetes 的角度看,vLLM 最适合被视为一个 GPU 推理服务组件。它擅长的是:

  • 高性能在线推理
  • KV cache 管理
  • 连续批处理
  • 多种并行推理模式
  • 标准化的 API 服务接口

而训练系统擅长的是:

  • 分布式训练
  • checkpoint 管理
  • 数据管道
  • 恢复与重试
  • 训练资源编排

因此,业界在 Kubernetes 上的主流实践并不是“让 vLLM 同时承担训练和推理”,而是把这两件事拆开:

  • 训练侧负责产出模型产物
  • 推理侧负责把模型能力稳定交付给线上流量
  • 平台层负责调度、发布、路由和观测

这也是为什么一个成熟的 LLM 平台,最终看起来往往不像“一个 Pod 跑一切”,而更像是一条完整的模型供应链。


参考资料