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-nginx
和 testrun
分別為 nginx:1.27
和 ubuntu:24.04
的其他資源。
假設要列出目前有在 Pod 的資源,可以這樣做:
輸出範例:
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
|
接下來就可以整理(tr
、sort
、uniq
、grep
)這些 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 大家比較常用的是 wide
、json
、yaml
,當別人還在寫 for 迴圈慢慢 grep
過濾查詢,碰到大量資料或複雜的規則,最終結果還可能會出現偏差,只要學會 JSONPath
或 jq
並搭配 bash
指令,就能寫出更簡單明瞭的方法!