最近在公司因為在開發 K8s Operator 的緣故,因此常常需要使用 Kubectl
跟 K8s 這個魔王打交道,開心的是,也因此學會了很多 Bash 相關的快速指令,這一篇快速分享一下,我是如何使用 JsonPath
的語法以及 xargs
快速的操作 k8s 上面的資源的!
本篇重點:
Kubectl
&JsonPath
概念xargs
拆解字串並傳入指令中
Kubectl
kubectl
是與 k8s 互動的 CLI 工具,通常會搭配 get <resource>
/ delete <resource>
的方式去操作 K8s 中的資源。
當我們要取得 K8s 資源的詳細資料的時候通常會用以下的幾種方式去做取得
kubectl get pod nginx
1NAME READY STATUS RESTARTS AGE
2nginx 1/1 Running 1 (24m ago) 22d
kubectl get pod nginx -o yaml
以 YAML 的方式回傳資訊
1apiVersion: v1
2kind: Pod
3metadata:
4 annotations:
5 kubectl.kubernetes.io/last-applied-configuration: |
6 {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"aaa-aaa":"bbb-bbb","abc/def":"omg","hello":"hi"},"name":"nginx","namespace":"default"},"spec":{"containers":[{"image":"nginx:1.14.2","name":"nginx","ports":[{"containerPort":80}]}]}}
7 creationTimestamp: "2024-06-18T02:51:33Z"
8 labels:
9 aaa-aaa: bbb-bbb
10 abc/def: omg
11 hello: hi
12 name: nginx
13 namespace: default
14 resourceVersion: "28520675"
15 uid: bd165233-da63-41fb-94ec-64d0ee87f512
16spec:
17 containers:
18 - image: nginx:1.14.2
19 imagePullPolicy: IfNotPresent
20 name: nginx
21 ports:
22 - containerPort: 80
23 protocol: TCP
24 resources: {}
25 terminationMessagePath: /dev/termination-log
26 terminationMessagePolicy: File
27 volumeMounts:
28 - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
29 name: kube-api-access-vb2dh
30 readOnly: true
31... 以下省略
kubectl get pod nginx -o json
1{
2 "apiVersion": "v1",
3 "kind": "Pod",
4 "metadata": {
5 "annotations": {
6 "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"labels\":{\"aaa-aaa\":\"bbb-bbb\",\"abc/def\":\"omg\",\"hello\":\"hi\"},\"name\":\"nginx\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx:1.14.2\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}\n"
7 },
8 "creationTimestamp": "2024-06-18T02:51:33Z",
9 "labels": {
10 "aaa-aaa": "bbb-bbb",
11 "abc/def": "omg",
12 "hello": "hi"
13 },
14 "name": "nginx",
15 "namespace": "default",
16 "resourceVersion": "28520675",
17 "uid": "bd165233-da63-41fb-94ec-64d0ee87f512"
18 },
19 "spec": {
20 "containers": [
21 {
22 "image": "nginx:1.14.2",
23 "imagePullPolicy": "IfNotPresent",
24 "name": "nginx",
25 "ports": [
26 {
27 "containerPort": 80,
28 "protocol": "TCP"
29 }
30 ],
31 "resources": {},
32 "terminationMessagePath": "/dev/termination-log",
33 "terminationMessagePolicy": "File",
34 "volumeMounts": [
35 {
36... 以下省略
kubectl describe pod nginx
以 describe 的方式取得詳細的條列式資料 這種做法可以很漂亮的取得重要的 k8s 物件資訊
1Name: nginx
2Namespace: default
3Priority: 0
4Service Account: default
5Node: henry-rapd-po-develop/192.168.89.96
6Start Time: Tue, 18 Jun 2024 10:51:33 +0800
7Labels: aaa-aaa=bbb-bbb
8 abc/def=omg
9 hello=hi
10Annotations: <none>
11Status: Running
12IP: 10.42.0.51
13IPs:
14 IP: 10.42.0.51
15Containers:
16 nginx:
17 Container ID: containerd://6fd82893641cd7389395c62d0aa4168e599fb511b7ad63408dddb00cd0542b4f
18 Image: nginx:1.14.2
19 Image ID: docker.io/library/nginx@sha256:f7988fb6c02e0ce69257d9bd9cf37ae20a60f1df7563c3a2a6abe24160306b8d
20 Port: 80/TCP
21 Host Port: 0/TCP
22 State: Running
23 Started: Wed, 10 Jul 2024 10:41:49 +0800
24 Last State: Terminated
25 Reason: Unknown
26 Exit Code: 255
27 Started: Tue, 18 Jun 2024 10:51:40 +0800
28 Finished: Wed, 10 Jul 2024 10:41:39 +0800
29 Ready: True
30 Restart Count: 1
31 Environment: <none>
32 Mounts:
33 /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-vb2dh (ro)
34Conditions:
35 Type Status
36 Initialized True
37 Ready True
38 ContainersReady True
39 PodScheduled True
40Volumes:
41 kube-api-access-vb2dh:
42 Type: Projected (a volume that contains injected data from multiple sources)
43 TokenExpirationSeconds: 3607
44 ConfigMapName: kube-root-ca.crt
45 ConfigMapOptional: <nil>
46 DownwardAPI: true
47QoS Class: BestEffort
48Node-Selectors: <none>
49Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
50 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
51Events:
52 Type Reason Age From Message
53 ---- ------ ---- ---- -------
54 Normal SandboxChanged 26m kubelet Pod sandbox changed, it will be killed and re-created.
55 Normal Pulled 26m kubelet Container image "nginx:1.14.2" already present on machine
56 Normal Created 26m kubelet Created container nginx
57 Normal Started 26m kubelet Started container nginx
Kubectl && JsonPath
上一節中提到我們取得資訊的格式可以是 json,也就代表我們可以用工具去分析這個JSON結構化資料,並且取得內容,這種作法已經內建在 kubectl
中了,也就是今天鼎鼎大名的主角 – JsonPath
!
先來一個簡單的指令
1kubectl get pod nginx -o jsonpath="{.metadata.name}"
我們得到的回應會是
1nginx
沒錯!我們簡化了輸出只取得重要的且我們關注的資訊! 這樣就可以在做 devops 的時候很方便地處理資料了!
.metadata.name
就是取得 剛剛範例中的 json 的資料,從 root key metadata
開始解析,取得 metadata
下的 name
key 的資料!
接著,我們來處理一個複雜一點的狀況
1> kubectl get pod
2NAME READY STATUS RESTARTS AGE
3example-deployment1-7c68fc9d7f-hp9dw 1/1 Running 1 (35m ago) 27d
4example-deployment1-7c68fc9d7f-rncg6 1/1 Running 1 (35m ago) 27d
5example-deployment2-56bffc5686-bzvkk 1/1 Running 1 (35m ago) 27d
6example-deployment2-56bffc5686-vjw7p 1/1 Running 1 (35m ago) 27d
7example-pod 1/1 Running 662 (35m ago) 27d
8nginx 1/1 Running 1 (35m ago) 22d
這次我們使用迴圈的方式去取得每一個 Pod 的 name,因此我們要使用 [*]
去針對每一個物件做處理
1> kubectl get pod -o jsonpath="{.items[*].metadata.name}"
2example-deployment1-7c68fc9d7f-hp9dw example-deployment1-7c68fc9d7f-rncg6 example-deployment2-56bffc5686-bzvkk example-deployment2-56bffc5686-vjw7p example-pod nginx
有發現這次開頭不一樣了嗎? 這是因為當我們取得多個物件的時候,k8s 會使用一個 items
的 key 去包裝這個陣列得值,也因此我們需要先取得 items
的陣列後
再使用 [*]
去針對陣列中所有的物件一一作分析
後面的 .metadata.name
就跟剛剛一樣,唯一不同的是這段是針對陣列裡的每一個物件去做處理!
xargs 整合
現在,我們已經使用 kubectl
+ jsonpath
取得了很多字串由空白分隔開來了
現在我們要把這些字串當作一個一個的參數傳進指令中
1kubectl get pod -o jsonpath="{.items[*].metadata.name}" | xargs -n 1 echo
xargs -n 1 echo
這邊的 -n 1
代表每一個字串都去執行一次 echo
指令
所以我們有10個pod 就會執行10次,echo 出 10 行
結果:
1example-deployment1-7c68fc9d7f-hp9dw
2example-deployment1-7c68fc9d7f-rncg6
3example-deployment2-56bffc5686-bzvkk
4example-deployment2-56bffc5686-vjw7p
5example-pod
6nginx
xargs 變化題 – 當作指令放進 bash 中
1kubectl get pod -o jsonpath="{.items[*].metadata.name}" | xargs -n 1 bash -c 'echo aaaa-$0-xdd'
我們可以用 bash -c
的方式當作參數傳入指令中,取得參數的方式就是用位置參數的取法就可以了 $0 $1
這種寫法
結果:
1aaaa-example-deployment1-7c68fc9d7f-hp9dw-xdd
2aaaa-example-deployment1-7c68fc9d7f-rncg6-xdd
3aaaa-example-deployment2-56bffc5686-bzvkk-xdd
4aaaa-example-deployment2-56bffc5686-vjw7p-xdd
5aaaa-example-pod-xdd
6aaaa-nginx-xdd
JsonPath + xargs 變化題 – 多參數 Xargs & 複雜結合字串處理的 JsonPath
這邊用了一些技巧去做出
第一個: 使用 range
+ {end}
的方式作迴圈,這樣就可以在每一次迴圈結束的時候加入換行符號了
第二個: 使用 {' '}
的方式串接字串
而 xargs
中的 -n 2
代表每兩個字串一組 -l
當作一行傳入 bash -c
中
1kubectl get pod --all-namespaces -o=jsonpath="{range .items[*]}{.metadata.name}{' '}{.metadata.namespace}{'\n'}{end}" | xargs -n 2 -l bash -c 'echo name: $0 ,namespace: $1'
結果:
1name: example-deployment1-7c68fc9d7f-hp9dw ,namespace: default
2name: example-deployment1-7c68fc9d7f-rncg6 ,namespace: default
3name: example-deployment2-56bffc5686-bzvkk ,namespace: default
4name: example-deployment2-56bffc5686-vjw7p ,namespace: default
5name: example-pod ,namespace: default
6name: nginx ,namespace: default
結語
這些 bash 指令真的很方便! 跟 SRE 合作以後,真的學到了很多很厲害的 bash 技巧,以後繼續更新文章記錄一下我的 Bash 技巧進步之路!