2. Knative Serving架构深度解析
Knative Serving 把“一次请求如何被接住、如何被扩缩、如何被送进业务容器”拆成了四个职责清晰的组件:Controller 负责把声明式配置翻译成实际可运行的资源;Activator 负责在无实例或实例不足时缓冲并转发请求;Autoscaler 负责根据指标决定副本数;Queue-Proxy 作为每个 Pod 的边车,负责请求排队、并发统计与指标上报。理解它们之间的协作,比记住组件名字更重要。
一、四个组件的职责边界
Controller 是 Knative Serving 的“大脑”。它监听 Service、Configuration、Revision、Route 等 CRD,并据此创建或更新 Deployment、Service、Ingress 等底层资源。例如,当用户提交一个 Service 时,Controller 会生成对应的 Configuration 和 Route;Configuration 再生成 Revision;Revision 最终对应一个 Deployment。Controller 不直接处理数据面请求,它只保证“期望状态”与“实际状态”一致。
Activator 是“请求缓冲区”。当某个 Revision 的副本数为 0,或正在冷启动、扩容尚未完成时,流量不会直接打到不存在的 Pod,而是先进入 Activator。Activator 会持有这些请求,等待后端出现可用实例后再转发。它同时承担负载均衡和请求缓冲的角色,避免请求在冷启动期间直接失败。
Autoscaler 是“扩缩决策器”。它从 Queue-Proxy 和指标系统收集数据,计算当前 Revision 所需的副本数,并把结果写回 Revision 的期望副本数。Knative 默认使用 KPA(Knative Pod Autoscaler),也支持 HPA。KPA 的核心输入包括并发数、RPS 以及稳定窗口、恐慌窗口等参数。
Queue-Proxy 是“数据面边车”。每个业务 Pod 中都会注入一个 Queue-Proxy 容器,它与业务容器共享网络命名空间。所有进入 Pod 的请求先经过 Queue-Proxy,由它负责排队、并发计数、超时控制,并把请求转发给业务容器。同时,Queue-Proxy 会周期性上报指标,供 Autoscaler 决策。
二、一次请求的完整链路
假设一个 Revision 当前副本数为 0,客户端发起请求。请求首先到达 Ingress(如 Kourier 或 Istio),Ingress 根据 Route 规则匹配到目标 Revision。此时 Controller 已经为该 Revision 配置了“无实例时指向 Activator”的路由策略,因此请求被转发到 Activator。
Activator 收到请求后不会立即返回失败,而是把请求放入等待队列,同时触发扩容。Autoscaler 从 Revision 的指标中看到“有请求但无实例”,会迅速把期望副本数从 0 提升到 1。Controller 监听到 Revision 变化后,创建或更新对应的 Deployment,Kubernetes 调度并启动 Pod。Pod 内包含业务容器和 Queue-Proxy 两个容器。
当 Pod 就绪后,Queue-Proxy 开始监听端口,Activator 检测到后端可用,便把排队中的请求转发给该 Pod 的 Queue-Proxy。Queue-Proxy 再将请求交给业务容器处理,并把响应沿原路返回。整个过程对客户端表现为一次稍慢但成功的请求,而不是 503。
当副本数已经大于 0 且 Pod 就绪时,Ingress 会直接把请求转发到 Pod 的 Queue-Proxy,不再经过 Activator。这样可以减少一跳,降低延迟。Activator 只在“无实例”或“实例不足”时介入,因此它并不是所有请求的必经之路。
三、Autoscaler 的决策输入与关键参数
Autoscaler 的决策依赖 Queue-Proxy 上报的指标。Queue-Proxy 会统计当前 Pod 的并发请求数、每秒请求数以及请求排队时长,并把这些数据发送给 Autoscaler。KPA 根据这些指标计算期望副本数,核心公式可以简化为:期望副本数 = 当前总并发 / 目标并发。例如目标并发设为 10,当前总并发为 35,则期望副本数约为 4。
KPA 还引入了稳定窗口和恐慌窗口。稳定窗口用于平滑扩缩,避免指标抖动导致副本数频繁变化;恐慌窗口用于快速扩容,当指标在短时间内急剧上升时,Autoscaler 会忽略稳定窗口,直接按更高倍数扩容。以下是一个示例配置片段:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: demo-app
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/target: "10"
autoscaling.knative.dev/minScale: "0"
autoscaling.knative.dev/maxScale: "20"
autoscaling.knative.dev/stable-window: "60s"
autoscaling.knative.dev/panic-window: "10s"
spec:
containers:
- image: registry.example.com/demo-app:v1
ports:
- containerPort: 8080
其中 target 表示每个副本的目标并发数,minScale 和 maxScale 控制副本数边界,stable-window 和 panic-window 控制扩缩灵敏度。这些参数需要结合业务延迟要求和资源成本共同调整。
四、Queue-Proxy 的排队与超时控制
Queue-Proxy 不只是“转发器”,它还承担请求排队和超时控制。当业务容器处理能力不足时,Queue-Proxy 会把请求暂存在队列中,避免请求直接压垮业务进程。同时,Queue-Proxy 会根据 Revision 的超时配置决定请求最长等待时间。如果请求在队列中等待超过阈值,Queue-Proxy 会返回超时错误,而不是无限等待。
Queue-Proxy 还会向 Autoscaler 上报“当前并发”和“排队深度”。这两个指标直接影响扩容决策:并发高说明需要更多副本,排队深说明当前副本处理不过来。因此,Queue-Proxy 是 Autoscaler 的“眼睛”,没有它,KPA 就无法感知数据面真实压力。
五、组件协作中的常见故障点
理解链路后,排障就有了方向。如果请求返回 503,可能是 Activator 无法连接后端,或 Pod 一直未就绪;如果冷启动特别慢,可能是镜像拉取慢或业务容器启动慢;如果副本数频繁抖动,可能是 target 设置过小或稳定窗口过短;如果请求延迟高但副本数不涨,可能是 Queue-Proxy 指标上报异常或 Autoscaler 未正确读取指标。
实际排查时,可以按“Ingress → Activator → Queue-Proxy → 业务容器”的顺序逐段确认。先看 Ingress 是否匹配到正确 Revision,再看 Activator 日志是否有转发失败,然后检查 Queue-Proxy 是否正常上报指标,最后确认业务容器是否真正处理了请求。这样就能把四个组件的协作关系转化为可操作的排障路径。