一句話結論:單機 k3s 叢集用 kube-prometheus-stack 一個 chart 就能裝好 Prometheus 與 Grafana,但要記得關掉 kube-proxy、scheduler、controller-manager 這三個元件,不然對應的規則會一直誤報。整套大約吃 850 MiB 記憶體。
遇到的問題
叢集跑起來之後,下一個問題是:它現在健康嗎?哪個 Pod 吃了太多資源?
Prometheus 加 Grafana 幾乎是標準答案。但要自己一個一個裝 Prometheus、Grafana、kube-state-metrics、node-exporter,再接起來、再寫規則,工作量不小。
kube-prometheus-stack 把這些打包成一個 chart。問題是它的預設值,是以標準的 Kubernetes 叢集為前提,換成 k3s 就會冒出一些意料之外的東西。
這篇整理出在單機 k3s 上需要調整的地方,所有 values 都在一個全新的單節點叢集上實際跑過。
手把手步驟
前提與測試版本
手邊要有一個 Kubernetes 叢集和 Helm。下面的指令與 values,是在這些版本上實測的:
| 元件 | Chart 版本 | 應用程式版本 |
|---|---|---|
| kube-prometheus-stack | 92.10.1 | Prometheus Operator v0.94.1 |
叢集是 k3s v1.31.5(單節點)。版本不同的話,values 的欄位可能不一樣,請對一下 chart 的 values.yaml。
步驟一:加 Helm repo
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
步驟二:寫 values
kube-prometheus-stack 一次帶來 Prometheus Operator、Prometheus、Grafana、Alertmanager、kube-state-metrics、node-exporter 和一整套預設規則與儀表板。新建 prom-values.yaml:
# k3s 把 kube-proxy/scheduler/controller-manager 編進 k3s 主程序,不是獨立的 Pod,
# chart 預設找不到對應的目標,不關的話對應的規則會一直誤報
kubeProxy: {enabled: false}
kubeScheduler: {enabled: false}
kubeControllerManager: {enabled: false}
prometheus:
prometheusSpec:
# 預設只選同一個 release 的 ServiceMonitor/規則,其他 namespace 的 exporter 會漏抓
serviceMonitorSelectorNilUsesHelmValues: false
podMonitorSelectorNilUsesHelmValues: false
ruleSelectorNilUsesHelmValues: false
retention: 7d
retentionSize: 4GB
resources:
requests: {cpu: 100m, memory: 256Mi}
limits: {cpu: 500m, memory: 1Gi}
storageSpec:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
說明一下。
關掉三個 k3s 沒有的元件
這三個元件在 k3s 上是編在主程序裡的,不是獨立的 Pod,chart 預設的做法找不到它們。不關的話,後面「踩到的坑」會講到對應的規則會怎麼樣。
selector 三行
serviceMonitorSelectorNilUsesHelmValues 這三個設成 false,Prometheus 才會抓其他 release、其他 namespace 的 ServiceMonitor 和規則。
預設是只選跟這個 chart 同一個 release 標籤的資源,之後如果別的 Helm release 帶了自己的 ServiceMonitor,就會被忽略。
保留與容量
metrics 留 7 天,並用 retentionSize: 4GB 當第二道保險,避免磁碟被吃滿。兩個條件,先到的先生效。
資源與儲存
resources 把 Prometheus 的記憶體限制在 1 GiB,storageSpec 給它一顆 10 GiB 的 PVC。單機磁碟有限,這兩個數字請依自己的機器調整。
步驟三:安裝
helm upgrade --install monitoring prometheus-community/kube-prometheus-stack \
--version 92.10.1 -n monitoring --create-namespace \
-f prom-values.yaml --wait --timeout 10m
這個 chart 比較大,第一次拉映像大概要幾分鐘。
完成後確認:
kubectl get pods -n monitoring
應該會看到 Prometheus、Alertmanager、Grafana、Operator、kube-state-metrics、node-exporter 都是 Running。
步驟四:驗證
Grafana
先取得密碼,帳號是 admin:
kubectl get secret -n monitoring -l app.kubernetes.io/component=admin-secret \
-o jsonpath="{.items[0].data.admin-password}" | base64 --decode; echo
再 port-forward:
kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80
打開 http://localhost:3000 登入,到 Dashboards,chart 已經預設放好一批 Kubernetes 相關的儀表板。
Prometheus 目標與告警
kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-prometheus 9090:9090
打開 http://localhost:9090,Status → Targets 應該全部是 UP(API server、CoreDNS、kubelet、kube-state-metrics、node-exporter、Grafana 等)。
Alerts 頁只會有一條在跑:Watchdog。這是 kube-prometheus-stack 刻意放的一條「永遠觸發」的心跳規則,用來確認告警管線本身活著,看到它是正常的。
如果看到其他規則在 firing,通常就是下面「踩到的坑」會講的情況。
資源用量
裝完幾分鐘後,用 kubectl top pods -n monitoring 量到的數字:
| 元件 | 記憶體 |
|---|---|
| Grafana | 約 465 MiB |
| Prometheus | 約 292 MiB |
| Alertmanager | 約 38 MiB |
| Prometheus Operator | 約 26 MiB |
| kube-state-metrics | 約 20 MiB |
| node-exporter | 約 9 MiB |
加起來約 850 MiB。整個節點(含 k3s 本身)當時用了約 2.4 GB。
這是剛裝好、幾乎沒有流量的數字。Prometheus 的用量會隨著抓取的目標與時間序列數量增加,上線之後請再觀察一陣子。
踩到的坑
1. k3s 上不關那三個元件,規則會一直誤報
這個我特地驗證過:把 kubeProxy、kubeScheduler、kubeControllerManager 都打開,過一分鐘去看規則,KubeProxyDown、KubeSchedulerDown、KubeControllerManagerDown 三條都進入 pending,等待時間是 900 秒。
也就是說 15 分鐘後它們就會變成 firing,而且永遠不會好,因為預設的設定在 k3s 上找不到任何目標。
要說明的是,k3s 並不是沒有這三個元件的 metrics。k3s 文件的 Requirements 頁,在網路埠的表格裡就列了 kube-proxy(10249)、kube-controller-manager(10257)、kube-scheduler(10259)的 metrics 埠。
只是想真的監控它們,需要自己處理綁定位址與抓取設定,這部分沒有實測,這裡選擇直接關掉。
另外用 helm template 比對渲染結果:打開時會多出這三條規則和對應的 ServiceMonitor,關掉之後兩者都是 0。
所以關掉這三個元件,是同時把目標、ServiceMonitor 和規則一起移除。
2. 別的 Helm release 的 ServiceMonitor 抓不到
chart 預設只選有自己 release 標籤的 ServiceMonitor、PodMonitor 和規則。
如果之後用另一個 Helm release 安裝資料庫或其他應用,它們帶的 ServiceMonitor 不會被這個 Prometheus 抓到,Targets 頁上就是看不到。
步驟二的那三行 ...NilUsesHelmValues: false 就是用來解這個問題的:改成不依 release 標籤過濾。
3. 叢集一大,可能撞到 inotify 上限
節點與 Pod 多了之後,系統可能開始隨機報 Too many open files,而且不是檔案描述符不夠,而是 inotify 的配額用完。
kind 的 Known Issues 文件對這點有說明:Ubuntu 預設的 fs.inotify.max_user_instances 是 128、max_user_watches 是 8192,對有很多節點的叢集不夠。
暫時調高:
sudo sysctl fs.inotify.max_user_watches=524288
sudo sysctl fs.inotify.max_user_instances=512
要永久生效,把兩行寫進 /etc/sysctl.conf(或 /etc/sysctl.d/ 底下的檔案)。這個設定是整台主機共用的,用容器當節點的叢集(例如 k3d、kind)會吃到同一份配額。
為什麼這樣選
kube-prometheus-stack,而不是自己組
一個 chart 就帶來 Operator、Prometheus、Grafana、kube-state-metrics、node-exporter 和一整套預設規則與儀表板。
自己一個一個裝也可以,但光是把它們接起來、再維護規則,就是不少工作。
代價是這個 chart 很大,預設值是為標準叢集設計的,換成 k3s 這種精簡發行版就要像上面這樣調整。
retention 7 天加容量上限
單機磁碟有限,所以同時設了時間(7 天)和容量(4 GB)兩個上限。要長期保存 metrics 的話,需要調大這兩個值和 PVC,或是把資料送到遠端儲存。
保留預設的 Alertmanager
這份 values 沒有動 Alertmanager,它會跟著預設一起裝起來。這是最省事的起點,之後想怎麼處理告警,再另外調整。
延伸閱讀
- kube-prometheus-stack 的 chart 說明:所有 values 的來源,不同 Kubernetes 發行版的注意事項也在裡面。
- Prometheus Operator:ServiceMonitor 與 selector:Operator 怎麼選出要抓的目標。
- K3s:Requirements:網路埠表格裡列出 kube-proxy、kube-controller-manager、kube-scheduler 的 metrics 埠。
- kind:Known Issues:「too many open files」與 inotify 上限的處理。
這篇的 values 在上面列的版本實測過。換版本的話,記得先看 chart 的 values.yaml 欄位有沒有改名。













