昨天用 PromQL 查到了 staging 的 CPU、記憶體和重啟次數,但每次都要打開 Prometheus 貼查詢,結果也只是一條一條的序列。今天用 Grafana 把這些查詢做成 Dashboard,打開就能一眼看出 Todo App 的狀況。
Grafana 是視覺化工具,本身不存資料,而是去資料來源(Prometheus)查詢,再把結果畫成圖表:
Prometheus(存資料、執行 PromQL)
│
│ Grafana 送出 PromQL 查詢
▼
Grafana Dashboard(畫成圖表)
所以昨天學的 PromQL 可以直接沿用,差別只在於結果從表格變成圖表,並且可以把多個查詢排在同一個畫面上。
昨天裝的 kube-prometheus-stack 已經包含 Grafana,也設定好了 Prometheus 資料來源。
今天目標:登入 Grafana,看懂內建 Dashboard,建立一個可以切換 dev / staging 的 Todo App Dashboard,最後把它存進 ConfigMap,Grafana 重啟也不會消失。
轉發到本機 3001,終端機保持開著:
kubectl port-forward svc/monitoring-grafana -n monitoring 3001:80
不用 3000,是因為前面幾天 Todo App 的前端用的就是 3000,會打開到前端的畫面。
打開 http://localhost:3001,帳號 admin,密碼從 Secret 取得:
kubectl get secret monitoring-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 -d
PowerShell:
$pw = kubectl get secret monitoring-grafana -n monitoring -o jsonpath="{.data.admin-password}"
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($pw))
左側選單 Connections → Data sources,會看到已經有一個 Prometheus,URL 指向昨天 port-forward 的那個 Service。
kube-prometheus-stack 安裝時就自動設定好了,不用手動新增。
左側選單 Dashboards,kube-prometheus-stack 預裝了很多 Dashboard,先看這幾個:
打開 Kubernetes / Compute Resources / Pod,上方的 namespace 選 staging,pod 選 todo-staging-api-xxx。右上角可以調整時間範圍,看過去幾小時的變化。
這些圖表背後都是 PromQL。在任一個圖表右上角的選單選 Edit,就能看到它用的查詢,會發現跟昨天寫的很像,一樣用了
rate、sum by和 label 篩選。看完按 Discard 離開,不要存檔。
內建 Dashboard 涵蓋整個叢集,這裡建一個只看 Todo App 的。
Dashboards → New → New dashboard → Add visualization,資料來源選 Prometheus。
新版 Grafana(12.x)沒有 Add visualization 時,點 Add panel(或右側邊欄的 + → Panel),再按 Configure visualization。注意不要選到 Variable。
查詢框預設是 Builder 模式(用選單組查詢),切到 Code 模式就能直接貼昨天的 PromQL。
右側如果先出現圖表類型清單,要先點一種類型,才會出現標題、單位等設定。
依序加入四個 Panel,每加完一個按 Back to dashboard,再新增下一個:
Panel 1:API CPU 使用量
sum by (pod) (rate(container_cpu_usage_seconds_total{namespace="staging", container="api"}[5m]))
{{pod}}
API CPU 使用量(core)
Legend 填
{{pod}},圖例才會只顯示 Pod 名稱。標題在右側 Panel options → Title,設定項目多時可以用右側上方的搜尋框找。
Panel 2:API 記憶體使用率
sum by (pod) (container_memory_working_set_bytes{namespace="staging", container="api"})
/
sum by (pod) (kube_pod_container_resource_limits{namespace="staging", container="api", resource="memory"})
{{pod}}
0,Max 填 1
0.8,Show thresholds 選 As lines
API 記憶體使用率
圖上會多一條 80% 的紅線,曲線越接近它,越接近被 OOMKilled。
沒看到紅線,通常是漏填 Min、Max。Y 軸會自動縮放到資料附近(例如 46%~48%),80% 就落在畫面外了。
兩個 Pod 的使用率接近時,曲線會疊在一起,滑鼠移上去就能看到各自的數值。
Panel 3:API 可用 Pod 數
sum(kube_deployment_status_replicas_available{namespace="staging", deployment=~".*-api"})
API 可用 Pod 數
staging 的 API 由 HPA 控制,這個數字會隨負載在 2~5 之間變化。
Panel 4:過去 1 小時重啟次數
sum by (pod) (increase(kube_pod_container_status_restarts_total{namespace="staging"}[1h]))
{{pod}}
過去 1 小時重啟次數
這裡沒有篩選 container,所以 frontend 和 mysql 的 Pod 也會列出來。
四個 Panel 都加好後,拖曳標題列調整位置、拖曳右下角調整大小,右上角 Save dashboard,命名為 Todo App Overview。
現在查詢都寫死 namespace="staging",想看 dev 就得再做一份。Grafana 的變數可以解決這個問題。
先確認 dev 有在跑:
kubectl get pods -n dev
出現
No resources found,通常是 Day 26 Step0 重建叢集後漏了部署 dev。在helm/補上,等 PodRunning一兩分鐘後再繼續:helm install todo-dev ./todo-app -f values-dev.yaml --set mysql.password=devpass123 --set mysql.rootPassword=devroot123 -n dev --create-namespace
namespace
dev,staging
新版 Grafana:編輯模式下點右側邊欄的 + → Variable,或齒輪 ⚙ → Variables → Add variable。
⚠️ 容易踩到的坑:
- 要選 Custom,不是 Constant(Constant 不會出現下拉選單)。選錯後用 Change type 改,可能留下隱藏的舊變數,記得確認變數清單的 Hidden 底下是空的。
- 查詢裡的
$namespace對應的是 Name,不是 Label。- 值用半形逗號、不加空格,Preview 要出現兩個選項。
- 改完要 Save,沒存檔就重新整理會全部消失。
namespace 下拉選單。"staging" 改成 "$namespace"(Panel 2 有兩處),例如:sum by (pod) (rate(container_cpu_usage_seconds_total{namespace="$namespace", container="api"}[5m]))
staging 後存檔,存檔時選的值就是預設值。切換下拉選單,同一個 Dashboard 就能看 dev 或 staging。Panel 3 用 deployment=~".*-api" 而不是寫死 todo-staging-api,就是為了讓兩個環境都適用。

