Kubectl JSONPath 實戰:Kubernetes 盤點 Bitnami 映像檔與查詢技巧

Bitnami 不再免費提供新版的 production ready 容器映像檔,你的叢集還有多少在使用?這篇文章分享我用 kubectl JSONPath 進行映像檔盤點的流程,快速找出 Bitnami image,並為後續替換與升級做準備。

前言

2025 年 7 月中旬,Bitnami 宣布要把所有的容器映像檔 (image),包括舊版或版本化的標籤,從公共目錄 (docker.io/bitnami) 移至 Bitnami Legacy 儲存庫 (docker.io/bitnamilegacy),8 月 28 日以後,公共目錄只會留下 latest 標籤,並停止同步。

如果只有少量 release (Helm) 在執行,也許可以肉眼檢查一下,或者把現在所有 helm 模板用 grep bitnami 出來就可以;不過這也不一定準確,可能會有沒開啟的 debug 工具也被加入進去。

但如果面對的是數十座 cluster 和數百台 node,裡面可能有上千個 application 和 pod 要管理,只剩下一星期,要如何有效率盤點又不會出錯呢?

……你不會跟我說你要用 for 迴圈 + kubectl 把列出來吧?不會吧?

JSONPath 基本介紹

JSONPath 是個 JSON 查詢語言,可以把複雜的 JSON 中以字串形式尋找所需資料。

語法上也沒有到特別複雜,如果寫過 C 語系或 Go Template 系列,原則上都很相似。

  • .[]:基本上一定會使用到它,例如 .kind 就會去查詢這段 JSON 裡面的 kind 欄位值。
  • *:用到星號,大多數就是 wildcard,這裡沒有例外,搭配 List 使用的話,例如 .items[*].name,就會把 items 每個元素的 name 列出來。
  • ?():括號裡面放條件,用於過濾(注意:kubectl 的 JSONPath 不支援正則表達式,請使用 -o json + jq 替代)
  • range + end:通常想做格式化輸出就會使用,例如 {range .items[*]}{.metadata.name}{"\n"}{end} 就會把 items 每個元素 metadata.name + 換行的形式做輸出。

剩下更詳細的示範可以看 Kubernetes 官方文件

實戰:盤點 Bitnami image

預先建立好 cluster,裡面包含 apache 和 nginx 的 Bitnami Helm Chart(皆為預設值),還有 my-nginxtestrun 分別為 nginx:1.27ubuntu:24.04 的其他資源。

假設要列出目前有在 Pod 的資源,可以這樣做:

1
kubectl get pod -A

輸出範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
NAMESPACE            NAME                                             READY   STATUS    RESTARTS   AGE
default apache-64c48795df-m4kd9 1/1 Running 0 3m22s
default my-nginx 1/1 Running 0 42s
default nginx-7dd6f7f5fd-zhkrk 1/1 Running 0 2m17s
default testrun 1/1 Running 0 54s
kube-system cilium-6b6rw 1/1 Running 0 35m
kube-system cilium-7mht5 1/1 Running 0 35m
kube-system cilium-envoy-8lcqm 1/1 Running 0 35m
kube-system cilium-envoy-8xwh8 1/1 Running 0 35m
kube-system cilium-envoy-p2xpj 1/1 Running 0 35m
kube-system cilium-envoy-q24p5 1/1 Running 0 35m
kube-system cilium-k7jml 1/1 Running 0 35m
kube-system cilium-operator-5bc4cfbd98-mp4qg 1/1 Running 0 35m
kube-system cilium-p64dn 1/1 Running 0 35m
kube-system coredns-674b8bbfcf-fssrj 1/1 Running 0 37m
kube-system coredns-674b8bbfcf-mx7pf 1/1 Running 0 37m
kube-system etcd-jsonpath-control-plane 1/1 Running 0 37m
kube-system kube-apiserver-jsonpath-control-plane 1/1 Running 0 37m
kube-system kube-controller-manager-jsonpath-control-plane 1/1 Running 0 37m
kube-system kube-scheduler-jsonpath-control-plane 1/1 Running 0 37m
local-path-storage local-path-provisioner-7dc846544d-w2qx8 1/1 Running 0 37m

