4. Kyverno 策略语言基础(一):策略结构、match与exclude块、资源选择器

在编写 Kyverno 策略之前,必须理解其核心语言结构。本章将深入剖析策略的两种类型(Policy 与 ClusterPolicy)、关键的匹配与排除逻辑,以及资源选择器的完整配置方法。掌握这些基础,是构建自动化安全基线核验的起点。

4.1 策略结构:Policy vs ClusterPolicy

Kyverno 策略分为两种作用域:Policy(命名空间级)和 ClusterPolicy(集群级)。它们的 YAML 结构几乎相同,但 spec 下的 rules 数组是核心执行单元。

特性 Policy ClusterPolicy
作用范围 仅作用于指定命名空间 作用于整个集群(所有命名空间)
API 版本 kyverno.io/v1 kyverno.io/v1
Kind Policy ClusterPolicy
典型用途 租户隔离、命名空间级安全基线 全局准入控制、集群安全基线、合规审计
资源选择器 支持 namespaceSelector + objectSelector 支持 namespaceSelector + objectSelector
最佳实践: 对于跨命名空间的全局安全基线(如“禁止特权容器”),始终使用 ClusterPolicy;对于仅适用于特定业务团队的策略(如“必须包含 team-label”),使用命名空间级的 Policy。

4.2 match 与 exclude 块:策略的“门卫”

每个规则(rule)都包含 match 和可选的 exclude 块。它们决定了策略何时生效、跳过哪些资源。两者都使用 ResourceDescription 结构来描述资源特征。

4.2.1 match 块:定义策略的目标

match 块是规则的必要条件。只有资源满足 match 中的所有条件时,规则才会被触发。支持按资源类型、标签、命名空间、注解等维度匹配。

# match 块示例:匹配所有包含 "app=web" 标签的 Pod
match:
  any:
  - resources:
      kinds:
      - Pod
      selector:
        matchLabels:
          app: web

4.2.2 exclude 块:排除特定资源

exclude 块用于豁免某些资源。当资源同时满足 match 和 exclude 条件时,exclude 优先级更高,规则不会执行。这在排除系统组件或调试 Pod 时非常有用。

# exclude 块示例:排除 kube-system 命名空间中的所有资源
exclude:
  any:
  - resources:
      namespaces:
      - kube-system
注意: match 和 exclude 都支持 any 和 all 逻辑运算符。any 表示满足任一条件即生效;all 表示必须满足所有条件。从 Kyverno 1.7 开始推荐使用 any 和 all 替代旧的数组写法。

4.3 资源选择器(ResourceDescription)

ResourceDescription 是 match/exclude 块中用于描述目标资源的核心数据结构。它提供了多维度的选择能力,包括:

  • kinds:资源类型列表(如 Pod、Deployment、Service)
  • names:资源名称列表(精确匹配)
  • namespaces:命名空间列表(精确匹配)
  • selector:标签选择器(支持 matchLabels 和 matchExpressions)
  • namespaceSelector:命名空间标签选择器(用于跨命名空间匹配)
  • annotations:注解匹配
# 完整的 ResourceDescription 示例
match:
  any:
  - resources:
      kinds:
      - Pod
      - Deployment
      namespaces:
      - production
      - staging
      selector:
        matchLabels:
          app: frontend
        matchExpressions:
        - key: version
          operator: In
          values:
          - v1
          - v2
      namespaceSelector:
        matchLabels:
          environment: production

4.4 策略结构全景图

下面的 SVG 图展示了 Kyverno 策略的完整结构,从顶层 Kind 到底层规则执行流程,帮助理解 match/exclude 与资源选择器的关系。

Kyverno 策略结构全景图 Kyverno 策略结构全景图 Policy / ClusterPolicy spec rules[] match exclude validate/mutate/generate ResourceDescription ResourceDescription kinds selector namespaces namespaceSelector 说明:match 和 exclude 块共享相同的 ResourceDescription 结构,支持 kinds、selector、namespaces、namespaceSelector 等字段。 exclude 优先级高于 match,当资源同时匹配两者时,规则不会执行。

4.5 实战对比:Policy 与 ClusterPolicy 的 YAML 差异

以下两个代码块展示了相同规则在 Policy 和 ClusterPolicy 中的写法差异。注意 kind 字段和 spec.rules 的完全一致性。

# Policy 示例:仅作用于 production 命名空间
apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: require-readonly-rootfs
  namespace: production
spec:
  rules:
  - name: check-readonly-rootfs
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "root filesystem must be read-only"
      pattern:
        spec:
          securityContext:
            readOnlyRootFilesystem: true
# ClusterPolicy 示例:作用于整个集群
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-readonly-rootfs
spec:
  rules:
  - name: check-readonly-rootfs
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      message: "root filesystem must be read-only"
      pattern:
        spec:
          securityContext:
            readOnlyRootFilesystem: true
关键差异: Policy 需要 namespace 字段且规则仅在该命名空间生效;ClusterPolicy 不需要 namespace,规则全局生效。在 match/exclude 块中,两者使用完全相同的 ResourceDescription 语法。

4.6 资源选择器的高级用法:namespaceSelector

namespaceSelector 是 ResourceDescription 中最强大的字段之一。它允许策略根据命名空间的标签来动态选择目标,而不是硬编码命名空间名称。这在多租户环境和动态命名空间场景中至关重要。

# 使用 namespaceSelector 匹配所有带有 "security-level=high" 标签的命名空间
match:
  any:
  - resources:
      kinds:
      - Pod
      namespaceSelector:
        matchLabels:
          security-level: high
选择器类型 匹配对象 典型场景
selector 资源本身的标签 匹配特定应用(如 app=nginx)
namespaceSelector 命名空间的标签 匹配所有生产环境命名空间
namespaces 命名空间名称列表 精确匹配已知命名空间
kinds 资源类型 匹配 Pod、Deployment 等

4.7 本章小结

  • Policy vs ClusterPolicy:作用域不同,结构相同;全局基线用 ClusterPolicy,租户隔离用 Policy。
  • match 与 exclude:match 定义目标,exclude 定义豁免;exclude 优先级更高。
  • ResourceDescription:统一的资源选择器,支持 kinds、namespaces、selector、namespaceSelector 等多维度匹配。
  • namespaceSelector:动态命名空间选择能力,是构建可扩展安全基线的关键。