💡 切到 dev 時,Pod 名稱要變成
todo-dev-...,可用 Pod 數是 1(dev 沒開 HPA)。還是todo-staging-...的話,代表有查詢沒改到。在 Panel 編輯畫面點 Query inspector,可以看到變數替換後實際送出的查詢。
這跟 Day 24 的 Helm values 是一樣的概念:模板只有一份,差異用參數帶入。
kube-prometheus-stack 預設沒有幫 Grafana 開啟永久儲存,Grafana 的 Pod 重啟後,在 UI 建立的 Dashboard 就會消失。
解法是把 Dashboard 匯出成 JSON,存成 ConfigMap。kube-prometheus-stack 的 Grafana 有一個 sidecar,會自動載入帶有 grafana_dashboard=1 label 的 ConfigMap。
時間範圍顯示成
2026-10-06 01:59:01 to ...這種固定時段,通常是在圖上拖曳放大後存了檔。不改回來,從 ConfigMap 載入後會一直停在那個時段。
新版 Grafana:右側邊欄的下載圖示 → Export as code → Download file。有格式選項的話選 Classic。
如果有 Export the dashboard to use in another instance 的開關,保持關閉。打開的話資料來源會變成
${DS_PROMETHEUS}佔位符,載入後 Panel 會沒資料。
Todo App Overview-<一串數字>.json。在 repo 根目錄建立 monitoring/,搬過去並改名:mkdir monitoring
mv ~/Downloads/"Todo App Overview-<一串數字>.json" monitoring/todo-app-dashboard.json
PowerShell:
mkdir monitoring
Move-Item "$HOME\Downloads\Todo App Overview-<一串數字>.json" monitoring\todo-app-dashboard.json
monitoring/ 執行,建立 ConfigMap 並加上 label:kubectl create configmap todo-app-dashboard -n monitoring --from-file=todo-app-dashboard.json
kubectl label configmap todo-app-dashboard -n monitoring grafana_dashboard=1
kubectl get configmap todo-app-dashboard -n monitoring --show-labels
LABELS 欄位看到 grafana_dashboard=1 就完成了。
kubectl delete pod -n monitoring -l app.kubernetes.io/name=grafana
kubectl get pods -n monitoring -w
等新的 Grafana Pod 顯示 3/3 Running 後按 Ctrl + C,重新執行 Step1 的 port-forward(Pod 重建後原本的會斷線)。登入後 Todo App Overview 還在,這次是從 ConfigMap 載入的。
找不到 Dashboard 時,看 sidecar 的 log:
kubectl logs -n monitoring deploy/monitoring-grafana -c grafana-sc-dashboard --tail=20
從 ConfigMap 載入的 Dashboard 無法在 UI 直接存檔。要修改的話,改完重新匯出覆蓋 JSON,再更新 ConfigMap(ConfigMap 已存在,不能再用
create):kubectl create configmap todo-app-dashboard -n monitoring --from-file=todo-app-dashboard.json --dry-run=client -o yaml | kubectl apply -f -
git pull
git add monitoring/todo-app-dashboard.json
git commit -m "Add Todo App Grafana dashboard"
git push
先
git pull,因為 CI 會更新values-staging.yaml的 image tag,本機可能不是最新的。
練習結束後,到 port-forward 的終端機按 Ctrl + C 停掉。
Dashboard 要放什麼?Google SRE 書裡提出了「四個黃金指標」,是設計 Dashboard 的好起點:
今天的 Dashboard 涵蓋的是 Saturation(CPU、記憶體、Pod 數)。這些資料來自 kubelet 和 kube-state-metrics,它們只看得到容器和 K8s 物件的狀態,看不到「進來了幾個請求、回應花了多久、有幾個失敗」。
Latency、Traffic、Errors 屬於應用程式層的指標,要由應用程式自己暴露 /metrics 給 Prometheus 抓取。以 Todo App 的 FastAPI 為例,可以用 prometheus-fastapi-instrumentator 自動產生請求數、回應時間等指標,再搭配 ServiceMonitor 讓 Prometheus 收集,就能把四個黃金指標補齊,有興趣的話很適合當作延伸練習。
$namespace 讓同一個 Dashboard 切換 dev / stagingDashboard 要有人盯著才有用。明天會學 Alerting,把今天的查詢變成告警規則,出問題時自動通知。