4. Kyverno 策略语言入门:YAML 策略结构、资源描述符、操作符、变量与 JMESPath 表达式
Kyverno 策略使用标准的 Kubernetes YAML 清单编写,其核心设计理念是“策略即代码”。理解策略语言的构成要素——从顶层结构到字段匹配、条件判断与数据变换——是编写可靠策略的基础。本章将系统拆解一个 Kyverno 策略的完整骨架,并深入每个关键组件。
4.1 策略 YAML 顶层结构
一个 Kyverno 策略资源(ClusterPolicy 或 Policy)遵循 Kubernetes 资源模型,其顶层字段如下表所示:
| 字段 | 类型 | 说明 |
|---|---|---|
apiVersion |
string | 固定为 kyverno.io/v1 |
kind |
string | ClusterPolicy(集群范围)或 Policy(命名空间范围) |
metadata |
ObjectMeta | 包含 name 和可选的 annotations |
spec |
Spec | 策略核心定义,包含 rules 数组 |
以下是一个最小化的策略骨架示例:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-labels
spec:
validationFailureAction: Enforce
rules:
- name: check-required-labels
match:
resources:
kinds:
- Pod
validate:
message: "标签 'app.kubernetes.io/name' 是必需的。"
pattern:
metadata:
labels:
app.kubernetes.io/name: "?*"
validationFailureAction 字段控制策略的生效模式:Enforce 直接拒绝违规请求;Audit 仅生成报告,不阻塞操作。在开发阶段建议先使用 Audit 模式。
4.2 资源描述符:match 与 exclude
每个规则通过 match 和 exclude 字段定义其作用范围。资源描述符支持按 kinds、names、namespaces、selector(标签选择器)以及 annotations 进行筛选。
资源描述符的核心匹配维度:
- kinds:匹配资源类型,支持核心 API 组(如
Pod)和自定义资源(如Deployment)。 - names:精确匹配资源名称。
- namespaces:匹配资源所在的命名空间。
- selector:使用标签选择器(
matchLabels/matchExpressions)进行语义匹配。 - annotations:匹配注解键值对。
rules:
- name: match-example
match:
resources:
kinds:
- Deployment
- StatefulSet
namespaces:
- production
selector:
matchLabels:
environment: prod
exclude:
resources:
names:
- system-critical-deploy
4.3 操作符:条件判断的基石
Kyverno 在 validate 和 mutate 中支持多种操作符,用于定义字段值与预期条件的比较关系。操作符分为标量比较和集合比较两类。
| 操作符 | 类型 | 示例 | 说明 |
|---|---|---|---|
= |
标量 | replicas: 3 |
精确相等(默认操作符) |
!= |
标量 | hostPID: false |
不等于 |
> |
标量 | spec.replicas > 1 |
大于(数值比较) |
< |
标量 | spec.replicas < 10 |
小于(数值比较) |
>= |
标量 | spec.replicas >= 2 |
大于等于 |
<= |
标量 | spec.replicas <= 5 |
小于等于 |
in |
集合 | tier in ["frontend","backend"] |
值在给定集合中 |
not in |
集合 | tier not in ["cache","queue"] |
值不在给定集合中 |
pattern 中使用操作符时,= 可以省略不写。例如 replicas: 3 等价于 replicas: =3。集合操作符 in 和 not in 常用于枚举值校验,如环境标签、安全上下文字段。
4.4 变量与 JMESPath 表达式
Kyverno 支持在策略中使用变量来引用请求对象(request.object)、旧对象(request.oldObject)、用户信息(request.userInfo)以及服务账号等上下文数据。变量通过 $() 语法嵌入,并可以结合 JMESPath 表达式进行数据提取与变换。
变量引用路径示例:
$(request.object.metadata.name)—— 获取被处理资源的名称。$(request.object.spec.containers[?name=="main"].image | [0])—— 获取名为 "main" 的容器镜像。$(request.object.metadata.labels."app.kubernetes.io/name")—— 获取包含特殊字符的标签值。
JMESPath 是 Kyverno 内置的查询语言,用于对 JSON/YAML 数据进行过滤、投影和变换。常用函数包括:
| 函数 | 说明 | 示例 |
|---|---|---|
contains() |
检查数组或字符串是否包含某元素 | contains(containers[*].name, "sidecar") |
length() |
返回数组或字符串长度 | length(containers) > 1 |
split() |
按分隔符拆分字符串 | split(image, ":")[1] |
to_string() |
将数值或布尔值转为字符串 | to_string(replicas) |
join() |
将数组元素拼接为字符串 | join(", ", volumes[*].name) |
以下是一个使用变量和 JMESPath 的 mutate 策略示例,自动为 Pod 添加基于命名空间的标签:
rules:
- name: auto-label-namespace
match:
resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
metadata:
labels:
namespace: "{{ request.namespace }}"
environment: "{{ request.object.metadata.labels.\"env\" || 'unknown' }}"
/、-、.)需要使用双引号包裹,并在 JMESPath 中转义。例如 labels."app.kubernetes.io/name"。在 deny 规则中使用变量时,务必确保变量在运行时能被正确解析,否则可能导致策略评估失败。
4.5 策略语言组件关系图
下图展示了 Kyverno 策略语言各组件之间的层级关系与数据流向:
4.6 综合示例:准入控制策略
以下是一个完整的 ClusterPolicy,综合运用了资源描述符、操作符、变量和 JMESPath,用于强制要求所有 Deployment 必须设置资源限制,且副本数不能为 0:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deployment-resource-guard
spec:
validationFailureAction: Enforce
rules:
- name: require-resource-limits
match:
resources:
kinds:
- Deployment
validate:
message: "Deployment 必须设置 CPU 和内存的 limits。"
pattern:
spec:
template:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"
- name: reject-zero-replicas
match:
resources:
kinds:
- Deployment
validate:
message: "Deployment 的 replicas 不能为 0。"
deny:
conditions:
any:
- key: "{{ request.object.spec.replicas }}"
operator: Equals
value: 0
- name: enforce-min-replicas
match:
resources:
kinds:
- Deployment
selector:
matchLabels:
critical: "true"
validate:
message: "关键 Deployment 的 replicas 必须大于等于 2。"
deny:
conditions:
any:
- key: "{{ request.object.spec.replicas }}"
operator: LessThan
value: 2
pattern 和通配符 ?* 确保资源限制字段存在且非空;第二个规则使用 deny 条件和 Equals 操作符拒绝副本数为 0 的请求;第三个规则结合标签选择器与 LessThan 操作符,对标记为 critical: "true" 的 Deployment 实施更严格的副本数下限。