kubectl get 中 -o jsonpath 的语法格式

目录

    • 前言
    • jsonpath语法讲解
    • kubectl get命令
    • 创建示例一个nginx deployment
    • 安装jq命令实现json格式化
    • -o jsonpath= 讲解
    • kubectl 的 jsonpath 输出不支持正则表达式
    • 总结

前言

环境: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语法讲解

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])]

kubectl get命令

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=

创建示例一个nginx deployment

[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格式化

jq命令是一个实现json格式化的工具,默认的centos源里面没有,需要先安装epel源。

yum install epel-release -y
yum install jq -y

-o jsonpath= 讲解

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 的 jsonpath 输出不支持正则表达式

# 下面的命令不会生效
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 ~]#

你可能感兴趣的:(kubernetes,kubernetes,运维)