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 与资源选择器的关系。
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
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:动态命名空间选择能力,是构建可扩展安全基线的关键。