Prometheus Memory High
最近這陣子,因為 Apply 了一些新 Feature,撈了更多的 Target,更多的Label,起初一切很美好,更多的資料讓我們更了解服務的現狀,大約幾個鐘頭後,開始發現 Grafana 查詢緩慢,甚至 Time Out。
Prometheus Memory High
Photo by Christian Paul Stobbe on Unsplash
最近這陣子,因為 Apply 了一些新 Feature,撈了更多的 Target,更多的Label,起初一切很美好,更多的資料讓我們更了解服務的現狀,大約幾個鐘頭後,開始發現 Grafana 查詢緩慢,甚至 Time Out。
我拉了 Prometheus 和 Grafana 等服務的 Panel 來嘗試了解狀況,發現Prometheus Memory 暴漲,CPU 則越來越高。
我讀了官方跟一些部落客的文章,了解了 TSDB 工作的方式,明白是什麼東西在使我記憶體變高,最終想記錄下來希望能幫助到其他人。

記憶體中裝了什麼?
官網有這麼一段話:
The current block for incoming samples is kept in memory and is not fully persisted.
從這邊得知了 Memory 中存放了 Samples 資料,接著我嘗試查詢了下後會發現 Sample 指的就是 Time Series。 OK, 這下我大概知道是什麼東西再讓我記憶體高了,八成是我 Time Series 記太多了。接下來就是驗證猜測是否正確跟找出太多的原因。
於是接下來開始朝兩個面向去嘗試:
- Time Series
- Grafana
Time Series
驗證我的猜測
在 Prometheus 後台查詢 scrape_samples_scraped ,這能很快的列出Prometheus 產生的 Time Series 數量,是我目前用過最快的方式來得知Prometheus 每一次撈取某個 Target 時撈到的 Time Series 數量。
因此如果下了這道指令,並且得出如下圖的紅色箭頭般的數據,可以看到線圖爬升的很快,那意味著你的某個 Prometheus Exporter (Target) 正在輸出大量的 Time Series,且 Prometheus 每次來撈也撈到了不少,並且正在快速增加中。

因此當看到此圖時,心中已經有底了,確實是 Time Series 太多了,因此下一個問題是比起我預期中的,多了什麼?
找出太多的原因
這邊我想了幾件事情:
- 即使某個 Time Series 的數值沒在累積了,Prometheus 仍然會每隔一段時間過來撈取,負擔仍在。
- 既然只要 Time Series 存在就有負擔,那我得看看所有 Time Series 是不是都是必要的。
接著有了一個發現,因為偶爾會有 Bot 在打各種 ooo.xxxx.com/… 這種網址,有時會掃到我們服務,因此 Prometheus Exporter 就會產生大量 404 紀錄。 並且當 Label 的值有多種可能時,會產生不同筆 Time Series。
例如下圖中右上角看出我有 669 個結果,這邊我 Sum & Hide 掉了 Host,事實上加上Host Label會產生數倍的組合。

數倍的組合例如這樣:
http_request_duration_seconds_count{Host=”A”, code=”404", Path=”/foo”}@timespan 1 http_request_duration_seconds_count{Host=”B”, code=”404”, Path=”/foo”}@timespan 1 http_request_duration_seconds_count{Host=”A”, code=”404", Path=”/bar”}@timespan 1 http_request_duration_seconds_count{Host=”B”, code=”404”, Path=”/bar”}@timespan 1 …
而我個人在這次經驗中遇到的情況則是 6 千多筆,這些資料對我來說不是我現在想看的,卻給 Prometheus 造成相當大的負擔。
既然原因知道了,我能做的事就很簡單了。
我能怎麼做?
先講重點,我把 404 的 Label 都清空了,所以原本同樣的 Metrics Name,不同 Label 的 Time Series 可以被 Summary 成一筆,因此所有404會被Summary起來,最終從Grafana上只會看到404的Count總數。
在有限時間內首要做的事要先止血,在我找到上面講的原因跟思考上面這些事情之前,首先做的事情是加 CPU, Memory 來避免監控服務崩潰。 可很快地意識到記憶體以很快的速度在攀升。 得開始尋找真正原因,才有了今天這個學習。 下圖是發現 Memory 不對勁,Top up 了兩次後發現都沒用。最後我Summary了所有不重要的資料。 也是整個事件從頭到尾記憶體的改善圖,能夠回到原本的水平附近真是可喜可賀。

Grafana
驗證我的猜測
我嘗試在 Grafana 上做複雜的查詢,例如 Sum 一些 Time Series,尤其是那種 Label 組合很多的,一次查個幾筆 Time Series,確實會對 Prometheus 造成較高的 CPU, Memory 需求。
如下圖,在藍虛線我 Apply 複雜的查法後,接連查詢了 6 Hours, 7 Days的範圍,觸發了兩波記憶體需求,漲幅近平時狀態的一倍!
但查詢結束後會很快的降下來,這讓我認為 Grafana 複雜的查詢只會暫時性的影響,反而比較困擾的會是查詢 Time Out 的問題,因此複雜的查詢不是造成記憶體越來越高的主因。

實際上本來效果不該只有一倍漲幅,上圖是基於我改善了 404 問題後重現出來的問題。
能怎麼做?
為了避免查詢等待很久,甚至 Time Out。 我重新審視自己想做的每一張Panel 想呈現的資訊,盡量別在一張 Dashboard 上放太多種複雜查詢法。 由簡單到詳細去拉出不同 Dashboard,例如所有服務主要的狀態圖,以及每個服務的細節狀態圖,來避免一次對 Prometheus 查詢太多。
結論
要送 Time Series 上 Prometheus 時,要注意 Time Series 總數會有幾條,我喜歡先從剷除不需要的 Label 開始做起,接著把不在乎的 Label 數值給清空或是改成一樣,這樣一來在 Time Series 上會被當成同一筆,最後 Grafana 上整理下不要去做太複雜的查詢,例如要 Sum by Label,而那個 Time Series 有好多種 Label。
後記
Prometheus 有一個 /status 頁面,能看到目前 TimeSeries 總數跟 Chunks數,這兩個數字也都跟 Memory 息息相關,因此也能參考這兩個指標。 Summary 404 後 Chunks 數量為原本的 1/5。
Reference
附上這段時間我讀過的幾篇文章
- https://ganeshvernekar.com/blog/prometheus-tsdb-the-head-block/#life-of-a-sample-in-the-head 這篇講的挺好的,他雖然在講 TSDB 的工作方式,但也幫助我瞭解了Chunk 的角色。
- Storage | Prometheus 就是官網
- Which targets have the most samples? — Robust Perception | Prometheus Monitoring Experts 提到了 scrape_samples_scraped 的用途。
메타데이터
- post_id
- 5a6faaeea8b7
- slug
- 5a6faaeea8b7
- url
- https://medium.com/titansoft/5a6faaeea8b7
- canonical_url
- https://medium.com/titansoft/5a6faaeea8b7
- author_url
- https://medium.com/@.acedia
- status
- ok
- fetched_at
- 2026-06-29 02:33:43