4. Kyverno 策略引擎架构:准入控制 Webhook、策略执行流程、匹配与排除逻辑
Kyverno 作为 Kubernetes 原生的策略引擎,其核心架构围绕 动态准入控制 Webhook 构建。理解其内部组件协作、策略执行的生命周期以及灵活的匹配/排除机制,是编写高效、安全策略的基础。本章将深入剖析 Kyverno 的运行时架构,从请求拦截到策略评估的完整链路。
4.1 核心架构组件与准入控制 Webhook
Kyverno 以 Deployment 形式运行在集群内,通过注册 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook 来拦截所有匹配的 API 请求。其架构主要包含以下组件:
| 组件 | 职责 | 说明 |
|---|---|---|
| Webhook Server | 接收 kube-apiserver 转发的准入请求 | 监听 9443 端口,处理 Mutating 和 Validating 两种请求 |
| Policy Controller | 管理策略的存储、缓存与状态同步 | 监听 ClusterPolicy / Policy 资源变化,维护策略规则索引 |
| Engine | 执行策略匹配、变量替换与条件评估 | 核心执行单元,处理 match/exclude 逻辑与 validate/mutate/generate 动作 |
| Cache | 缓存已处理的策略结果与集群状态 | 提升性能,避免重复计算,支持背景扫描(Background Scan) |
| Metrics & Reporting | 暴露 Prometheus 指标与策略执行报告 | 提供策略命中率、执行延迟、违规计数等可观测性数据 |
架构要点: Kyverno 的 Webhook Server 是同步阻塞的,kube-apiserver 会等待其返回响应。因此,策略引擎的性能和稳定性直接影响集群 API 的响应延迟。建议为 Kyverno 设置 PodAntiAffinity 和 资源配额,避免单点故障和资源争抢。
4.2 策略执行流程:从请求到响应
当一个资源请求(如创建 Pod)到达 kube-apiserver 时,Kyverno 的策略执行流程分为以下 6 个阶段:
- 请求拦截:kube-apiserver 根据 Webhook 配置的 rules(资源、操作、API 组)判断是否将请求转发给 Kyverno。
- 策略匹配:Webhook Server 将请求中的资源对象与所有已启用的 ClusterPolicy / Policy 进行 match 条件匹配。
- 变量解析:对于匹配的策略,Engine 解析规则中的变量(如
{{ request.object.metadata.name }}、{{ images.containers[*].name }})。 - 规则执行:按规则类型依次执行:
- Mutating:先执行 mutate 规则(如注入 Sidecar、添加标签),生成 JSON Patch。
- Validating:再执行 validate 规则(如检查特权容器、强制只读根文件系统)。
- Generate:对于创建请求,检查是否需要生成关联资源(如自动创建 NetworkPolicy)。
- 响应聚合:将所有规则的执行结果(允许/拒绝/补丁)聚合成一个 AdmissionResponse。
- 返回结果:Webhook Server 将响应返回给 kube-apiserver,apiserver 根据结果决定是否允许请求继续。
执行顺序关键点: 在同一个策略中,mutate 规则总是先于 validate 规则执行。这意味着 validate 规则可以检查 mutate 规则修改后的最终状态。例如,先通过 mutate 注入一个只读 Sidecar,再通过 validate 验证最终 Pod 的 securityContext 是否符合基线。
4.3 匹配与排除逻辑:精准控制策略作用域
Kyverno 通过 match 和 exclude 字段实现精细的资源选择。这两个字段支持多种匹配维度,且 exclude 优先级高于 match:即使资源匹配了 match 条件,如果也匹配了 exclude 条件,则策略不会执行。
4.3.1 匹配维度与语法
| 匹配维度 | 字段路径 | 示例 | 说明 |
|---|---|---|---|
| 资源类型 | resources.kinds |
["Pod", "Deployment"] |
支持核心 API 组和自定义资源(CRD) |
| 资源名称 | resources.names |
["nginx-*", "app-*"] |
支持通配符 * 和 ? |
| 命名空间 | resources.namespaces |
["production", "staging"] |
仅对命名空间作用域的资源有效 |
| 标签选择器 | resources.selector |
matchLabels: { app: frontend } |
支持 matchLabels 和 matchExpressions |
| 注解选择器 | resources.annotations |
matchAnnotations: { "security/scan": "passed" } |
基于注解键值对匹配 |
| 用户信息 | subjects |
kind: User, name: admin |
匹配发起请求的用户、组或 ServiceAccount |
4.3.2 匹配与排除的优先级规则
- 同一策略内:
exclude的匹配条件与match独立评估。如果资源同时满足 match 和 exclude,则 exclude 生效,策略跳过。 - 多策略间:每个策略独立评估。一个资源可能被多个策略匹配,每个策略都会执行其规则。
- 全局排除:Kyverno 支持在 Webhook 配置级别排除特定命名空间(如
kube-system)或资源类型,避免影响系统组件。
常见陷阱: 在编写排除逻辑时,注意
resources.namespaces 和 resources.selector 是 与(AND) 关系。例如,同时指定 namespaces: ["production"] 和 selector: { matchLabels: { app: frontend } },则只有 production 命名空间中且标签为 app=frontend 的资源才会被匹配。如果需要“或”逻辑,需要拆分为多个规则。
4.3.3 实战示例:精细控制策略作用域
以下策略演示了如何结合 match 和 exclude 实现“对 production 命名空间中所有非 kube-system 的 Pod 强制执行只读根文件系统”:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-readonly-rootfs
spec:
validationFailureAction: Enforce
rules:
- name: check-readonly-rootfs
match:
resources:
kinds:
- Pod
namespaces:
- production
exclude:
resources:
namespaces:
- kube-system
names:
- "*-init-*"
validate:
message: "所有 production 命名空间的容器必须设置 readOnlyRootFilesystem: true"
pattern:
spec:
containers:
- securityContext:
readOnlyRootFilesystem: true
匹配逻辑拆解:
- match:匹配
kind=Pod且namespace=production的资源。 - exclude:从匹配结果中排除
namespace=kube-system或名称以-init-结尾的 Pod。 - 最终效果:策略仅作用于 production 命名空间中非 kube-system 且非 init 容器的 Pod。
4.4 策略执行模式:Enforce 与 Audit
Kyverno 支持两种执行模式,通过 validationFailureAction 字段控制:
| 模式 | 行为 | 适用场景 |
|---|---|---|
| Enforce | 违反策略时 拒绝 请求,阻止资源创建/更新 | 生产环境安全基线、合规性强制要求 |
| Audit | 违反策略时 仅记录 违规事件,不阻止请求 | 策略测试、灰度验证、存量资源评估 |
推荐实践: 对于新的安全基线策略,建议先使用
Audit 模式运行一段时间,通过 kubectl get policyreport 查看违规报告,确认不会影响现有业务后再切换为 Enforce 模式。这可以避免因策略误判导致的生产事故。