kubernetes集群工具 kubect 提供了一种强大的数据提取的模式,jsonpath,相对于 yaml 来说,jsonpath 拥有高度的自制提取功能,以及一些更便于提取字段的模式,使得过去 kubernetes 资源信息时更便捷,在本文中将解开 jsonpath 的神秘面纱。
什么是jsonpath
JSONPath 是一种用于查询 JSON 数据结构中特定元素的查询语言。它类似于 XPath 用于 XML 数据的查询。JSONPath 允许您以一种简单而灵活的方式从 JSON 对象中提取数据,而不需要编写复杂的代码来解析 JSON 结构。
JSONPath 使用路径表达式来指定您要检索的 JSON 数据的位置。这些路径表达式类似于文件系统中的路径,但用于导航 JSON 结构。以下是一些常见的 JSONPath 表达式示例:
$
:表示 JSON 根对象。$.store
:表示从根对象中获取名为 “store” 的属性。$.store.book
:表示从根对象中获取 “store” 属性中的 “book” 属性。$.store.book[0]
:表示获取 “store” 属性中的 “book” 属性的第一个元素。$.store.book[?(@.price < 10)]
:表示选择 “store” 属性中的 “book” 属性中价格小于 10 的所有元素。
Function | Description | Example | Result |
---|---|---|---|
text | the plain text | kind is {.kind} | kind is List |
@ | the current object | {@} | the same as input |
. or [] | child operator | {.kind} or {[‘kind’]} | List |
.. | recursive descent | {..name} | 127.0.0.1 127.0.0.2 myself e2e |
* | wildcard. Get all objects | {.items[*].metadata.name} | [127.0.0.1 127.0.0.2] |
[start:end :step] | subscript operator | {.users[0].name} | myself |
[,] | union operator | {.items[*][‘metadata.name’, ‘status.capacity’]} | 127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8] |
?() | filter | {.users[?(@.name==“e2e”)].user.password} | secret |
range, end | iterate list | {range .items[*]}[{.metadata.name}, {.status.capacity}] {end} | [127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] |
“ | quote interpreted string | {range .items[*]}{.metadata.name}{’\t’}{end} | 127.0.0.1 127.0.0.2 |
JSONPath 支持各种操作符和函数,以便更复杂地筛选和操作 JSON 数据。它在 JSON 数据的导航和过滤方面非常强大,通常用于从 JSON 数据中提取所需的信息。
JSONPath 在各种编程语言和工具中都有实现,包括 JavaScript、Python、Java 等,因此您可以根据需要选择适合您项目的工具来使用 JSONPath 查询 JSON 数据。
kubectl中对jsonpath的支持
例如,通常在生产环境中处理 Kubernetes 问题时,您将需要查看数百个节点和数千个 Pod 的信息,例如 Deployment, Pod, Replicat, Service, Secret 等资源信息,但要获取这些类型的资源,通常会使用 kubectl 命令,然而在50%以上的高级场景下,是过滤信息并进行整理。在这种场景下,使用 kubectl + shell 命令进行整理的却没有 jsonpath 来的实在。假设在一个大规模集群中,例如 10 万个 Node 节点,这时如果你想获得一些节点信息,或者 Pod 信息,再或者某些需要循环的条件,这时候多次的请求对你在统计数据上造成的时间成本及频繁请求API都会造成压力,这个时候 jsonpath 的功能就很好的解决了这个问题,通过一次请求,快速循环可以在很短时间内得出结果,并减少了大量请求 kube-apiserver 的压力。
kubectl jsonpath 示例
仅获取某个资源的名称
|
|
获取一个 deployment的 信息
|
|
通常使用 json path 不会获取一个资源的信息,而是获取所有资源的信息,例如获取所有 Pod 的 name
|
|
Tips:jsonpath 的输出是以字符串方式输出,不会携带换行之类的
@ 的用法
@ 表示当前对象,例如 kubectl get pods 这获取的是一个 list 列表,那么 @ 就代表这个 list,例如
|
|
. 和 [] 的用法
. 和 [] 是子操作符,用于获取到列表的元素,返回值也是 list,例如获取 Pod 列表中第一个 Pod,下面是一个 [] 的使用示例,可以获取某个元素
|
|
. 是 [] 的子操作符,可以获取某一个元素下的某个值,与 json 中语法相同,例如获取 Pod 列表中==第一个 Pod 的名称==
|
|
下标操作符 :
下标操作符 “:” 可以视为一个切片,获取列表中某一些元素,语法为 [start:end :step]
例如获取前三个元素的名称
|
|
获取最后两个元素
$ kubectl get pods -n spinnaker -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'
spin-clouddriver-88df48858-dfzkg
spin-deck-5dc8f847b8-m4tbk
spin-echo-69868fd866-nxn8g
spin-front50-54fb4b6d67-jfkds
spin-gate-7b6f4d4566-gdjkd
spin-orca-7765fb5c96-9gmvr
spin-redis-8485df6b88-bgrgm
spin-rosco-6d77f8cb-bf2nj
$ kubectl get pods -n spinnaker -o jsonpath='{range .items[-2:]}{.metadata.name}{"\n"}{end}'
spin-redis-8485df6b88-bgrgm
spin-rosco-6d77f8cb-bf2nj
过滤表达式
如果设置了 limit 参数则打印其名称
|
|
价格大于 10 的 元素的 name
|
|
json path 支持下列过滤操作符参考 [2]
Operator | Description |
---|---|
== | 等于。字符串值必须用单引号(而不是双引号)括起来:[?(@.color=='red')] 。注意:数字与字符串比较的工作方式因播放引擎而异。在 TestEngine 中,1 不等于 “1”。在 ReadyAPI 1.9 及更早版本中,1 等于 “1”。 |
!= | 不等于,字符串值必须用单引号括起来:[?(@.color!='red')] 。 |
> | 大于 |
>= | 大于或等于 |
< | 小于 |
<= | 小于或等于 |
=~ | 匹配 JavaScript 正则表达式。例如,[?(@.description =~ /cat.*/i)] 匹配描述以 cat 开头的项目(不区分大小写)。注意:如果使用 ReadyAPI 1.1 作为播放引擎,则不支持。 |
! | 用于否定过滤器:[?(!@.isbn)] 匹配不具有 isbn 属性的项目。注意:如果使用 ReadyAPI 1.1 作为播放引擎,则不支持。 |
&& | 逻辑与 AND,用于组合多个过滤表达式: [?(@.category=='fiction' && @.price < 10)] |
|| | 逻辑或 OR Logical OR, 用于组合多个过滤表达式: `[?(@.category==‘fiction’ |
in | 检查左侧值是否存在于右侧列表中。类似于 SQL IN 运算符。字符串比较区分大小写。 [?(@.size in ['M', 'L'])] [?('S' in @.sizes)] 注意:仅由 TestEngine 播放引擎支持。 |
nin | 与 in 相反。检查左侧值是否不存在于右侧列表中。字符串比较区分大小写。 [?(@.size nin ['M', 'L'])] [?('S' nin @.sizes)] 注意:仅由 TestEngine 播放引擎支持。 |
contains | 检查字符串是否包含指定的子字符串(区分大小写),或者数组是否包含指定的元素。[?(@.name contains 'Alex')] [?(@.numbers contains 7)] [?('ABCDEF' contains @.character)] 注意:仅由 TestEngine 播放引擎支持。 |
size | 检查数组或字符串是否具有指定的长度。 [?(@.name size 4)] 注意:仅由 TestEngine 播放引擎支持。 |
empty true | 匹配空数组或字符串。 [?(@.name empty true)] 注意:仅由 TestEngine 播放引擎支持。 |
empty false | 匹配非空数组或字符串。 [?(@.name empty false)] 注意:仅由 TestEngine 播放引擎支持。 |
正则表达式
kubectl jsonpath 不支持正则表达式,如果需要使用正则表达式可以使用 jq 替换
例如获取 spin 开头的 Pod 是否配置了 resources
|
|
example
|
|
kubectl example 示例
获取 Pod 为 web 的 Pod name
|
|
过滤一个元素
过滤 Node 地址模式
|
|
过滤元素并只打印想要的属性
|
|
从数组中获取每个元素的单个字段
|
|
换行
jsonpath 在获取元素后,是一个单行字符串,如果需要换行操作可以使用下面示例
|
|
循环并获得多个元素
如果想获取两个元素,可以使用下面示例
|
|
递归
如果想获取一个元素下所有相同名称的字段,可以使用下面示例
递归获取所有 name 字段
|
|
巧用递归简化语句,如果一个元素 (元素名称) 是独有的,那么可以使用递归直接获取到这个元素的值,例如,过去所有 containers
|
|
获取每个 Pod limit 值
|
|
获取容器的 IP
获取单独一个 Pod
|
|
循环获取
|
|
获取所有的 Container ID 和 Pod IP
|
|
获取所有的容器名称和镜像名称
|
|
获取所有状态条件中的类型
|
|
获取 Pod 的 apiversion
|
|
从第一个状态条件开始到最后一个结束,每隔2个获取一次
|
|
Reference
[1] jsonpath
[2] JSONPath Syntax