大家好!这里是 Kubernetes 策略的炼金术士,Kyverno 大师系列课程的第六讲。🧙♂️
上次我们学习了赋予策略智能的“变量”和“ConfigMap 引用”技术。但是,如果获取的数据过于复杂,或者我只想挑选出我想要的部分,该怎么办呢?
这时,救星就登场了,它就是 JMESPath。Kyverno 自由处理数据的核心引擎 JMESPath,从基础到实战应用,让我们在 10 分钟内完美掌握它!🚀

🏗️ 1. 什么是 JMESPath?
JMESPath(詹姆斯路径)是一种用于从 JSON 文档中提取和处理数据的查询语言。由于 Kubernetes 的所有资源最终都以 JSON(或 YAML)结构组成,因此 Kyverno 使用 JMESPath 从复杂的资源信息中精确地提取所需数据。
- 比喻: 这就像在一个巨大的图书馆(JSON 数据)中,根据特定类型(查询条件)挑选书籍,并制作出精美的摘要(结果值)的过程。
🔍 2. JMESPath 的基本语法(打好基础)
我们先来学习最常用的 4 种核心语法。
① 点表示法 (Identifier) – .
沿着数据的层次结构深入。
- 数据: {“metadata”: {“name”: “my-pod”}}
- 查询: metadata.name → 结果: “my-pod”
② 列表提取 (Index & Flatten) – [ ]
从数组(Array)形式的数据中获取或展开特定元素。
- 数据: {“containers”: [{“name”: “nginx”}, {“name”: “sidecar”}]}
- 查询: containers[0].name → 结果: “nginx”
- 查询: containers[*].name → 结果: [“nginx”, “sidecar”]
③ 过滤 (Filter) – [? … ]
只选择满足特定条件的数据。
- 查询: containers[?name==’nginx’]
④ 管道 (Pipe) – |
将前一个结果作为下一个查询的输入。(连续加工!)
🛠️ 3. Kyverno 策略内数据提取原理
Kyverno 在策略内使用 {{ … }} 双大括号来执行 JMESPath。
实战示例 1:提取镜像标签
当你想从容器镜像地址 (nginx:1.21) 中只获取版本信息时:
YAML
# 查询: request.object.spec.containers[0].image | split(@, ':') | [1]
# @ 表示当前数据,通过 ':' 分割并获取第二个值(索引 1)。
实战示例 2:复杂条件验证 (JMESPath 应用)
当你想验证服务的所有端口都不是 8080 时:
YAML
validate:
message: "Port 8080 is strictly forbidden!"
deny:
conditions:
all:
- key: 8080
operator: In
value: "{{ request.object.spec.ports[*].port }}" # 提取所有端口号作为列表
🧪 4. Kyverno 独有的特殊 JMESPath 函数
除了标准的 JMESPath,Kyverno 还提供了对 Kubernetes 运维有用的专用函数。
- split: 将字符串按特定字符分割。 split(‘a/b/c’, ‘/’)
- to_upper / to_lower: 大小写转换
- length: 返回数组或字符串的长度
- contains: 检查是否包含特定值
🚀 5. 运维人员的实战技巧 (Best Practices)
- 为数据缺失做准备: 像 {{ request.object.metadata.labels.env || ‘default’ }} 这样使用 || 运算符设置默认值,可以防止错误。
- 利用官方测试网站: 在 jmespath.org 上提前练习,看看你的查询是否能正确解析复杂的 JSON 数据。
- 利用 Kyverno CLI: 在部署策略之前,养成使用 `kyverno jp` 命令在本地预先检查查询结果的习惯。
- 保持可读性: 过多使用管道 (|) 会使策略难以阅读。最好在 `context` 部分将复杂逻辑预先定义为变量。
💻 JMESPath 实战综合示例:镜像标签和安全上下文验证
此策略利用 JMESPath 展示了高级逻辑,用于 1) 提取所有容器镜像的标签并验证特定值,以及 2) 检查是否缺少特定的安全设置。
YAML
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: jmespath-advanced-validation
annotations:
policies.kyverno.io/title: "Advanced Data Extraction with JMESPath"
policies.kyverno.io/description: "Using JMESPath to audit image tags and security contexts."
spec:
validationFailureAction: Audit
background: true
rules:
- name: validate-container-data
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Security violation: Check image tags or security settings."
deny:
conditions:
all:
# 1. 使用 JMESPath 提取所有容器的镜像标签,并检查是否包含 'latest'
- key: "latest"
operator: In
value: "{{ request.object.spec.containers[*].image | map(&split(@, ':') | [1], @) }}"
# 2. 检查所有容器中是否有任何一个 'allowPrivilegeEscalation' 为 true
- key: true
operator: AnyIn
value: "{{ request.object.spec.containers[*].securityContext.allowPrivilegeEscalation || [false] }}"
🔍 JMESPath 查询详细解析 (How it works?)
我们将逐步分析上述策略中使用的复杂查询是如何处理数据的。
1️⃣ 提取镜像标签列表 🏷️
request.object.spec.containers[*].image | map(&split(@, ‘:’) | [1], @)
- containers[*].image: 将所有容器的镜像字符串作为数组获取。(例如:[“nginx:latest”, “redis:6.2”])
- map(…): 对数组的每个元素执行命令。
- split(@, ‘:’) | [1]: 将每个镜像字符串按 : 分割,并获取其中第二个值(索引 1),即标签。
- 最终结果: 生成一个干净的标签列表,如 [“latest”, “6.2”]。
2️⃣ 安全设置默认值处理 🛡️
request.object.spec.containers[*].securityContext.allowPrivilegeEscalation || [false]
- || [false]: 如果用户完全没有设置 `securityContext` 导致数据为 null,则不抛出错误,而是返回默认值 [false],以确保策略验证稳定进行。
🚀 通过此策略可以学到什么?
- 数组处理能力: 使用 [*] 和 map() 可以一次性验证所有容器,无论是一个还是十个。
- 数据加工技术: 学习如何不直接使用原始数据 (nginx:latest),而是只截取所需部分 (latest) 进行比较。
- 异常预防设计: 通过 || 运算符,学习如何在数据缺失(可选字段)的情况下,使策略平稳运行的技巧。
🌟 总结
今天,我们了解了 Kyverno 幕后引擎 JMESPath 的基础知识和数据提取原理。
熟练掌握 JMESPath 后,您将能够超越简单地阻止资源,成为一名高级策略设计者,能够“分析用户请求数据的特定模式以进行修改或拒绝”。🛠️
Kubernetes YAML 固然复杂,但有了 JMESPath 这把镊子,就无所畏惧了。
如有疑问,请在评论区留言!😊
发表回复