讀:本文由梯度科技云管研發(fā)部高級(jí)工程師周宇明撰寫,共分為7章,緊密圍繞Prometheus的基本原理與開發(fā)指南展開介紹:
1.1.監(jiān)控的作用 ★
為了構(gòu)建穩(wěn)定性保障體系,核心就是在干一件事:減少故障。
減少故障有兩個(gè)層面的意思,一個(gè)是做好常態(tài)預(yù)防,不讓故障發(fā)生;另一個(gè)是如果故障發(fā)生,要能盡快止損,減少故障時(shí)長(zhǎng),減小故障影響范圍。監(jiān)控的典型作用就是幫助我們發(fā)現(xiàn)及定位故障。
監(jiān)控的其他作用:日常巡檢、性能調(diào)優(yōu)的數(shù)據(jù)佐證、提前發(fā)現(xiàn)一些不合理的配置。
之所以能做到這些,是因?yàn)樗袃?yōu)秀的軟件,都內(nèi)置了監(jiān)控?cái)?shù)據(jù)的暴露方法,讓用戶可以對(duì)其進(jìn)行觀測(cè),了解其健康狀況:比如各類開源組件,有的是直接暴露了 Prometheus metrics 接口,有的是暴露了 HTTP JSON 接口,有的是通過 JMX 暴露監(jiān)控?cái)?shù)據(jù),有的則需要連上去執(zhí)行命令。另外,所有軟件都可以使用日志的方式來暴露健康狀況。
因此,可被監(jiān)控和觀測(cè),也是我們開發(fā)軟件時(shí)必須考慮的一環(huán)。
1.2.監(jiān)控架構(gòu)分類 ★
定義:可進(jìn)行聚合計(jì)算的原子型數(shù)據(jù),通常通過多個(gè)標(biāo)簽值來確定指標(biāo)唯一性。
特點(diǎn):指標(biāo)數(shù)據(jù)僅記錄時(shí)間戳和對(duì)應(yīng)的指標(biāo)數(shù)值,通常存儲(chǔ)在時(shí)間序列數(shù)據(jù)庫(kù)中(TSDB),存儲(chǔ)成本低,可用于渲染趨勢(shì)圖或柱狀圖,可靈活配置告警規(guī)則,對(duì)故障進(jìn)行快速發(fā)現(xiàn)和響應(yīng);但是不適合用于定位故障原因。
實(shí)現(xiàn)方案:Zabbix、Open-Falcon、Prometheus
定義:離散事件,是系統(tǒng)運(yùn)行時(shí)發(fā)生的一個(gè)個(gè)事件的記錄。
特點(diǎn):日志數(shù)據(jù)可以記錄詳細(xì)的信息(請(qǐng)求響應(yīng)參數(shù)、自定義文字描述、異常信息、時(shí)間戳等),一般用于排查具體問題;日志通常存儲(chǔ)在文件中,數(shù)據(jù)非結(jié)構(gòu)化,存儲(chǔ)成本高,不適合作為監(jiān)控?cái)?shù)據(jù)的來源。
實(shí)現(xiàn)方案:ELK、Loki
定義:基于特定請(qǐng)求作用域下的所有調(diào)用信息。
特點(diǎn):一般需要依賴第三方存儲(chǔ),在微服務(wù)中一般有多個(gè)調(diào)用信息,如從網(wǎng)關(guān)開始,A服務(wù)調(diào)用B服務(wù),調(diào)用數(shù)據(jù)庫(kù)、緩存等。在鏈路系統(tǒng)中,需要清楚展現(xiàn)某條調(diào)用鏈中從主調(diào)方到被調(diào)方內(nèi)部所有的調(diào)用信息。不僅有利于梳理接口及服務(wù)間調(diào)用的關(guān)系,還有助于排查慢請(qǐng)求或故障產(chǎn)生的原因。
實(shí)現(xiàn)方案:jaeger、zipkin、Skywalking
企業(yè)級(jí)的開源解決方案,擅長(zhǎng)設(shè)備、網(wǎng)絡(luò)、中間件的監(jiān)控。
優(yōu)點(diǎn):
缺點(diǎn):
Open-Falcon 最初來自小米,14 年開源,當(dāng)時(shí)小米有 3 套 Zabbix,1 套業(yè)務(wù)性能監(jiān)控系統(tǒng) perfcounter。Open-Falcon 的初衷是想做一套大一統(tǒng)的方案,來解決這個(gè)亂局。
優(yōu)點(diǎn):
缺點(diǎn):
Prometheus 的設(shè)計(jì)思路來自Borgmon,就像 Borgmon 是為 Borg 而生的,而 Prometheus 就是為 Kubernetes 而生的。提供了多種服務(wù)發(fā)現(xiàn)機(jī)制,大幅簡(jiǎn)化了 Kubernetes 的監(jiān)控。
Prometheus2.0版本開始,重新設(shè)計(jì)了時(shí)序庫(kù),性能和可靠性都大幅提升。
優(yōu)點(diǎn):
缺點(diǎn):
有兩種典型的部署方式,一種是跟隨監(jiān)控對(duì)象部署,比如所有的機(jī)器上都部署一個(gè)采集器,采集機(jī)器的 CPU、內(nèi)存、硬盤、IO、網(wǎng)絡(luò)相關(guān)的指標(biāo);另一種是遠(yuǎn)程探針式,比如選取一個(gè)中心機(jī)器做探針,同時(shí)探測(cè)很多個(gè)機(jī)器的 PING 連通性,或者連到很多 MySQL 實(shí)例上去,執(zhí)行命令采集數(shù)據(jù)。
Telegraf:
InfluxData 公司的產(chǎn)品,主要配合 InfluxDB 使用。Telegraf 也可以把監(jiān)控?cái)?shù)據(jù)推給 Prometheus存儲(chǔ);
Telegraf 是指標(biāo)領(lǐng)域的 All-In-One 采集器,支持各種采集插件,只需要使用這一個(gè)采集器,就能解決絕大部分采集需求;
Telegraf 采集的很多數(shù)據(jù)都是字符串類型,但如果把這類數(shù)據(jù)推給 Prometheus 生態(tài)的時(shí)序庫(kù),比如 VictoriaMetrics、M3DB、Thanos 等,它就會(huì)報(bào)錯(cuò)。
Exporter
Exporter是專門用于Prometheus 生態(tài)的采集器,但是比較零散,每個(gè)采集目標(biāo)都有對(duì)應(yīng)的 Exporter 組件,比如 MySQL 有 mysqld_exporter,Redis 有 redis_exporter,JVM 有 jmx_exporter。
Exporter 的核心邏輯,就是去這些監(jiān)控對(duì)象里采集數(shù)據(jù),然后暴露為 Prometheus 協(xié)議的監(jiān)控?cái)?shù)據(jù)。比如 mysqld_exporter,就是連上 MySQL,執(zhí)行一些類似于 show global status 、show global variables 、show slave status 這樣的命令,拿到輸出,再轉(zhuǎn)換為 Prometheus 協(xié)議的數(shù)據(jù);
很多中間件都內(nèi)置支持了 Prometheus,直接通過自身的 /metrics 接口暴露監(jiān)控?cái)?shù)據(jù),不用再單獨(dú)伴生 Exporter;比如 Kubernetes 中的各類組件,比如 etcd,還有新版本的 ZooKeeper、 RabbitMQ;
不管是Exporter還是支持Prometheus協(xié)議的各類組件,都是提供 HTTP 接口(通常是 /metrics )來暴露監(jiān)控?cái)?shù)據(jù),讓監(jiān)控系統(tǒng)來拉,這叫做 PULL 模型。
Grafana-Agent
Grafana 公司推出的一款 All-In-One 采集器,不但可以采集指標(biāo)數(shù)據(jù),也可以采集日志數(shù)據(jù)和鏈路數(shù)據(jù)。
如何快速集成各類采集能力的呢?Grafana-Agent 寫了個(gè)框架,方便導(dǎo)入各類 Exporter,把各個(gè) Exporter 當(dāng)做 Lib 使用,常見的 Node-Exporter、Kafka-Exporter、Elasticsearch-Exporter、Mysqld-Exporter 等,都已經(jīng)完成了集成。對(duì)于默認(rèn)沒有集成進(jìn)去的 Exporter,Grafana-Agent 也支持用 PULL 的方式去抓取其他 Exporter 的數(shù)據(jù),然后再通過 Remote Write 的方式,將采集到的數(shù)據(jù)轉(zhuǎn)發(fā)給服務(wù)端。
很多時(shí)候,一個(gè)采集器可能搞不定所有業(yè)務(wù)需求,使用一款主力采集器,輔以多款其他采集器是大多數(shù)公司的選擇。
Prometheus TSDB
Prometheus本地存儲(chǔ)經(jīng)歷過多個(gè)迭代:V1.0(2012年)、V2.0(2015年)、V3.0(2017年)。最初借用第三方數(shù)據(jù)庫(kù)LevelDB,1.0版本性能不高,每秒只能存儲(chǔ)5W個(gè)樣本;2.0版本借鑒了Facebook Gorilla壓縮算法,將每個(gè)時(shí)序數(shù)據(jù)以單個(gè)文件方式保存,將性能提升到每秒存儲(chǔ)8W個(gè)樣本;2017年開始引入時(shí)序數(shù)據(jù)庫(kù)的3.0版本,并成立了Prometheus TSDB開源項(xiàng)目,該版本在單機(jī)上提高到每秒存儲(chǔ)百萬個(gè)樣本。
3.0版本保留了2.0版本高壓縮比的分塊保存方式,并將多個(gè)分塊保存到一個(gè)文件中,通過創(chuàng)建一個(gè)索引文件避免產(chǎn)生大量的小文件;同時(shí)為了防止數(shù)據(jù)丟失,引入了WAL機(jī)制。
InfluxDB
InfluxDB 針對(duì)時(shí)序存儲(chǔ)場(chǎng)景專門設(shè)計(jì)了存儲(chǔ)引擎、數(shù)據(jù)結(jié)構(gòu)、存取接口,國(guó)內(nèi)使用范圍比較廣泛,可以和 Grafana、Telegraf 等良好整合,生態(tài)是非常完備的。
不過 InfluxDB 開源版本是單機(jī)的,沒有開源集群版本。
M3DB
M3DB 是 Uber 的時(shí)序數(shù)據(jù)庫(kù),M3 在 Uber 抗住了 66 億監(jiān)控指標(biāo),這個(gè)量非常龐大。其主要包括4個(gè)組件:M3DB、M3 Coordinator、M3 Query、M3 Aggregator,我們當(dāng)前產(chǎn)品中Prometheus的遠(yuǎn)程存儲(chǔ)就是通過M3DB實(shí)現(xiàn)的。
用戶會(huì)配置數(shù)百甚至數(shù)千條告警規(guī)則,一些超大型的公司可能要配置數(shù)萬條告警規(guī)則。每個(gè)規(guī)則里含有數(shù)據(jù)過濾條件、閾值、執(zhí)行頻率等,有一些配置豐富的監(jiān)控系統(tǒng),還支持配置規(guī)則生效時(shí)段、持續(xù)時(shí)長(zhǎng)、留觀時(shí)長(zhǎng)等。
告警引擎通常有兩種架構(gòu),一種是數(shù)據(jù)觸發(fā)式,一種是周期輪詢式。
數(shù)據(jù)觸發(fā)式,是指服務(wù)端接收到監(jiān)控?cái)?shù)據(jù)之后,除了存儲(chǔ)到時(shí)序庫(kù),還會(huì)轉(zhuǎn)發(fā)一份數(shù)據(jù)給告警引擎,告警引擎每收到一條監(jiān)控?cái)?shù)據(jù),就要判斷是否關(guān)聯(lián)了告警規(guī)則,做告警判斷。因?yàn)楸O(jiān)控?cái)?shù)據(jù)量比較大,告警規(guī)則的量也可能比較大,所以告警引擎是會(huì)做分片部署的,這樣的架構(gòu),即時(shí)性很好,但是想要做指標(biāo)關(guān)聯(lián)計(jì)算就很麻煩,因?yàn)椴煌闹笜?biāo)哈希后可能會(huì)落到不同的告警引擎實(shí)例。
周期輪詢式,通常是一個(gè)規(guī)則一個(gè)協(xié)程,按照用戶配置的執(zhí)行頻率,周期性查詢判斷即可,做指標(biāo)關(guān)聯(lián)計(jì)算就會(huì)很容易。像 Prometheus、Nightingale、Grafana 等,都是這樣的架構(gòu)。
生成事件之后,通常是交給一個(gè)單獨(dú)的模塊來做告警發(fā)送,這個(gè)模塊負(fù)責(zé)事件聚合、收斂,根據(jù)不同的條件發(fā)送給不同的接收者和不同的通知媒介。
監(jiān)控?cái)?shù)據(jù)的可視化也是一個(gè)非常通用且重要的需求,業(yè)界做得最成功的是Grafana,采用插件式架構(gòu),可以支持不同類型的數(shù)據(jù)源,圖表非常豐富,基本是開源領(lǐng)域的事實(shí)標(biāo)準(zhǔn)。
2.1.主要特點(diǎn)
2.2. 局限性
2.3. 架構(gòu)剖析 ★
prometheus監(jiān)控探針,共收錄有上千種Exporter,用于對(duì)第三方系統(tǒng)進(jìn)行監(jiān)控,方式是獲取第三方系統(tǒng)的監(jiān)控?cái)?shù)據(jù)然后按照Prometheus的格式暴露出來;沒有Exporter探針的第三方系統(tǒng)也可以自己定制開發(fā)。
不過Exporter種類繁多會(huì)導(dǎo)致維護(hù)壓力大,也可以考慮用Influx Data公司開源的Telegraf統(tǒng)一進(jìn)行管理。使用Telegraf集成Prometheus比單獨(dú)使用Prometheus擁有更低的內(nèi)存使用率和CPU使用率。
是支持臨時(shí)性job主動(dòng)推送指標(biāo)的中間網(wǎng)關(guān)。
使用場(chǎng)景:臨時(shí)/短作業(yè)、批處理作業(yè)、應(yīng)用程序與Prometheus之間有防火墻或不在同一個(gè)網(wǎng)段;
不過該解決方案存在單點(diǎn)故障問題、必須使用PushGateway的API從推送網(wǎng)關(guān)中刪除過期指標(biāo)。
可以使用Kubernetes的API獲取容器信息的變化來動(dòng)態(tài)更新監(jiān)控對(duì)象;
從Job、Exporter、PushGateway3個(gè)組件中通過HTTP輪詢的形式拉取指標(biāo)數(shù)據(jù);
本地存儲(chǔ):直接保存到本地磁盤,從性能上考慮,建議使用SSD且不要保存超過一個(gè)月的數(shù)據(jù);
遠(yuǎn)程存儲(chǔ):適用于存儲(chǔ)大量監(jiān)控?cái)?shù)據(jù),支持的遠(yuǎn)程存儲(chǔ)包括OpenTSDB、InfluxDB、M3DB、PostgreSQL等;需要配合中間層適配器進(jìn)行轉(zhuǎn)換;
多維度數(shù)據(jù)模型的靈活查詢。
實(shí)際工作中使用Grafana,也可以調(diào)用HTTP API發(fā)送請(qǐng)求獲取數(shù)據(jù);
獨(dú)立的告警組件,可以將多個(gè)AlertManager配置成集群,支持集群內(nèi)多個(gè)實(shí)例間通信;
按照一定的時(shí)間間隔產(chǎn)生的一個(gè)個(gè)數(shù)據(jù)點(diǎn),這些數(shù)據(jù)點(diǎn)按照時(shí)間戳和值的生成順序存放,得到了向量(vector)。
每條時(shí)間序列是通過指標(biāo)名稱和一組標(biāo)簽集來命名的。
矩陣中每一個(gè)點(diǎn)都可以稱之為一個(gè)樣本(Sample),主要有3方面構(gòu)成:
指標(biāo)(Metrics):包括指標(biāo)名稱(__name__)和一組標(biāo)簽集名稱;
時(shí)間戳(TimeStamp):默認(rèn)精確到毫秒;
樣本值(Value):默認(rèn)使用64位浮點(diǎn)類型。
時(shí)間序列的指標(biāo)可以基于Bigtable設(shè)計(jì)為Key-Value存儲(chǔ)的方式:
Prometheus的Metrics可以有兩種表現(xiàn)方式(指標(biāo)名稱只能由ASCII字符、數(shù)字、下劃線、冒號(hào)組成,冒號(hào)用來表示用戶自定義的記錄規(guī)則):
分別對(duì)應(yīng)的查詢形式(以下兩個(gè)查詢語句等價(jià)):
所有PromQL語句必須包含至少一個(gè)有效表達(dá)式(至少一個(gè)不會(huì)匹配到空字符串的標(biāo)簽過濾器),因此,以下三種示例是非法的:
用于返回在指定時(shí)間戳之前查詢到的最新樣本的瞬時(shí)向量。
高級(jí)應(yīng)用:
瞬時(shí)偏移向量
高級(jí)應(yīng)用:
只增不減,一般配合rate(統(tǒng)計(jì)時(shí)間區(qū)間內(nèi)增長(zhǎng)速率)、topk(統(tǒng)計(jì)top N的數(shù)據(jù))、increase等函數(shù)使用;
increase(v range-vector)獲取區(qū)間向量的第一個(gè)和最后一個(gè)樣本并返回其增長(zhǎng)量:
為什么increase函數(shù)算出來的值非33?真實(shí)計(jì)算公式:(360 - 327) / (1687922987 - 1687922882) * 120=37.71428571428571
irate(v range-vector)是針對(duì)長(zhǎng)尾效應(yīng)專門提供的用于計(jì)算區(qū)間向量的增長(zhǎng)速率的函數(shù),反應(yīng)的是瞬時(shí)增長(zhǎng)率,敏感度更高。長(zhǎng)期趨勢(shì)分析或告警中更推薦rate函數(shù)。
rate(v range-vector) 求取的是每秒變化率,也有數(shù)據(jù)外推的邏輯,increase 的結(jié)果除以 range-vector 的時(shí)間段的大小,就是 rate 的值。
rate(jvm_memory_used_bytes{id="PS Eden Space"}[1m]) 與 increase(jvm_memory_used_bytes{id="PS Eden Space"}[1m])/60.0 是等價(jià)的
表示樣本數(shù)據(jù)可任意增減的指標(biāo);實(shí)際更多用于求和、取平均值、最大值、最小值。
without可以讓sum函數(shù)根據(jù)相同的標(biāo)簽進(jìn)行求和,但是忽略掉without函數(shù)覆蓋的標(biāo)簽;如上圖,可以忽略掉id,只按照堆/非堆的區(qū)別進(jìn)行內(nèi)存空間求和。
用于描述數(shù)據(jù)分布,最典型的應(yīng)用場(chǎng)景就是監(jiān)控延遲數(shù)據(jù),計(jì)算 90 分位、99 分位的值。
有些服務(wù)訪問量很高,每秒幾百萬次,如果要把所有請(qǐng)求的延遲數(shù)據(jù)全部拿到,排序之后再計(jì)算分位值,這個(gè)代價(jià)就太高了。使用 Histogram 類型,可以用較小的代價(jià)計(jì)算一個(gè)大概值。
Prometheus的Histogram類型計(jì)算原理:bucket桶排序+假定桶內(nèi)數(shù)據(jù)均勻分布。
Histogram 這種做法性能有了巨大的提升,但是要同時(shí)計(jì)算成千上萬個(gè)接口的分位值延遲數(shù)據(jù),還是非常耗費(fèi)資源的,甚至?xí)斐煞?wù)端 OOM。
數(shù)據(jù)解析:http://ip:9090/metrics prometheus_http_request_duration_seconds
在客戶端計(jì)算分位值,然后把計(jì)算之后的結(jié)果推給服務(wù)端存儲(chǔ),展示的時(shí)候直接查詢即可。
Summary 的計(jì)算是在客戶端計(jì)算的,也就意味著不是全局(整個(gè)服務(wù))的分位值,分位值延遲數(shù)據(jù)是進(jìn)程粒度的。
負(fù)載均衡會(huì)把請(qǐng)求均勻地打給后端的多個(gè)實(shí)例。一個(gè)實(shí)例內(nèi)部計(jì)算的分位值,理論上和全局計(jì)算的分位值差別不會(huì)很大。另外,如果某個(gè)實(shí)例有故障,比如硬盤問題,導(dǎo)致落在這個(gè)實(shí)例的請(qǐng)求延遲大增,我們?cè)趯?shí)例粒度計(jì)算的延遲數(shù)據(jù)反而更容易發(fā)現(xiàn)問題。
數(shù)據(jù)解析:http://ip:9090/metrics go_gc_duration_seconds
上述兩個(gè)查詢是等價(jià)的;同一個(gè)聚合語句中不可同時(shí)使用by和without,by的作用類似于sql語句中的分組(group by),without語義是:除開XX標(biāo)簽,對(duì)剩下的標(biāo)簽進(jìn)行分組。
數(shù)學(xué)中稱為方差,用于衡量一組數(shù)據(jù)的離散程度:數(shù)據(jù)分布得越分散,各個(gè)數(shù)據(jù)與平均數(shù)的差的平方和越大,方差就越大。
標(biāo)準(zhǔn)差:用方差開算術(shù)平方根。
count:對(duì)分組中時(shí)間序列的數(shù)目進(jìn)行求和
count_values:表示時(shí)間序列中每一個(gè)樣本值(value)出現(xiàn)的次數(shù),實(shí)踐中一般用于統(tǒng)計(jì)版本號(hào)。
用于計(jì)算當(dāng)前樣本數(shù)據(jù)值的分布情況,例如計(jì)算一組http請(qǐng)求次數(shù)的中位數(shù):
僅用于瞬時(shí)向量之間,and(并且)、or(或者)、unless(排除)
內(nèi)置函數(shù)absent扮演了not的角色;
absent應(yīng)用場(chǎng)景,配置告警規(guī)則:
提供了對(duì)時(shí)間序列標(biāo)簽的自定義能力。
label_replace(input_vector, "dst", "replacement", "src", "regex")
label_join(input_vector, "dst", "separator", "src_1", "src_2" ...)
resets函數(shù)用于統(tǒng)計(jì)計(jì)數(shù)器重置次數(shù),兩個(gè)連續(xù)的樣本之間值減少,被認(rèn)為是一次計(jì)數(shù)器重置,相當(dāng)于是進(jìn)程重啟次數(shù)。
預(yù)測(cè)時(shí)間序列v在t秒后的值
使用簡(jiǎn)單的線性回歸計(jì)算區(qū)間向量v中各個(gè)時(shí)間序列的導(dǎo)數(shù)
計(jì)算區(qū)間向量?jī)?nèi)第一個(gè)元素和最后一個(gè)元素的差值:
最新的兩個(gè)樣本值之間的差值,如上圖例子,返回值為整數(shù)
要求sf > 0, tf <=1
霍爾特-溫特雙指數(shù)平滑算法,暫時(shí)想不到應(yīng)用場(chǎng)景
返回區(qū)間向量中每個(gè)樣本數(shù)據(jù)值變化的次數(shù),如果樣本值沒有變化就返回1;
prometheus提供度量標(biāo)準(zhǔn)process_start_time_seconds記錄每一個(gè)targets的啟動(dòng)時(shí)間,該時(shí)間被更改則意味著進(jìn)程重啟,可以發(fā)出循環(huán)崩潰告警:
expr: avg wtihout(instance) (changes{process_start_time_seconds [1h]}) > 3
調(diào)用成功會(huì)返回2XX狀態(tài)碼
resultType: matrix(區(qū)間向量) | vector(瞬時(shí)向量) | scalar | string
入?yún)ⅲ篜romQL表達(dá)式、時(shí)間戳、超時(shí)設(shè)置(可全局設(shè)置)
入?yún)ⅲ篜romQL表達(dá)式、起始時(shí)間戳、結(jié)束時(shí)間戳、查詢時(shí)間步長(zhǎng)(不能超過11000)、超時(shí)設(shè)置(可全局設(shè)置)
啟動(dòng)參數(shù)帶上--web.enable-admin-api
執(zhí)行以下命令可對(duì)數(shù)據(jù)庫(kù)進(jìn)行備份:
curl -X POST http://your_ip:9090/api/v1/admin/tsdb/snapshot
備份目錄:/prometheus/data/snapshot
刪除序列:http:// your_ip:9090/api/v1/admin/tsdb/delete_series
釋放空間:http:// your_ip:9090/api/v1/admin/tsdb/clean_tombstones
預(yù)先計(jì)算經(jīng)常需要用到的或計(jì)算量較大的表達(dá)式,并將結(jié)果保存為一組新的時(shí)間序列。
抓取前依賴服務(wù)發(fā)現(xiàn),通過relabel_configs的方式自動(dòng)對(duì)服務(wù)發(fā)現(xiàn)的目標(biāo)進(jìn)行重新標(biāo)記;
抓取后主要指標(biāo)保存在存儲(chǔ)系統(tǒng)之前,依賴作業(yè)內(nèi)的metrics_relabel_configs實(shí)現(xiàn)。
重寫instance實(shí)現(xiàn)告警同時(shí)顯示服務(wù)名+IP端口
將監(jiān)控不需要的數(shù)據(jù)直接丟掉,不在prometheus保存,配置方法類似。
從左上開始,Prometheus 發(fā)送的警報(bào)到 Alertmanager;
(word不方便添加代碼塊,如果公眾號(hào)可以添加代碼塊,上圖內(nèi)容可以單獨(dú)提供代碼)
關(guān)鍵配置參數(shù):
prometheus.yml
alertmanager.yml
主要包括4個(gè)組件:M3DB、M3 Coordinator、M3 Query、M3 Aggregator
前有網(wǎng)友提出,想要用代碼監(jiān)控一個(gè)接口,定時(shí)訪問它,如果接口返回值發(fā)生某些變化就提醒用戶。
于是,我寫了個(gè)簡(jiǎn)單的腳本。
腳本編寫時(shí),考慮的是放在目標(biāo)網(wǎng)站的控制臺(tái)來執(zhí)行。之所以這樣做,是因?yàn)槿绻旁陧撁嫱獠繄?zhí)行,往往需要補(bǔ)環(huán)境,費(fèi)時(shí)費(fèi)力。
// 變量聲明&定時(shí)器
let _timer=null;
let _subjects=[];
_timer=setInterval(()=> {
getData()
}, 60000);
// 接口訪問
function getData () {
return fetch("https://mail.126.com/xxxx", {
"xxx": {},
}).then((res)=> {
res.text().then((str)=> {
str=(str || '').replace(/\n/g, '')
let subjects=str.match(/('subject':'.*?',)/g)
if (_subjects.length===0) {
_subjects=subjects
} else if (subjects[0] !==_subjects[0]) {
notificationHandler();
}
})
}).catch(err=> {
console.log('err:', err)
});
}
// 發(fā)送通知
function notificationHandler () {
let notification;
if (window.Notification && Notification.permission==='granted') {
notification=new Notification('收到新郵件啦', {
dir: 'ltr',
body: `收到新郵件啦,快去看看吧`
});
} else if (Notification.permission !=='denied') {
Notification.requestPermission().then(function(permission) {
if (permission==='granted') {
notification=new Notification('收到新郵件啦', {
dir: 'ltr',
body: `收到新郵件啦,快去看看吧`
});
}
});
}
if (notification) {
notification.onclick=()=> {
window.focus();
};
}
}
上述代碼中的相關(guān)邏輯是以郵箱收件箱為例。
將代碼放到控制臺(tái)執(zhí)行后,每隔1分鐘訪問一次接口,當(dāng)響應(yīng)內(nèi)容有變化時(shí),會(huì)向用戶發(fā)送系統(tǒng)通知;當(dāng)用戶點(diǎn)擊通知面板時(shí),系統(tǒng)就會(huì)將焦點(diǎn)給到受監(jiān)控的網(wǎng)頁,方便用戶對(duì)網(wǎng)頁進(jìn)行查看。
1)要求瀏覽器支持Notification這個(gè)API,這個(gè)API對(duì)應(yīng)的就是系統(tǒng)右下角的通知功能,目前主流瀏覽器都是支持的。
系統(tǒng)通知
2)在控制臺(tái)運(yùn)行代碼前,需要用戶已經(jīng)授權(quán)瀏覽器可以使用Notification權(quán)限,如果不知道是否允許,可以在控制臺(tái)執(zhí)行代碼:
Notification.requestPermission().then(function(permission) {console.log(permission)})
返回值為 granted 說明是已授權(quán)的;
如果不是,那么瀏覽器會(huì)彈出提示詢問我們是否允許;
如果權(quán)限是denied,而且看不到彈窗,那么可以重啟瀏覽器再做嘗試。
申請(qǐng)權(quán)限
前一直覺得監(jiān)控告警是件很神奇的事情,仿佛可望不可及,今天我們就一起來解開它神秘的面紗哈哈~~
我的電腦是win10系統(tǒng),我在電腦上安裝了Docker Desktop軟件,使用docker部署的
prometheus、pushgateway和alertmanager。
一、拉取prometheus、pushgateway和alertmanager的鏡像,命令很簡(jiǎn)單:
docker pull prom/prometheus
docker pull prom/pushgateway
docker pull prom/alertmanager
可以通過docker images命令查看鏡像是否拉取成功。
二、配置prometheus,創(chuàng)建prometheus.yml
global:
scrape_interval: 60s
evaluation_interval: 60s
alerting:
alertmanagers:
- static_configs:
- targets: ["ip:9093"] #這里是alertmanager的地址,注意這個(gè)地址是宿主機(jī)的地址,不可以寫localhost或者127.0.0.1,下面的ip同理
rule_files:
- "rule/*.yml" #alertmanager的告警規(guī)則文件
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['ip:9090']
labels:
instance: prometheus
- job_name: pushgateway
static_configs:
- targets: ['ip:9091']
labels:
instance: pushgateway
可以在rule文件夾下創(chuàng)建一個(gè)test_rule.yml
groups:
- name: test_rule
rules:
- alert: chat接口超時(shí)1500ms個(gè)數(shù) # 告警名稱
expr: test_metric > 0 # 告警的判定條件,參考Prometheus高級(jí)查詢來設(shè)定
for: 1m # 滿足告警條件持續(xù)時(shí)間多久后,才會(huì)發(fā)送告警
labels: #標(biāo)簽項(xiàng)
team: node
annotations: # 解析項(xiàng),詳細(xì)解釋告警信息
summary: "異常服務(wù)節(jié)點(diǎn):{{$labels.exported_instance}}"
description: "異常節(jié)點(diǎn):{{$labels.exported_instance}}: 異常服務(wù)名稱: {{$labels.Service_Name}} "
value: "chat接口超時(shí)1500ms個(gè)數(shù):{{$value}}"
其中exported_instance和Service_Name都是我們往pushgateway中推送的數(shù)據(jù),通過{{$labels.xxx}}的形式可以獲取到
三、配置alertmanager.yml,創(chuàng)建alertmanager.yml
global:
resolve_timeout: 5m #處理超時(shí)時(shí)間,默認(rèn)為5min
smtp_smarthost: 'smtp.126.com:25' # 郵箱smtp服務(wù)器代理,我這里是126的
smtp_from: '###@126.com' # 發(fā)送郵箱名稱=郵箱名稱
smtp_auth_username: '###@126.com' # 郵箱名稱=發(fā)送郵箱名稱
smtp_auth_password: '#####' # 授權(quán)碼
smtp_require_tls: false
smtp_hello: '126.com'
templates:
- 'test.tmpl' #告警信息模板
route:
group_by: ['alertname'] #報(bào)警分組依據(jù)
group_wait: 10s #最初即第一次等待多久時(shí)間發(fā)送一組警報(bào)的通知
group_interval: 10m # 在發(fā)送新警報(bào)前的等待時(shí)間
repeat_interval: 1h # 發(fā)送重復(fù)警報(bào)的周期 對(duì)于email配置中,此項(xiàng)不可以設(shè)置過低,>否則將會(huì)由于郵件發(fā)送太多頻繁,被smtp服務(wù)器拒絕
receiver: 'email' # 發(fā)送警報(bào)的接收者的名稱,以下receivers name的名稱
receivers:
- name: 'email'
email_configs: # 郵箱配置
- to: '###@126.com' # 接收警報(bào)的email配置
headers: { Subject: "[WARN] 報(bào)警郵件"} # 接收郵件的標(biāo)題
send_resolved: true
html: '{{ template "test.html" .}}' #這個(gè)test.html就是模板中define的名稱,需要對(duì)應(yīng)起來
webhook_configs:
- url: 'http://ip:9093/alertmanager/hook' #這個(gè)是alertmanager的地址,ip也是宿主機(jī)的ip
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
再配置test.tmpl
{{ define "test.html" }}
<table border="1">
<tr>
<td>報(bào)警項(xiàng)</td>
<td>實(shí)例</td>
<td>報(bào)警閥值</td>
<td>開始時(shí)間</td>
</tr>
{{ range $i, $alert :=.Alerts }}
<tr>
<td>{{ index $alert.Labels "alertname" }}</td>
<td>{{ index $alert.Labels "instance" }}</td>
<td>{{ index $alert.Annotations "value" }}</td>
<td>{{ $alert.StartsAt }}</td>
</tr>
{{ end }}
</table>
{{ end }}
配置結(jié)束,下面開始啟動(dòng)容器
一、啟動(dòng)pushgateway:docker run -d --name=pushgateway -p 9091:9091 prom/pushgateway
可以登錄http://localhost:9091/查看:
二、啟動(dòng)alertmanager
docker run -d -p 9093:9093 --restart=always --name=alertmanager -v 宿主機(jī)的alertmanager.yml地址:/etc/alertmanager/alertmanager.yml -v 宿主機(jī)的test.tmpl地址:/etc/alertmanager/test.tmpl prom/alertmanager:latest
登錄http://localhost:9093/查看:
三、啟動(dòng)prometheus容器
docker run -d -p 9090:9090 --restart=always --name=prometheus -v 宿主機(jī)的prometheus.yml地址:/etc/prometheus/prometheus.yml -v 宿主機(jī)的rule文件夾路徑:/etc/prometheus/rule/ prom/prometheus
登錄 http://localhost:9090/查看:
查看監(jiān)控情況:
此時(shí)環(huán)境已經(jīng)全部部署完畢,下面可以往pushgateway中推送數(shù)據(jù),查看告警情況
echo "test_metric 2" | curl --data-binary @- http://127.0.0.1:9091/metrics/job/test_job/instance/192.168.0.1/Service_Name/ai_sym_interface
這個(gè)命令的意思是向job為test_job中推送數(shù)據(jù),instance為192.168.0.1,Service_Name為ai_sym_interface,值為2
可登錄pushgateway查看推送情況:
由于prometheus監(jiān)控了pushgateway的數(shù)據(jù)指標(biāo),所以在prometheus中也可以看到這條數(shù)據(jù):
由于我們配置了test_rule.yml,當(dāng)test_metric大于0并持續(xù)一秒會(huì)發(fā)送,報(bào)警郵件:
至此,郵箱告警就完成了,其他的告警也是同樣的道理,可以繼續(xù)研究,加油~!
原文鏈接:記憶旅途
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。