快轉到主要內容

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

·493 字·3 分鐘·
ChengHao Yang
作者
ChengHao Yang
SRE / CNCF Ambassador
目錄

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 的資源,可以這樣做:

kubectl get pod -A

輸出範例:

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。(篇幅限制)

{
    "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,那就是需要的資料了。

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

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

輸出範例:

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:

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

輸出範例:

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 字串:

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

輸出範例:

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

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

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

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 指令,就能寫出更簡單明瞭的方法!

相關文章