2. Kyverno 架构基础:Admission Controller 模式、Webhook 生命周期、策略引擎核心组件

要理解 Kyverno 的策略冷启动瓶颈,首先需要掌握其底层架构。Kyverno 本质上是一个运行在 Kubernetes 集群内部的 动态准入控制器(Dynamic Admission Controller),它通过拦截资源请求、匹配策略规则并执行相应的 mutate/validate/generate 操作来实现策略即代码。

2.1 Admission Controller 模式:Kubernetes 请求拦截点

Kubernetes API Server 在处理任何资源请求(create/update/delete)时,会依次经过一系列内置和动态注册的 Admission Controller。Kyverno 利用的就是这一机制,将自己注册为 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。

关键概念:Admission Controller 是 API Server 与 etcd 之间的最后一道防线。请求必须先通过所有准入控制器的检查,才能持久化到 etcd。Kyverno 在这一环节执行策略,确保只有符合规则的资源才能被创建或更新。

Kyverno 的 Webhook 配置(MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration)定义了哪些资源、哪些操作需要被拦截。默认情况下,Kyverno 会拦截所有核心资源(Pod、Service、Deployment 等)的 CREATE 和 UPDATE 操作。

Webhook 类型 作用阶段 Kyverno 行为 失败策略
MutatingWebhook 对象持久化之前,先于验证 执行 mutate 策略(注入 sidecar、添加标签、修改镜像等) Fail(默认)
ValidatingWebhook 对象持久化之前,后于变更 执行 validate 策略(检查安全上下文、资源限制、禁止特权容器等) Fail(默认)
冷启动关联:当 Kyverno Pod 首次启动或 Webhook 配置重新加载时,API Server 会立即将大量请求转发至 Kyverno。如果策略引擎尚未完成初始化(例如规则缓存未预热、CEL 编译环境未就绪),就会产生显著的请求排队和超时,这就是冷启动瓶颈的直接表现。
Admission Controller 请求拦截流程 kubectl / 客户端 API Server MutatingWebhook (Kyverno) ValidatingWebhook (Kyverno) etcd CREATE/UPDATE 1. 拦截 2. 返回 Patch 3. 验证 4. 允许/拒绝 5. 持久化 说明:MutatingWebhook 先于 ValidatingWebhook 执行。Kyverno 同时注册两种 Webhook, 分别处理 mutate 和 validate 策略。冷启动时,两个 Webhook 的响应时间都会显著增加。

2.2 Webhook 生命周期:从注册到故障恢复

Kyverno 的 Webhook 并非静态存在,而是经历一个完整的生命周期。理解这一生命周期对于诊断冷启动问题至关重要。

  1. 注册阶段:Kyverno 启动时,通过 MutatingWebhookConfiguration 和 ValidatingWebhookConfiguration 资源向 API Server 注册自身。注册信息包括 Webhook 服务地址(kyverno-svc.kyverno.svc:443)、匹配规则(resources、operations)、超时时间(默认 10s)、失败策略(Fail/Ignore)等。
  2. 就绪阶段:Kyverno 启动后,会等待内部策略引擎完成初始化(加载所有 ClusterPolicy/Policy、编译 CEL 表达式、预热规则缓存)。只有就绪探针(readinessProbe)通过后,Kyverno 才会开始接收请求。
  3. 运行阶段:API Server 将匹配的请求以 AdmissionReview 对象形式发送给 Kyverno。Kyverno 处理完成后返回 AdmissionResponse,包含 allowed(是否允许)、patch(mutate 操作)、status(拒绝原因)等字段。
  4. 故障/恢复阶段:如果 Kyverno 响应超时或返回错误,API Server 根据失败策略决定是否忽略该 Webhook(Ignore)或拒绝整个请求(Fail)。Kyverno 重启后,Webhook 配置通常保持不变,但需要重新完成就绪阶段。
冷启动陷阱:在 Kyverno 重启后的就绪阶段,如果就绪探针配置过于宽松(例如只检查 TCP 端口而不检查策略引擎是否真正就绪),API Server 可能会在引擎尚未完成初始化时就将请求转发过来,导致大量请求超时或失败。这是冷启动瓶颈的核心成因之一。

2.3 策略引擎核心组件

Kyverno 的策略引擎由多个内部组件协同工作,每个组件在冷启动时都有各自的初始化开销。

组件名称 职责 冷启动开销
Policy Controller 监听 ClusterPolicy/Policy 资源变化,维护策略的声明式状态 中等:需要从 API Server 同步所有策略定义
Rule Cache 将策略规则编译为内部可执行结构,缓存匹配结果 高:首次启动时缓存为空,所有规则需重新编译
CEL Engine 执行 CEL(Common Expression Language)表达式,用于复杂的条件判断 高:CEL 环境初始化、表达式解析和类型检查耗时显著
Webhook Server 处理 HTTP/HTTPS 请求,解析 AdmissionReview,调用引擎执行策略 低:主要开销在网络和序列化
Metrics & Logging 收集策略执行指标(延迟、通过率、拒绝率),输出日志 低:初始化后持续运行
Kyverno 策略引擎核心组件架构 API Server Webhook Server (HTTP Handler) Policy Controller (监听策略变更) Rule Cache (编译 & 缓存) CEL Engine (表达式执行) Metrics & Logging (监控 & 审计) AdmissionReview 查询规则 复杂条件 更新缓存 记录延迟 冷启动瓶颈关键路径: 1. Policy Controller 从 API Server 同步所有策略 → 2. Rule Cache 编译每条规则 → 3. CEL Engine 初始化表达式环境 这三个步骤在首次启动时串行执行,且无法并行处理,导致 Webhook Server 在就绪前无法响应请求。

2.4 组件间的依赖关系与冷启动时序

冷启动瓶颈的本质在于组件间的 串行依赖。以下是 Kyverno 启动时的关键时序:

  1. Pod 启动:容器启动,Webhook Server 开始监听 443 端口。
  2. 策略同步:Policy Controller 通过 List/Watch 从 API Server 获取所有 ClusterPolicy 和 Policy 资源。如果集群中有大量策略(例如 200+),这一步可能耗时 5-15 秒。
  3. 规则编译:Rule Cache 将每条策略的规则(match、exclude、mutate、validate、generate)编译为内部 AST(抽象语法树)。CEL 表达式需要额外的解析和类型检查。
  4. 缓存预热:编译后的规则存入内存缓存。此时缓存为空,所有请求都需要实时编译,直到缓存被填满。
  5. 就绪探针通过:只有上述步骤完成后,readinessProbe 才返回成功,API Server 开始转发请求。
性能数据:在 100 条策略、50 个 CEL 表达式的典型场景下,Kyverno 冷启动时间约为 20-40 秒。在此期间,如果就绪探针配置不当,API Server 可能提前转发请求,导致大量 500 错误和 AdmissionReview 超时。