环境:k8s 1.22.17 centos7.9
本篇讲解kubectl get
命令的输出格式化,即-o jsonpath=
参数的使用格式。
-o jsonpath= 与 -ojsonpath= 与 -o=jsonpath= 与 --output=jsonpath=
四者等价,写法不一样而已。
官网:https://kubernetes.io/zh-cn/docs/reference/kubectl/jsonpath/
jsonpath是一种用于从json数据中提取数据的查询语言,通过jsonpath表达式从json数据中选择和提取数据,jsonpath表达式就是由一系列操作符和表达式组成的。
#jsonpath表达式的基本操作符
$ 根节点
@ 当前节点,一般用于子表达式或者过滤表达式
. 或 [] 用于连接父节点,.点要求value本身是一个json对象才可以进行往下连接。
[] 也可以用于连接父节点,语法:$["data"]["studnet"]、$["name"] 等价于 $.name
点示例:
$.name则表示提取根节点下的name节点的值
$.data.student则表示提取根节点下的data节点下的student数组的值(student假设是一个数组的话则返回整个数组)
$.data.student[0]则表示提取根节点下的data节点下的student数组中的第1个值(student是一个数组的话则返回整个数组中第1个值)
$.data.student[0].name则表示提取根节点下的data节点下的student数组中的第1个值的name值
*号 通配符星号表示所有,如: $.* 表示提取根节点下的所有节点的值,$.data.student[*].name则表示提取根节点下的data节点
下的student数组中的所有节点的name值
.. 表示深层递归,我们知道$.name表示提取根节点下的name节点的值,而$..name则表示提取根节点及其下所有子节点中的name节点的
值(递归提取),$.data..name则表示提取data节点及其data节点下边的所有节点的name节点的值(递归提取data节点所有name节点值)。
针对数组节点的处理:
一般来说,整对数组节点的提取,我们主要采用的方式有这么几种:下标提取、过滤表达式。
下标提取又可以有3个方式,如下:
提取单个元素,语法:array[index] 表示提提数组中指定的index下标的值
枚举方式,语法:array[index1,index2,index3] 表示同时提取数组中的多个index下标元素值,使用逗号分隔index即可
分片,语法: array[start:end] 表示提取数组中半闭半开区间的值,即包含start,不包含end的下标元素值,start可以省略,省略
时默认是0,end亦可省略,省略时默认是最后一个index下标
下标提取示例:
$.data.student[0] 提取student数组中第1个元素的值
$.data.student[1] 提取student数组中第2个元素的值
$.data.student[0,3] 提取student数组中第1个元素和第4个元素的值
$.data.student[*] 使用*号通配符表示提取student数组中全部元素的值
$.data.student[0:3] 提取student数组中[0,3)元素的值,换句话说就是012元素的值,不含元素3的值
$.data.student[:3] 省略start,start默认是0,则等价于$.data.student[0:3]
$.data.student[1:] 省略end,则表示到最后一个index,即提取数组中从下标1开始到最后一个元素的值
过滤表达式:对于复杂的业务需求,可以通过过滤表达式对数组中的元素进行过滤。
==、!=、<、<=、>、>= 等于、不等于、小于、小于等于、大于、大于等于
=~ 正则匹配
in 存在于
nin 不存在于
subsetof 子集
|| 或
&& 与
基本格式:$.data.studnet[?(表达式)]
@表示正在处理的当前节点
数组中过滤表达式示例:
$.data.studnet[?(@.isVIP==true)] 提取data节点下student节点下isVIP=true的元素
$.data.studnet[?(@.isVIP==true)].name 提取data节点下student节点下isVIP=true的元素的name值
$.data.studnet[?(@.age>=20)] 提取data节点下student节点下年龄大于20的元素
$.data.studnet[?(@.age>=20 && @.sex=="man")] 提取data节点下student节点下年龄大于等于20并且性别是男生的元素
$.data.studnet[?(@.age==20 || @.age==25 )] 等价于 $.data.studnet[?(@.age in [20,25])]
$.data.studnet[?(@.age nin [20,25])]
Usage:
kubectl get
[(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-
file=...|jsonpath=...|jsonpath-file=...]
(TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags] [options]
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@master examples]#
#从kubectl get 命令帮助中可以看到,除了我们经常使用的 -o yaml 、-o json、-o wide 之外,还有一个很好的参数可以帮助我
# 们截取pod的某些字段,即-o jsonpath=
[root@master ~]# vim deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
env: dev
tiar: front
namespace: default
spec:
replicas: 3 #3个副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.7.9
name: nginx-container
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
[root@master ~]# kubectl apply -f deploy-nginx.yaml
[root@master ~]# kubectl -n default get pod -l app=nginx #现在有3个pod了
NAME READY STATUS RESTARTS AGE
nginx-65f6846d8b-gwmjl 1/1 Running 0 3h23m
nginx-65f6846d8b-jpb8d 1/1 Running 0 3h23m
nginx-65f6846d8b-nrprn 1/1 Running 0 3h23m
[root@master ~]#
jq命令是一个实现json格式化的工具,默认的centos源里面没有,需要先安装epel源。
yum install epel-release -y
yum install jq -y
jsonpath模板由 {} 包起来的 jsonpath表达式组成。kubectl 使用 jsonpath表达式来过滤 json对象中的特定字段并格式化输出。
下面是常见的jsonpath表达式:
$表示根节点,$运算符是可选的,因为默认情况下表达式总是从根对象开始。以下讲解的jsonpath示例都默认省略$运算符,请知晓。
-o jsonpath="{$}"
示例:
kubectl get pod -l app=nginx -o jsonpath="{$}"
kubectl get pod -l app=nginx -o jsonpath="{}" #与上面等价
kubectl get pod -l app=nginx -o jsonpath="{$}" | jq . #我们先来看原始输出结果,如下
{
"apiVersion": "v1",
"items": [ #可以看到items是数组,包含有3个值,每个值里面其实就是pod的json清单
{ #这是第一个pod的json格式清单
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
....... #这里省略了
},
"spec": {
....... #这里省略了
},
"status": {
....... #这里省略了
}
},
{ #这是第一个pod的json格式清单
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
.......
},
"spec": {
.......
},
"status": {
.......
}
},
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
.......
},
"spec": {
.......
},
"status": {
.......
}
}
],
"kind": "List", #可以看到jsonpath得到的是一个list列表(即使是一个pod,也是list类型,与pod数据多少无关)
"metadata": {
"resourceVersion": "",
"selfLink": ""
}
}
# -o jsonpath="{.items[0].metadata.name}" 、-o jsonpath="{$.items[0].metadata.name}" 示例
#items是一个数组,所以可以使用[n]下标的形式引用对应的值,数组下标从0开始,可以使用通配符*匹配所有
[root@master ~]# kubectl -n default get pod -l app=nginx -owide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-65f6846d8b-k9kdw 1/1 Running 0 21m 10.233.64.20 master
nginx-65f6846d8b-nrprn 1/1 Running 0 3h47m 10.233.64.17 master
nginx-65f6846d8b-xljt5 1/1 Running 0 21m 10.233.64.21 master
[root@master ~]#
#获取根节点下items数组中第1个元素的metadata节点下的name的值
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[0].metadata.name}"
nginx-65f6846d8b-k9kdw
#获取根节点下items数组中第2个元素的metadata节点下的name的值
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[1].metadata.name}"
nginx-65f6846d8b-nrprn
#获取根节点下items数组中第3个元素的metadata节点下的name的值
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[2].metadata.name}"
nginx-65f6846d8b-xljt5
#获取根节点下items数组中所有元素的metadata节点下的name的值
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[*].metadata.name}"
nginx-65f6846d8b-k9kdw nginx-65f6846d8b-nrprn nginx-65f6846d8b-xljt5
[root@master ~]#
#获取根节点下items数组中所有元素下status节点下的podIP值
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[*].status.podIP}"
10.233.64.20 10.233.64.17 10.233.64.21
[root@master ~]#
[root@master ~]#
#同时获取多个值,使用['n1','n2',..]即可
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{.items[*]['metadata.name','status.podIP']}"
nginx-65f6846d8b-k9kdw nginx-65f6846d8b-nrprn nginx-65f6846d8b-xljt5 10.233.64.20
10.233.64.17 10.233.64.21
[root@master ~]#
range, end 迭代列表
range, end 迭代列表可以进行常量的输出,还可以使用制表符换行符进行格式化,语法格式如下:
语法格式:{range .items[*]}{.metadata.name},{xxx},{xxx} {end}
-o jsonpath="{range .items[*]}{.metadata.name} {end}"
-o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP} {end}"
-o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP}{'\n'}{end}"
#输出容器名字和容器启动时间,并使用制表符换行符进行格式化
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.status.startTime}{'\n'}{end}"
nginx-65f6846d8b-k9kdw 2023-07-12T13:47:56Z
nginx-65f6846d8b-nrprn 2023-07-12T10:22:26Z
nginx-65f6846d8b-xljt5 2023-07-12T13:47:56Z
[root@master ~]#
#{end}前面没有空格,输出结果都连接到一起了
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}{end}"
nginx-65f6846d8b-k9kdwnginx-65f6846d8b-nrprnnginx-65f6846d8b-xljt5[root@master ~]#
#{end}前面加了个空格
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name} {end}"
nginx-65f6846d8b-k9kdw nginx-65f6846d8b-nrprn nginx-65f6846d8b-xljt5 [root@master ~]#
#同时输出容器name和容器IP
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP} {end}"
nginx-65f6846d8b-k9kdw, 10.233.64.20 nginx-65f6846d8b-nrprn, 10.233.64.17 nginx-65f6846d8b-xljt5, 10.233.64.21 [root@master ~]#
#使用换行符美化结果
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP}{'\n'}{end}"
nginx-65f6846d8b-k9kdw, 10.233.64.20
nginx-65f6846d8b-nrprn, 10.233.64.17
nginx-65f6846d8b-xljt5, 10.233.64.21
[root@master ~]#
#输出结果拼接端口号
[root@ceph-1 ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.status.podIP}:6379 {end}"
10.233.64.20:6379 10.233.64.17:6379 10.233.64.21:6379 [root@ceph-1 ~]#
# 下面的命令不会生效
kubectl get pods -o jsonpath='{.items[?(@.metadata.name=~/^test$/)].metadata.name}'
# 下面的命令可以获得所需的结果
kubectl get pods -o json | jq -r '.items[] | select(.metadata.name | test("test-")).spec.containers[].image'
jsonpath模板由 {} 包起来的 jsonpath表达式组成。kubectl 使用 jsonpath表达式来过滤 json字符串中的特定字段并格式化输出。
-o jsonpath=
得到的是一个json字符串list列表,那么就可以通过表达式来过滤 json字符串中的特定字段并格式化输出。
下面是常见的jsonpath表达式:
kubectl get pod -l app=nginx -o jsonpath="{$}" #{$}表示根节点,即输出根节点全部json字符串;
kubectl get pod -l app=nginx -o jsonpath="{}" #$可以省略,与上面等价
kubectl get pod -l app=nginx -o jsonpath="{.items[0].metadata.name}" #获取根节点下items数组中第1个元素metadata节点下的name值
kubectl get pod -l app=nginx -o jsonpath="{.items[*].status.podIP}" #获取根节点下items数组中全部元素status节点下podIP的值
kubectl get pod -l app=nginx -o jsonpath="{.items[*]['metadata.name','status.podIP']}" #同时获取多个值
range, end 迭代列表
range, end 迭代列表可以进行常量的输出,还可以使用制表符换行符进行格式化,语法格式如下:
语法格式:{range .items[*]}{.metadata.name},{xxx},{xxx} {end}
-o jsonpath="{range .items[*]}{.metadata.name} {end}"
-o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP} {end}"
-o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP}{'\n'}{end}"
-o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP}:6379 {end}"
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name} {end}"
nginx-65f6846d8b-k9kdw nginx-65f6846d8b-nrprn nginx-65f6846d8b-xljt5 [root@master ~]#
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP} {end}"
nginx-65f6846d8b-k9kdw, 10.233.64.20 nginx-65f6846d8b-nrprn, 10.233.64.17 nginx-65f6846d8b-xljt5, 10.233.64.21
#使用换行符美化结果
[root@master ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.metadata.name}, {.status.podIP}{'\n'}{end}"
nginx-65f6846d8b-k9kdw, 10.233.64.20
nginx-65f6846d8b-nrprn, 10.233.64.17
nginx-65f6846d8b-xljt5, 10.233.64.21
[root@master ~]#
#输出结果拼接端口号
[root@ceph-1 ~]# kubectl get pod -l app=nginx -o jsonpath="{range .items[*]}{.status.podIP}:6379 {end}"
10.233.64.20:6379 10.233.64.17:6379 10.233.64.21:6379 [root@ceph-1 ~]#