如果要完整列出詳細資訊,可以使用 -o yaml-o json。(篇幅限制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"creationTimestamp": "2025-08-21T11:37:47Z",
"generateName": "apache-64c48795df-",
"generation": 1,
"name": "apache-64c48795df-m4kd9",
"namespace": "default",
},
"spec": {
"containers": [
{
"image": "docker.io/bitnami/apache:2.4.65-debian-12-r2",
"imagePullPolicy": "IfNotPresent",
(truncated....)
],
"kind": "List",
"metadata": {
"resourceVersion": ""
}
}

到這裡可以知道,kubectl.items 列出目前的 Pod,裡面當中的 .spec 就是 PodSpec,再往下探勘,就可以看到 .containers,因為一個 Pod 可以有數個 container,每個 container 都會有 .image,那就是需要的資料了。

這樣就可以依照條件,寫出一份:

1
kubectl get pod -A -o jsonpath="{.items[*].spec.containers[*].image}"

輸出範例:

1
docker.io/bitnami/apache:2.4.65-debian-12-r2 nginx:1.27 docker.io/bitnami/nginx:1.29.1-debian-12-r0 ubuntu:24.04 quay.io/cilium/cilium:v1.17.4@sha256:24a73fe795351cf3279ac8e84918633000b52a9654ff73a6b0d7223bcff4a67a quay.io/cilium/cilium:v1.17.4@sha256:24a73fe795351cf3279ac8e84918633000b52a9654ff73a6b0d7223bcff4a67a quay.io/cilium/cilium-envoy:v1.32.6-1746661844-0f602c28cb2aa57b29078195049fb257d5b5246c@sha256:a04218c6879007d60d96339a441c448565b6f86650358652da27582e0efbf182 quay.io/cilium/cilium-envoy:v1.32.6-1746661844-0f602c28cb2aa57b29078195049fb257d5b5246c@sha256:a04218c6879007d60d96339a441c448565b6f86650358652da27582e0efbf182 quay.io/cilium/cilium-envoy:v1.32.6-1746661844-0f602c28cb2aa57b29078195049fb257d5b5246c@sha256:a04218c6879007d60d96339a441c448565b6f86650358652da27582e0efbf182 quay.io/cilium/cilium-envoy:v1.32.6-1746661844-0f602c28cb2aa57b29078195049fb257d5b5246c@sha256:a04218c6879007d60d96339a441c448565b6f86650358652da27582e0efbf182 quay.io/cilium/cilium:v1.17.4@sha256:24a73fe795351cf3279ac8e84918633000b52a9654ff73a6b0d7223bcff4a67a quay.io/cilium/operator-generic:v1.17.4@sha256:a3906412f477b09904f46aac1bed28eb522bef7899ed7dd81c15f78b7aa1b9b5 quay.io/cilium/cilium:v1.17.4@sha256:24a73fe795351cf3279ac8e84918633000b52a9654ff73a6b0d7223bcff4a67a registry.k8s.io/coredns/coredns:v1.12.0 registry.k8s.io/coredns/coredns:v1.12.0 registry.k8s.io/etcd:3.5.21-0 registry.k8s.io/kube-apiserver:v1.33.1 registry.k8s.io/kube-controller-manager:v1.33.1 registry.k8s.io/kube-scheduler:v1.33.1 docker.io/kindest/local-path-provisioner:v20250214-acbabc1a

接下來就可以整理(trsortuniqgrep)這些 image:

1
kubectl get pod -A -o jsonpath="{.items[*].spec.containers[*].image}" | tr " " "\n" | sort | uniq

輸出範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
docker.io/bitnami/apache:2.4.65-debian-12-r2
docker.io/bitnami/nginx:1.29.1-debian-12-r0
docker.io/kindest/local-path-provisioner:v20250214-acbabc1a
nginx:1.27
quay.io/cilium/cilium-envoy:v1.32.6-1746661844-0f602c28cb2aa57b29078195049fb257d5b5246c@sha256:a04218c6879007d60d96339a441c448565b6f86650358652da27582e0efbf182
quay.io/cilium/cilium:v1.17.4@sha256:24a73fe795351cf3279ac8e84918633000b52a9654ff73a6b0d7223bcff4a67a
quay.io/cilium/operator-generic:v1.17.4@sha256:a3906412f477b09904f46aac1bed28eb522bef7899ed7dd81c15f78b7aa1b9b5
registry.k8s.io/coredns/coredns:v1.12.0
registry.k8s.io/etcd:3.5.21-0
registry.k8s.io/kube-apiserver:v1.33.1
registry.k8s.io/kube-controller-manager:v1.33.1
registry.k8s.io/kube-scheduler:v1.33.1
ubuntu:24.04

grep 找出 Bitnami 字串:

1
kubectl get pod -A -o jsonpath="{.items[*].spec.containers[*].image}" | tr " " "\n" | sort | uniq | grep bitnami

輸出範例:

1
2
docker.io/bitnami/apache:2.4.65-debian-12-r2
docker.io/bitnami/nginx:1.29.1-debian-12-r0

這樣下來,是不是心裡比較踏實,而且還更有效率?

不過 kubectl 的 JSONPath 目前不支援正則表達式,所以如果想要使用的話,就用 jq 來處理吧!

1
kubectl get pod -A -o json | jq -r '.items[].spec.containers[].image | select(test("bitnami"))' | sort | uniq

除了盤點 Bitnami Image 以外,如果想要知道目前基礎架構所使用的 Docker Image 有無安全漏洞,列出來後就可以送到 trivy 或其他 container 弱掃工具,統計哪些 Deployment 的 replica 大於 5 個,甚至想要知道 Pod 狀態數量,搭配 bash 指令,就能簡易算出結果。

結論

後續就能從 workload(e.g. Deployment、Statefulset、Cronjob 等)修改,不過這是後話了,先盤點正在使用的 Image,對 workload 上 patch 修正(e.g. 字串替換)只是小事。

CRD 控制 workload 呢?請閱讀 CRD 給的對應 API 在哪,原則上都大同小異。

kubectl 的 output 大家比較常用的是 widejsonyaml,當別人還在寫 for 迴圈慢慢 grep 過濾查詢,碰到大量資料或複雜的規則,最終結果還可能會出現偏差,只要學會 JSONPathjq 並搭配 bash 指令,就能寫出更簡單明瞭的方法!

Buy Me A Coffee

Kubectl JSONPath 實戰:Kubernetes 盤點 Bitnami 映像檔與查詢技巧
https://blog.yangjerry.tw/jsonpath-introduction/
作者
Jerry Yang
發布於
2025年8月21日
許可協議