前面一節我們介紹了使用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表達式中的文本
-
使用range和end來遍歷集合(這點和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"}
}
]
}
| 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示例
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方便.尤其在不同環境如果輸出的格式不一樣的話,通過字符串截取得到的結果可能是錯誤的.
