kubectl技巧之通过jsonpath截取属性 - 周国通 - 博客园


系列目录

前面一节我们介绍了使用 go-template 截取属性, go-template 功能非常强大, 可以定义变量, 使用流程控制等, 这是 jsonpath 所不具备的. 然而, jsonpth 使用的时候更为灵活. 通过上一节我们发现, 我们想要找到某个具体属性, 必须从最外层一层层向内找到具体属性, 这对于嵌套层次非常深的 yaml 对象来说操作是非常繁琐的. 而使用 jsonpath 只需要知道顶层对象, 然后可以省略中间的对象, 递归查找直接找到我们想要的属性, 这在很多时候对我们在不清楚对象的层次但是清楚知道某个属性名称的时候获取这个属性的值是非常有帮助的. 并且 jsonpath 可以使用下标索引数组对象, 这在实际工作中也是非常有帮助的 (比如虽然 pod 里可以包含多个 containers, 但是很多时候一个 pod 里只有一个 container, 使用 go-template 我们为了找到这个对象需要写一个遍历表达式, 而使用 jsonpath 可以直接取第 0 个对象, 省去了写循环的麻烦), 还有一点很重要的是 jsonpath 是一个标准, 这对于熟悉 jsonpath 的开发者来说使用起来方便很多.

jsonpath 模板使用一对花括号 ({}) 把 jsonpath 表达式包含在里面 (go-template是双花括号). 除了标准 jsonpath 语法外, kubernetes jsonpath 模板还额外支持以下语法:

  • 用 “” 双引号来引用 JSONPath 表达式中的文本
  • 使用rangeend来遍历集合 (这点和 go-template 类似)
  • 使用负数来从尾部索引集合

$ 操作符是可选的因为表达式默认总是从根节点开始选择
对象通过它的String()函数打印输出出来

假如有以下 JSON 字符串

{
  "kind": "List",
  "items":[
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.1"},
      "status":{
        "capacity":{"cpu":"4"},
        "addresses":[{"type": "LegacyHostIP", "address":"127.0.0.1"}]
      }
    },
    {
      "kind":"None",
      "metadata":{"name":"127.0.0.2"},
      "status":{
        "capacity":{"cpu":"8"},
        "addresses":[
          {"type": "LegacyHostIP", "address":"127.0.0.2"},
          {"type": "another", "address":"127.0.0.3"}
        ]
      }
    }
  ],
  "users":[
    {
      "name": "myself",
      "user": {}
    },
    {
      "name": "e2e",
      "user": {"username": "admin", "password": "secret"}
    }
  ]
}
FunctionDescriptionExampleResult
textthe plain textkind 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, enditerate 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 示例

kubectl get pods -o json
kubectl get pods -o=jsonpath='{@}'
kubectl get pods -o=jsonpath='{.items[0]}'
kubectl get pods -o=jsonpath='{.items[0].metadata.name}'
kubectl get pods -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.startTime}{"\n"}{end}'

如果对象是集合类型, 需要使用 range 关键字开始, 以 end 关键字结果, 同前面一节 go-template 类似.

我们通过以下示例来看如何通过 jsonpath 简单地获取到容器所在节点名称

[centos@k8s-master ~]$ kubectl get po consul-0 -ojsonpath='{..nodeName}'
k8s-node1
[centos@k8s-master ~]$

当然以上也可以通过 grep 来获取到同样的信息, 并且对于很多熟悉 linux 命令的童鞋来说更为方便, 如果仅仅是查看. grep 确实更为方便, 但是通过 jsonpath 是准确地获取到了一个属性的值, 而 grep 则是截取的包含这个关键字的一行, 如果我们要把获取的值作为下一个命令的的输入值时, 通过 grep 获取的结果往往是需要处理的. 例如通过 grep 获取到的结果如下

"k8s-node1",[centos@k8s-master ~]$ kubectl get po consul-0 -ojson|grep nodeName
        "nodeName": "k8s-node1",

这里想要准备的获取结果, 产生要截取第二列值, 然后再去掉引号, 操作起来不如 jsonpath 方便. 尤其在不同环境如果输出的格式不一样的话, 通过字符串截取得到的结果可能是错误的.
https://www.cnblogs.com/tylerzhou/p/11049050.html


文章作者:   Joey Wang
版权声明:   本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Joey Wang !
 上一篇
Running Spring Boot apps as GraalVM Native Images - codecentric AG Blog Running Spring Boot apps as GraalVM Native Images - codecentric AG Blog
All those Micronaut, Quarkus.io & Co. frameworks sound great! But Spring is the undisputed forerunner in Enterprise
2021-09-03 Joey Wang
下一篇 
Git清理commit中历史提交的大文件 - 云+社区 - 腾讯云 Git清理commit中历史提交的大文件 - 云+社区 - 腾讯云
文章时间:2019 年 11 月 10 日 14:02:59 解决问题:清理 Git 中比较大的文件,主要针对历史记录进行清理 ps:因为 Git 可以恢复版本,所有历史提交过的较大的文件,也会被保存下来,所以我们需要……xx 嗯,你懂的
2021-08-19 Joey Wang
  目录