一. 引言
Prometheus 是一款開源的監(jiān)控與報警系統(tǒng),支持對海量監(jiān)控數(shù)據(jù)的抓取與查詢。在部署 Prometheus 服務(wù)之前,對服務(wù)的存儲用量進行規(guī)劃是十分重要的。否則,運維人員無法對業(yè)務(wù)數(shù)據(jù)的規(guī)模和所需存儲資源的量級獲得直觀認識。分配的存儲資源過多,會導(dǎo)致資源閑置與成本浪費;分配的存儲容量不足,則無法應(yīng)對業(yè)務(wù)的增長,嚴重影響監(jiān)控服務(wù)的穩(wěn)定性。
部署 Prometheus 服務(wù)的第一個步驟是,整理與獲得需要監(jiān)控的節(jié)點集合。通過這一集合,我們可以計算出業(yè)務(wù)數(shù)據(jù)的規(guī)模。進而,我們可以計算出,需要多少存儲資源來支撐監(jiān)控服務(wù)的運行。
本文對影響 Prometheus 服務(wù)的運行時存儲用量的各個因素進行了剖析與討論,并給出若干經(jīng)驗公式。這些公式可以用于預(yù)估監(jiān)控服務(wù)的內(nèi)存和硬盤用量。
二. 計算樣本總量
首先明確兩個名詞,監(jiān)控節(jié)點與測量點。
- 監(jiān)控節(jié)點。一個 exporter 進程被認為是一個監(jiān)控節(jié)點。一臺主機上可能運行多個不同類型的 exporter,因此,這臺主機上存在多個監(jiān)控節(jié)點。
- 測量點。一個測量點代表了某監(jiān)控節(jié)點上的一個觀測對象。從某測量點采集到的一組樣本數(shù)據(jù)構(gòu)成一條時間序列(time series)。
為了預(yù)估存儲用量,首先需要計算樣本數(shù)據(jù)的總量。我們約定:
- 需要監(jiān)控的節(jié)點集合為 $$nodes={i|i>0}$$
- 節(jié)點 i 上的測量點的數(shù)目為 $$metrics(i)$$
- 對節(jié)點 i 的抓取時間間隔為 $$interval(i)$$,一般為所有節(jié)點設(shè)置相同的抓取間隔
每個節(jié)點上的測量點的數(shù)目由所使用的具體的 exporter 定義。特別的:
- Node Exporter 有 251 個測量點
- Prometheus 服務(wù)本身有 775 個測量點
抓取間隔越大,數(shù)據(jù)越稀疏;抓取間隔越小,監(jiān)控數(shù)據(jù)的時間分辨率越高,但所需的存儲資源會增多。建議將該值設(shè)置在 5s ~ 15s 之間。
基于上述約定可得,在特定的時間范圍 $$duration$$ 內(nèi),Prometheus 從節(jié)點集合中所抓取的樣本數(shù)據(jù)的總量依下式計算:
$$sample_count(duration)=\sum_{i \in nodes}{(metrics(i) \times \frac{duration}{interval(i)})}$$
Prometheus 支持三種不同的數(shù)據(jù)編碼方案。第一種方案是 delta 編碼,已被棄用;第二種方案是 double-delta 編碼,這也是默認使用的編碼方案;第三種方案是 varbit 編碼,基于 Facebook 的一篇關(guān)于時序數(shù)據(jù)庫的論文。varbit 編碼方案雖能提高數(shù)據(jù)壓縮率,卻顯著增大了編解碼的運算時間。除非有特殊場景,否則我們使用 double-delta 編碼方案。
由 Prometheus 的官方文檔,使用 double-delta 方案對數(shù)據(jù)進行編碼后,每條樣本的字節(jié)大小為:
$$sample_size=3.3B$$
經(jīng)過若干次采樣測量,觀測到的平均樣本大小介于 3.0~3.8B 之間。可以認為 3.3B 的單條樣本大小是可信的。
三. 規(guī)劃內(nèi)存用量
Prometheus 對內(nèi)存的使用由以下四個部分組成:
- 留存于內(nèi)存的活躍樣本
- 排隊等待持久化的過期樣本
- 索引數(shù)據(jù)
- 其他運行時內(nèi)存消耗
第 3.1 節(jié)討論樣本數(shù)據(jù)的內(nèi)存用量(前兩部分),第 3.2 節(jié)討論索引數(shù)據(jù)的內(nèi)存用量。對于其他的運行時內(nèi)存消耗,本文不予討論。
3.1 為樣本數(shù)據(jù)計算內(nèi)存用量
3.1.1 留存于內(nèi)存的活躍樣本
對于活躍樣本,假設(shè)我們要求的留存時間為 $$mem_retention$$,則所需的內(nèi)存空間為:
$$sample_mem_1=sample_size \times sample_count(mem_retention)$$
在內(nèi)存中的留存數(shù)據(jù)越多,查詢過往數(shù)據(jù)的性能越高。但是,新數(shù)據(jù)的價值遠遠高于過往數(shù)據(jù)。在實際應(yīng)用中,需要根據(jù)所監(jiān)控的業(yè)務(wù)的性質(zhì),設(shè)定合理的內(nèi)存留存時間。Facebook 在其論文中給出的經(jīng)驗值是 26h。建議將該值設(shè)置在 6h ~ 48h 之間。
3.1.2 排隊等待持久化的過期樣本
對于排隊樣本,我們約定:
- 為了完成對當(dāng)前所有排隊樣本的持久化,Prometheus 需要花費的時間周期為 $$persist_cycle$$
- 為了不至于使 Prometheus 進入緊急模式(Rush mode),排隊樣本所占的空間不應(yīng)超過預(yù)估空間的 $$80%$$
一般情況下,持久化的時間周期為 6 個小時:
$$persist_cycle=6h$$
因此,排隊樣本所需的內(nèi)存空間為:
$$sample_mem_2=\frac{sample_size \times sample_count(persist_cycle)}{0.8}$$
3.1.3 匯總
基于前兩個公式,再加上索引數(shù)據(jù)的內(nèi)存用量(參見第 3.2 節(jié)),總內(nèi)存用量可以依下式計算:
$$mem=sample_mem_1+sample_mem_2+index_mem$$
一條經(jīng)驗法則為,總內(nèi)存用量不應(yīng)超過物理內(nèi)存大小的三分之二。
下表計算了若干典型的內(nèi)存用量(假設(shè)所有節(jié)點均為 Node Exporter 節(jié)點):
節(jié)點數(shù)目 | 內(nèi)存留存 | 抓取間隔 | 活躍樣本量 | 排隊樣本量 | 內(nèi)存用量 | 物理內(nèi)存 |
---|---|---|---|---|---|---|
100 | 6h | 1s | 1.789G | 2.237G | 4.026G | 6G |
100 | 6h | 5s | 0.358G | 0.447G | 0.805G | 1.5G |
1000 | 6h | 5s | 3.58G | 0.447G | 4.027G | 6G |
100 | 24h | 1s | 7.156G | 2.237G | 9.393G | 14G |
100 | 24h | 5s | 1.432G | 0.447G | 1.879G | 3G |
1000 | 24h | 5s | 14.32G | 0.447G | 14.75G | 22G |
3.2 為索引數(shù)據(jù)計算內(nèi)存用量
對索引數(shù)據(jù)所需內(nèi)存的估計,可以使用下面的經(jīng)驗公式:
$$index_mem=\frac{series_count}{1000}MB$$
其中,
$$series_count=\sum_{i \in nodes}{metrics(i)}$$
也就是,如果有 1000 個時間序列,大約需要 1M 內(nèi)存。為了提高對舊數(shù)據(jù)查詢性能,可以適當(dāng)增大索引內(nèi)存。
四. 規(guī)劃硬盤用量
4.1 為樣本數(shù)據(jù)計算硬盤用量
Prometheus 將樣本數(shù)據(jù)持久化為若干文件。當(dāng)文件中的過期數(shù)據(jù)超過一定比率時,Prometheus 會對文件執(zhí)行收縮操作。這個比率被稱為文件的收縮比,默認值為 $$10%$$。留存時間設(shè)置的越大,文件的收縮比應(yīng)該相應(yīng)地上調(diào)。
假設(shè)我們要求樣本留存時間為 $$disk_retension$$,文件的收縮比為 $$shrink_ratio$$,則樣本的硬盤用量為:
$$sample_disk=\frac{sample_size \times sample_count(disk_retention)}{1+shrink_ratio}$$
加上存儲檢查點所需的硬盤空間(參加第 4.2 節(jié)),總硬盤用量為:
$$disk=sample_disk+checkpoint_disk$$
下表計算了若干典型的硬盤用量(假設(shè)所有節(jié)點均為 Node Exporter 節(jié)點),注意,該表未包含存儲 checkpoint 所需要的硬盤空間:
節(jié)點數(shù)目 | 留存時間 | 抓取間隔 | 硬盤用量 |
---|---|---|---|
100 | 14d | 1s | 91G |
100 | 14d | 5s | 18G |
1000 | 14d | 1s | 910G |
1000 | 14d | 5s | 180G |
4.2 為檢查點(Checkpoint)計算硬盤用量
檢查點操作用于將內(nèi)存中的活躍樣本暫存到某硬盤文件中,以減少由于程序崩潰或機器掉電等引起的數(shù)據(jù)丟失。其硬盤用量與活躍樣本的內(nèi)存用量持平即可:
$$checkpoint_disk=sample_mem_1$$
五. 總結(jié)
本文中,我們首先討論了如何計算所觀測的樣本總量。特別的,Node Exporter 有 251 個測量點,Prometheus 服務(wù)本身有 775 個測量點。
進行內(nèi)存用量規(guī)劃時,我們主要關(guān)注留存于內(nèi)存中的活躍樣本與位于持久化隊列中的過期樣本。索引數(shù)據(jù)所需的內(nèi)存較少,一個經(jīng)驗公式為,每一千個時間序列大約需要 1M 內(nèi)存。
Prometheus 對硬盤的使用主要集中在對樣本數(shù)據(jù)的持久化上。當(dāng)文件過大時,Prometheus 會對文件執(zhí)行收縮操作。收縮操作的觸發(fā)由文件的收縮比控制,該選項的默認值為 $$10%$$。
請注意,數(shù)據(jù)對內(nèi)存和硬盤的使用情況由眾多因素共同影響,例如,數(shù)據(jù)本身的性質(zhì),內(nèi)存性能,硬盤性能,垃圾回收機制,內(nèi)存碎片等。對存儲用量作出準確的預(yù)估是困難的。本文給出的公式在評估數(shù)據(jù)量級時有參考意義,對于實際的調(diào)優(yōu)工作,還需要對線上環(huán)境進行深入而詳盡的觀察和測量之后方可完成。