3. 策略基础:Policy 与 ClusterPolicy 的区别、规则(Rule)结构详解

在 Kyverno 中,策略是声明式准入控制的核心载体。理解 Policy 与 ClusterPolicy 的差异,以及规则(Rule)的内部结构,是编写安全策略的基础。本节将拆解这两个关键概念,并深入规则引擎的构成要素。

3.1 Policy 与 ClusterPolicy:作用域与目标

Kyverno 提供了两种策略资源类型,它们的核心区别在于作用范围和匹配目标。选择哪种类型取决于你希望策略生效的边界。

特性 Policy(命名空间级) ClusterPolicy(集群级)
作用域 仅在其所属的单个命名空间内生效 在整个集群范围内生效,可跨命名空间
匹配资源 只能匹配同一命名空间内的资源 可匹配所有命名空间或特定命名空间的资源
典型用途 租户隔离、团队级安全基线、命名空间专属标签 全局安全基线、Pod 安全标准(PSS)、集群级资源限制
资源名称 使用 kind: Policy 使用 kind: ClusterPolicy
spec 字段 无需 spec.rules 外额外字段 支持 spec.rules 及 spec.background 等集群级配置
实践建议: 当策略需要应用于整个集群(如禁止特权容器)时,使用 ClusterPolicy;当策略仅针对某个团队或项目(如强制特定标签)时,使用命名空间级的 Policy。

3.2 规则(Rule)结构详解

无论是 Policy 还是 ClusterPolicy,其核心逻辑都封装在 spec.rules 数组中。每个规则(Rule)都是一个独立的“匹配-执行”单元。一个策略可以包含多个规则,它们按顺序评估。

一个完整的规则由以下四个核心部分组成:

  1. 名称(name): 规则的唯一标识符,用于日志和审计。
  2. 匹配(match): 定义规则适用的资源条件(必须满足)。
  3. 排除(exclude): 定义规则不适用的资源条件(可选,优先级高于 match)。
  4. 执行动作(validate / mutate / generate / verifyImages): 定义匹配后执行的具体操作。
规则执行逻辑: 一个请求必须满足 match 中的所有条件,且不命中 exclude 中的任何条件,才会触发规则的动作。

3.2.1 匹配(match)与排除(exclude)

match 和 exclude 使用相同的资源描述结构,支持按资源类型、标签选择器、命名空间、用户信息等维度进行筛选。

# 匹配示例:匹配所有命名空间中,标签为 app=web 的 Deployment
match:
  any:
  - resources:
      kinds:
      - Deployment
      selector:
        matchLabels:
          app: web

# 排除示例:排除 kube-system 命名空间中的所有资源
exclude:
  any:
  - resources:
      namespaces:
      - kube-system

3.2.2 执行动作类型

Kyverno 规则支持四种核心动作,覆盖了准入控制的主要场景:

动作类型 关键字 功能描述 典型场景
验证 validate 检查资源是否符合预期,拒绝不符合的请求 强制只读根文件系统、禁止 hostNetwork
变更 mutate 在资源创建/更新时自动修改其字段 自动注入 Sidecar、添加安全上下文
生成 generate 基于源资源创建新资源(如 ConfigMap、Secret) 为每个命名空间生成默认 NetworkPolicy
镜像验证 verifyImages 验证容器镜像的签名和来源 确保只使用经过签名的官方镜像

3.3 规则结构可视化

下图展示了一个典型 Kyverno 规则从匹配到执行的整体流程,帮助理解各组件之间的协作关系。

Kyverno 规则结构流程图 Kyverno 规则(Rule)结构 规则名称 (name) 匹配 (match) 资源类型 / 标签 / 命名空间 / 用户 排除 (exclude) [可选] 优先级高于 match 执行动作 (action) validate mutate generate verifyImages 规则按顺序评估,第一个匹配的规则决定最终动作

3.4 规则编写示例:准入权限变更风险场景

以下是一个针对“配置准入权限变更风险”的 ClusterPolicy 示例。该策略会验证所有 Pod 是否设置了 readOnlyRootFilesystem: true,从而降低容器逃逸风险。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-readonly-rootfs
spec:
  validationFailureAction: Enforce   # 拒绝不符合规则的请求
  background: true                   # 对现有资源进行扫描
  rules:
  - name: check-readonly-rootfs
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "根文件系统必须设置为只读,以防止恶意写入。"
      pattern:
        spec:
          containers:
          - securityContext:
              readOnlyRootFilesystem: true
风险提示: 在编写 mutate 规则时,务必谨慎。错误的变更逻辑可能导致资源无法创建或集群状态异常。建议先在 validationFailureAction: Audit 模式下测试,确认无误后再切换为 Enforce。

3.5 规则评估顺序与优先级

当一个请求命中多个规则时,Kyverno 遵循以下顺序:

  • 先执行 mutate 规则:所有变更规则按策略创建顺序执行,后执行的 mutate 可以覆盖先前的变更。
  • 再执行 validate 规则:验证规则在 mutate 完成后执行,确保最终资源状态符合预期。
  • 最后执行 generate 规则:生成规则通常用于创建附属资源,不影响当前请求的准入决策。

理解这一顺序对于设计复杂的策略组合至关重要,尤其是在需要先注入 Sidecar 再验证安全上下文的场景中。