4. Runtime 工作流程:从 kubectl apply 到请求被路由
一句话理解:一次
kubectl apply -f inference-service.yaml会触发 KServe controller 的 reconcile 链——选 runtime → 渲染 workload → 注入 storage → 创建网关资源 → 更新 status → 等待 Pod ready → 流量接入。
4.1 完整时序图
用户 K8s API KServe ServingRuntime Knative/ Pod Ingress/
Server Controller 注册表 K8s API (runtime) Gateway
│ │ │ │ │ │ │
│ apply IS │ │ │ │ │ │
│────────────▶│ │ │ │ │ │
│ │ write IS │ │ │ │ │
│ │─────────────▶│ │ │ │ │
│ │ │ Informer ADDED │ │ │ │
│ │ │ │ │ │ │
│ │ │───────────┐ │ │ │ │
│ │ │ ▼ │ │ │ │
│ │ │ workqueue.add(IS) │ │ │
│ │ │ │ │ │ │
│ │ │◀────────── │ │ │ │
│ │ │ │ │ │ │
│ │ │ reconcile(IS) │ │ │ │
│ │ │ │ │ │ │
│ │ │ 1. 读取 spec │ │ │ │
│ │ │ 2. 匹配 runtime │ │ │ │
│ │ │───────────────▶│ │ │ │
│ │ │◀───────────────│ │ │ │
│ │ │ 3. 渲染 PodSpec│ │ │ │
│ │ │ (model │ │ │ │
│ │ │ container │ │ │ │
│ │ │ + storage │ │ │ │
│ │ │ init) │ │ │ │
│ │ │ │ │ │ │
│ │ │ 4. 创建/更新 │ │ │ │
│ │ │ Knative │ │ │ │
│ │ │ Service 或 │ │ │ │
│ │ │ Deployment │ │ │ │
│ │ │──────────────────────────────▶│ │ │
│ │ │ │ │ │ │
│ │ │ 5. 创建 Service/│ │ │ │
│ │ │ Ingress │ │ │ │
│ │ │─────────────────────────────────────────────────────────▶│
│ │ │ │ │ │ │
│ │ │ 6. 创建 HPA/ │ │ │ │
│ │ │ KEDA/ │ │ │ │
│ │ │ Knative PA │ │ │ │
│ │ │──────────────────────────────▶│ │ │
│ │ │ │ │ │ │
│ │ │ 7. 更新 IS status│ │ │ │
│ │◀─────────────│ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │ │ Pod 创建 │ │
│ │ │ │ │────────────▶│ │
│ │ │ │ │ │ storage init│
│ │ │ │ │ │ 拉模型 │
│ │ │ │ │ │ │
│ │ │ │ │ │ runtime 启动│
│ │ │ │ │ │ 加载模型 │
│ │ │ │ │ │ │
│ │ │ │ │ 就绪探针通过 │ │
│ │ │ │ │◀────────────│ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ HTTP │ │ │ │ │ │
│ POST │ │ │ │ │ │
│ /v2/... │ │ │ │ │ │
│──────────────────────────────────────────────────────────────────────────────────────▶│
│ │ │ │ │ │ │
│ │ │ │ │ │◀────────────│
│ │ │ │ │ │ 推理返回 │
│ │ │ │ │ │────────────▶│
│ response │ │ │ │ │ │
│◀──────────────────────────────────────────────────────────────────────────────────────│4.2 阶段详解
阶段 1:CRD 写入与事件触发
用户执行:
kubectl apply -f sklearn-iris.yamlK8s API Server 把 InferenceService 对象写入 etcd,resourceVersion 递增。KServe controller 的 Informer 收到 ADDED 事件,加入 workqueue。
阶段 2:Runtime 选择
Reconciler 读取 spec.predictor.model.modelFormat.name,查询 runtime 注册表。
示例:
spec:
predictor:
model:
modelFormat:
name: sklearn匹配到:
# ClusterServingRuntime
metadata:
name: kserve-sklearnserver
spec:
supportedModelFormats:
- name: sklearn
autoSelect: true
priority: 1如果用户显式写 runtime: kserve-sklearnserver,则跳过 autoSelect 直接命中。
阶段 3:渲染 PodSpec
Controller 用 runtime 模板生成容器:
containers:
- name: kserve-container
image: kserve/sklearnserver:v0.13.0
args:
- --model_name=sklearn-iris
- --model_dir=/mnt/models
volumeMounts:
- name: kserve-provision-location
mountPath: /mnt/models同时注入 storage-initializer init container:
initContainers:
- name: storage-initializer
image: kserve/storage-initializer:v0.13.0
args:
- gs://kfserving-examples/models/sklearn/1.0/model-1
- /mnt/models如果配置了 transformer 或 explainer,再渲染对应的 sidecar 或独立 deployment,并设置它们与 predictor 之间的调用关系。
阶段 4:创建 Workload
Serverless 模式:
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
annotations:
serving.kserve.io/deploymentMode: ServerlessController 创建一个 Knative Service:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: sklearn-iris
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "5"
spec:
containers:
- image: kserve/sklearnserver:v0.13.0
...RawDeployment 模式:
Controller 直接创建:
DeploymentService(ClusterIP)Ingress/VirtualServiceHorizontalPodAutoscaler(如果配了 HPA)
阶段 5:创建网关资源
KServe 根据 ingressGateway 配置创建 Istio VirtualService 或 K8s Ingress。
示例 Istio VirtualService:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: sklearn-iris
spec:
gateways:
- knative-serving/knative-ingress-gateway
hosts:
- sklearn-iris.default.example.com
http:
- route:
- destination:
host: sklearn-iris-predictor
weight: 100阶段 6:扩缩容配置
Serverless 模式下,KServe 把 minReplicas/maxReplicas 转成 Knative annotations:
metadata:
annotations:
autoscaling.knative.dev/minScale: "1"
autoscaling.knative.dev/maxScale: "5"RawDeployment 模式下,创建 HPA:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: sklearn-iris-predictor
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sklearn-iris-predictor
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60阶段 7:更新 Status
Controller 把创建结果写回 IS 的 status subresource:
status:
conditions:
- type: PredictorReady
status: "True"
- type: IngressReady
status: "True"
- type: Ready
status: "True"
url: http://sklearn-iris.default.example.com
address:
url: http://sklearn-iris.default.svc.cluster.local注意:status 更新不会增加 .metadata.generation(只有 spec 修改才会),这是 K8s /status subresource 的标准行为。
阶段 8:Pod 启动与模型加载
Pod 启动顺序:
- storage-initializer 下载模型到
/mnt/models。 - runtime container 启动。
- runtime 扫描
/mnt/models加载模型。 - readiness probe 通过(通常检查 8080
/ready)。 - Pod 加入 Service endpoints。
阶段 9:请求路由
客户端请求:
curl http://sklearn-iris.default.example.com/v1/models/sklearn-iris:predict \
-H "Content-Type: application/json" \
-d '{"instances": [[1.0,2.0,3.0,4.0]]}'流量路径:
客户端
│
▼
Ingres Gateway (Istio / Kourier)
│
▼
Service (sklearn-iris-predictor)
│
▼
Pod
│
▼
queue-proxy (Serverless) 或 直接到 runtime (RawDeployment)
│
▼
model server runtime
│
▼
模型推理 → 返回响应4.3 金丝雀升级流程
当用户更新 IS(如换模型版本、换 runtime 镜像)并设置 canaryTrafficPercent: 20:
- Controller 创建新版本 revision/deployment。
- 配置 traffic split:20% 到新版本,80% 到老版本。
- 观测 metrics(延迟、错误率)。
- 逐步调大 canary 比例到 100。
- 老版本 revision 缩容。
spec:
predictor:
canaryTrafficPercent: 20
model:
modelFormat:
name: sklearn
storageUri: gs://models/sklearn/v24.4 失败与重试
Reconcile 过程中任何一步失败(如 runtime 不存在、storage URI 无效、权限不足),Controller 会:
- 返回 error,workqueue 按指数退避重试。
- 在 IS status 中写入失败 condition:
status:
conditions:
- type: PredictorReady
status: "False"
reason: RuntimeNotFound
message: 'No ServingRuntime supports modelFormat "foo"'- 等待用户修复 spec 或新增 runtime 后重新 reconcile。
4.5 缩到零与冷启动
Serverless 模式:
- 无流量时 Pod 数为 0。
- 新请求先到 Knative Activator。
- Activator 缓冲请求,触发 Knative autoscaler 扩容。
- storage-initializer + runtime 启动 + 模型加载完成后,请求才放行。
冷启动成本:
- 小模型(sklearn/xgboost):几秒。
- 大模型(LLM 几十 GB):几十秒到几分钟。
- 因此 GPU/LLM 生产环境通常用 RawDeployment(minReplicas >= 1)。
本章小结
- 完整链路:apply IS → controller reconcile → 选 runtime → 渲染 workload → 创建网关 → 更新 status → Pod ready → 请求路由。
- Reconcile 是幂等的:反复执行结果一致,status 更新不影响 generation。
- 两种模式在 workload 创建上有本质差异:Serverless 用 Knative Service,RawDeployment 用原生 K8s 资源。
- 金丝雀通过 traffic split 实现;失败通过 status conditions + workqueue 退避暴露。
- 冷启动是 Serverless 的核心 trade-off,GPU 场景慎用。
参考来源