KServe 工作流程:从 InferenceService 到 VLLM 服务

上一篇完成了 KServe 的安装,并通过 InferenceService 跑通了一个 Qwen 模型服务。
当时提交的 InferenceService 只包含模型格式、存储地址、GPU 资源和启动参数,KServe 却创建出了 Deployment、Service 和 HTTPRoute。这份 YAML 中没有容器镜像,那么 KServe 如何选中 HuggingFaceServer,Pod 中又为什么会运行 vLLM?
这一篇先看 KServe 的整体架构和核心 CRD,再结合上一篇的 qwen-llm,梳理从提交 InferenceService 到请求进入 vLLM 的完整流程。
以下内容基于 KServe 0.18,部署模式为 Standard。
1. KServe 整体架构
KServe 是一个构建在 Kubernetes 之上的 AI 推理平台:

整体分为控制面和数据面:

1.1 控制面:从 InferenceService 到推理服务
控制面负责创建和维护推理服务。整个过程从用户提交 InferenceService 开始:
- 用户通过
kubectl apply将 InferenceService 提交到 Kubernetes API Server。 - Admission Webhook 对配置进行默认化和校验。例如补充默认部署模式,并拒绝不符合 API 约束的配置。
- InferenceService 写入集群后,KServe Controller 通过 Watch 感知对象变化,开始执行调谐。
- Controller 根据
modelFormat匹配 ServingRuntime,从 Runtime 中取得模型服务器镜像和默认启动参数,再与 InferenceService 中的模型地址、运行参数和资源需求合并。 - 在 Standard 模式下,Controller 根据合并后的配置创建 Deployment、Service 和 HTTPRoute。Pod 创建时,KServe Pod Mutating Webhook 根据存储注解注入 PVC volume 和 volumeMount;接下来由 Kubernetes 负责调度 Pod、挂载存储和分配 GPU,Gateway Controller 负责让 HTTPRoute 生效。
- Controller 持续观察 Deployment 和 HTTPRoute 的状态。当 Predictor 可用、路由被 Gateway 接受后,会更新
PredictorReady、IngressReady和最终的Ready状态。
所以,控制面管理的是推理服务的生命周期:创建、更新、状态同步,以及配置变更后的持续调谐。
1.2 数据面:访问已经创建的推理服务
数据面由实际运行模型和处理请求的资源组成。上一篇的环境使用 Envoy Gateway 作为 Gateway API 的实现。模型服务 Ready 后,客户端就可以通过数据面访问推理服务。
客户端访问模型域名时,请求先到达 Envoy Gateway 管理的 Envoy Proxy。Envoy Proxy 应用 HTTPRoute/qwen-llm 的规则,并根据其中指向 Service/qwen-llm-predictor 的 backendRef,将请求发送到 Ready 的 Predictor Pod。这里的 Service 用于标识和发现后端,并不是一个独立的代理进程。Pod 中运行的是 HuggingFaceServer,当前配置使用 vLLM 作为推理后端。vLLM 完成推理后,响应沿原链路返回客户端。
| |
控制面决定服务应该如何部署,并保证它处于期望状态;数据面负责服务创建后的请求转发和模型推理。在线请求不会经过 KServe Controller。
2. 核心 CRD
KServe 通过 CRD 描述模型服务、运行时、推理图和模型存储初始化方式。对于上一篇的 Qwen Demo,最核心的是 InferenceService 和 ClusterServingRuntime。
二者之间的关系如下:
| |
2.1 InferenceService
InferenceService 用于描述一个模型服务需要什么,包括模型格式、模型地址、运行参数、副本数和资源需求。
一个最小的 InferenceService 如下:
| |
InferenceService 的 Spec 可以包含以下三个逻辑部分:
| 组成部分 | 是否必需 | 作用 |
|---|---|---|
| Predictor | 是 | 加载模型并执行预测或生成 |
| Transformer | 否 | 请求预处理和响应后处理 |
| Explainer | 否 | 生成模型解释 |
对于大模型推理,通常只需要 Predictor。上一篇的 Qwen 服务也只配置了 Predictor。
这里的 Predictor 是一个逻辑角色。到了 Standard 模式下,它最终会变成名为 qwen-llm-predictor 的 Deployment 和 Service。
2.2 ServingRuntime 和 ClusterServingRuntime
InferenceService 描述要运行什么模型,ServingRuntime 描述使用什么模型服务器运行。
Runtime API 按作用范围分为两种:
- ServingRuntime 只在当前 Namespace 中生效
- ClusterServingRuntime 则可以被整个集群中的 InferenceService 使用
一个简化后的 HuggingFace Runtime 如下:
| |
containers 定义模型服务器的镜像和启动方式,supportedModelFormats 声明它支持哪些模型格式。
当 InferenceService 没有显式指定 Runtime 时,KServe 会根据 modelFormat、版本、协议以及 Runtime 的 autoSelect 和 priority 自动匹配。
因此:
| |
表示模型格式为 huggingface,KServe 会选择支持该格式的 Runtime。它并不表示 Pod 中只能使用 Hugging Face Transformers 进行推理。
2.3 其他 CRD
除了 InferenceService 和 Runtime,KServe 还提供了一些面向特定场景的 CRD:
- InferenceGraph 编排多个 InferenceService,实现路由、分支和服务组合
- ClusterStorageContainer 定义不同模型存储协议对应的初始化容器和匹配规则
- TrainedModel 在 ModelMesh 场景中声明需要加载或卸载的模型
上一篇的 Demo 没有使用这些资源,后续遇到对应场景时再单独分析。
3. 核心组件
CRD 只描述期望状态,真正读取这些对象并创建模型服务的是 KServe 控制面。
3.1 Webhook
Webhook 位于资源写入 Kubernetes API 的入口。InferenceService Admission Webhook 负责补充默认值,并拒绝不符合 API 约束的配置;Pod Mutating Webhook 则会在 Pod 创建时注入模型存储相关配置。
在当前环境中,Webhook 和 Controller 运行在同一个 kserve-controller-manager Pod 中,但承担不同职责。
3.2 KServe Controller
KServe Controller 持续 Watch InferenceService,并通过 Reconcile 循环让实际状态与期望状态保持一致。
它主要负责:
- 匹配 ServingRuntime 或 ClusterServingRuntime
- 合并 Runtime 与 InferenceService 中的容器配置
- 创建工作负载、Service 和网络入口
- 处理模型存储和健康检查配置
- 观察底层资源状态并回写 InferenceService Status
Controller 只负责资源编排。Deployment 创建以后,Pod 由 Kubernetes Scheduler 调度,GPU 由 NVIDIA Device Plugin 分配;Gateway Controller 负责让 HTTPRoute 生效,实际流量由 Envoy Proxy 转发。
3.3 Predictor Pod 内部结构
以上一篇的 Qwen 服务为例,Predictor Pod 内部的层次如下:
| |
Predictor Pod 是模型服务的运行载体,容器主进程是 HuggingFaceServer。它负责启动模型服务并提供 OpenAI 兼容接口。
当前模型使用 vLLM 作为 HuggingFaceServer 的推理后端。HuggingFaceServer 会在同一个容器中创建 vLLM 引擎,由 vLLM 使用 GPU 执行推理。
4. Qwen Demo 工作流程
前面介绍的 CRD 和组件,最终会通过 Controller 的调谐过程串起来。
上一篇的 qwen-llm 使用 Standard 模式,下面只分析该模式下的资源创建和请求流程。
上一篇使用的核心配置如下:
| |
qwen-model PVC 是上一篇提前创建的,InferenceService 只负责引用它。
4.1 控制面资源创建流程
从提交 InferenceService 到服务 Ready,完整流程如下:
| |
可以从 InferenceService Status 查看最终选择结果:
| |
| |
Controller 选择 kserve-huggingfaceserver,再把 InferenceService 中的参数和 GPU 资源合并到 Runtime 提供的容器模板中。最终 Deployment 使用 GPU 版本的 HuggingFaceServer 镜像:
| |
Standard 模式下创建的资源关系如下:
| |
Deployment 可用、HTTPRoute 就绪后,Controller 会把底层状态汇总到 InferenceService:
| |
4.2 模型 Pod 启动流程
storageUri 描述模型的来源,不是容器内的最终路径,也不是 HuggingFaceServer 的启动参数。Controller 会将 pvc://qwen-model 写入 Pod 模板注解;ReplicaSet 创建 Pod 时,KServe Pod Mutating Webhook 读取该注解,将 qwen-model 解析为 PVC 名称,并向模型容器注入 PVC volume 和挂载到 /mnt/models 的 volumeMount。
如果这里使用 hf:// 地址,Webhook 则会注入 Storage Initializer init container,先从 Hugging Face Hub 下载模型,再通过共享的 EmptyDir volume 将模型提供给模型容器。
HuggingFaceServer 启动后,backend 默认为 auto。GPU 镜像中包含 vLLM;当 vLLM 可用且模型架构在 vLLM 的支持列表中时,HuggingFaceServer 会创建 vLLM 后端并从 /mnt/models 加载模型。
实际日志如下:
| |
kserve-huggingfaceserver 是本次部署选择的 Runtime,vLLM 是 HuggingFaceServer 容器内自动选择的推理后端。因此,这次部署不需要单独指定 vLLM Runtime;集群中是否还存在其他自定义 vLLM Runtime,与这条执行链路无关。
4.3 在线请求流程
服务 Ready 后,上一篇的 OpenAI Chat Completions 请求沿着下面的路径进入模型:
| |
这条请求链路属于数据面。KServe Controller 会继续维护 Deployment 和 InferenceService 状态,但不会参与请求转发。
5. 总结
结合上一篇的 Qwen Demo,KServe 的整个工作过程可以概括为:

- InferenceService 描述模型服务需要什么
modelFormat声明模型格式,供 KServe 匹配 RuntimestorageUri指定模型存储地址args设置模型服务器和推理引擎的启动参数resources声明 CPU、内存和 GPU 等资源需求
ClusterServingRuntime/kserve-huggingfaceserver提供模型服务器镜像和启动方式- KServe Controller 匹配 Runtime、合并配置,并创建 Deployment、Service 和 HTTPRoute
- Kubernetes 负责调度 Pod、挂载 PVC 和分配 GPU
- Envoy Proxy 应用 HTTPRoute 规则,通过 Predictor Service 标识的后端将请求发送到 Ready Pod
- HuggingFaceServer 使用 vLLM Backend,由 vLLM 通过 GPU 执行推理