背景
目前階段牲剃,我司主要監(jiān)控告警系統(tǒng)使用的是 Zabbix德澈,對(duì)于基礎(chǔ)設(shè)施及應(yīng)用服務(wù)狀態(tài)監(jiān)控祭刚,Zabbix 內(nèi)建或由社區(qū)貢獻(xiàn)了諸多模板,可通過在頁(yè)面上遠(yuǎn)程配置或?qū)⒉杉_本下發(fā)至 Zabbix Agent 端進(jìn)行使用好啰。業(yè)務(wù)發(fā)展至今,除遇到一些并發(fā)上的性能問題外儿奶,基本能滿足我們對(duì)于基礎(chǔ)硬件框往、服務(wù)設(shè)施的監(jiān)控需求。然而闯捎,對(duì)于業(yè)務(wù)類數(shù)據(jù)椰弊,如粒度細(xì)至客戶分頻道的帶寬數(shù)據(jù),使用 Zabbix 進(jìn)行監(jiān)控告警則顯得力不從心瓤鼻。
在初期秉版,我們通過自研告警程序來滿足部分業(yè)務(wù)上的需求。如流量茬祷、帶寬突增突降告警沐飘,狀態(tài)碼數(shù)量閾值告警等,程序足夠輕量并且有效,上線后也著實(shí)滿足了一些基本業(yè)務(wù)告警需求耐朴。但是借卧,隨著告警數(shù)據(jù)維度的增加以及規(guī)則復(fù)雜度的上升,迭代開發(fā)這個(gè)告警程序的代價(jià)逐漸變大筛峭。一方面铐刘,每增加一些需要監(jiān)控的業(yè)務(wù)數(shù)據(jù),就必需要數(shù)據(jù)中心提供新的數(shù)據(jù)接口影晓;另一方面镰吵,告警需求所涉及的規(guī)則都必需轉(zhuǎn)換為程序代碼,無法進(jìn)行類似 SQL 之類的標(biāo)準(zhǔn)化查詢挂签。這兩方面都導(dǎo)致每添加一個(gè)業(yè)務(wù)數(shù)據(jù)的監(jiān)控告警都需要耗費(fèi)一定的開發(fā)資源疤祭,同時(shí)業(yè)務(wù)使用方也較難進(jìn)行自定義的告警配置。
那么饵婆,我們理想中的通用業(yè)務(wù)監(jiān)控告警引擎是什么樣的呢勺馆?針對(duì)使用、開發(fā)以及未來的可拓展性侨核,我們認(rèn)為它應(yīng)該具備如下特點(diǎn):
1.能夠與業(yè)務(wù)數(shù)據(jù)源緊密結(jié)合草穆,能直接或通過最小的代價(jià)從數(shù)據(jù)源中同步到業(yè)務(wù)數(shù)據(jù)集。比如每新增一種業(yè)務(wù)數(shù)據(jù)搓译,不再需要通過開發(fā)額外的接口進(jìn)行同步悲柱,而只需利用 SQL 便能實(shí)時(shí)同步數(shù)據(jù);
2.具備通用的查詢語(yǔ)法些己,能夠以規(guī)則匹配的形式從數(shù)據(jù)源中過濾出所需的數(shù)據(jù)集豌鸡,然后使用內(nèi)置的聚合算子對(duì)數(shù)據(jù)集進(jìn)行運(yùn)算,并能以插件的形式增加聚合算子段标;
3.復(fù)雜的告警規(guī)則能夠通過組合查詢條件直颅、聚合算子的形式得以實(shí)現(xiàn);
4.觸發(fā)告警能夠以指定的形式發(fā)送至各類告警接收通道怀樟;
5.告警引擎可橫向拓展部署功偿,滿足海量監(jiān)控需求。
技術(shù)預(yù)研
由于目前我們的業(yè)務(wù)數(shù)據(jù)大部分經(jīng)過結(jié)構(gòu)化處理存儲(chǔ)于 Clickhouse 中往堡,而 Clickhouse 又具備了足夠強(qiáng)大的查詢聚合能力械荷,因此,最初我們?cè)O(shè)想能夠使用類似存儲(chǔ)過程的方式虑灰,通過在 Clickhouse 中添加持續(xù)進(jìn)行的 SQL 運(yùn)算吨瞎,并結(jié)合某種回調(diào)觸發(fā)告警。然而穆咐,Clickhouse 本身并不支持存儲(chǔ)過程颤诀。我們所能做的字旭,是開發(fā)一個(gè)獨(dú)立的服務(wù),持續(xù)不斷從 Clickhouse 中查詢業(yè)務(wù)數(shù)據(jù)并進(jìn)行規(guī)則匹配崖叫。這么做遗淳,似乎又回到了老路上,不可取心傀。
于是屈暗,換一種思路,既然一個(gè)獨(dú)立的監(jiān)控告警服務(wù)不可避免脂男,那么開源世界中有沒有這么一種引擎可直接加以應(yīng)用呢养叛?經(jīng)過調(diào)研,我們發(fā)現(xiàn) Prometheus是一個(gè)絕佳的開源解決方案宰翅。Prometheus 最初是由 SoundCloud開發(fā)弃甥,2016年加入云計(jì)算基金會(huì)(CNCF),成為 Kubernetes 之后的第二個(gè)托管項(xiàng)目汁讼。Prometheus 本身被設(shè)計(jì)為一個(gè)高性能的時(shí)序數(shù)據(jù)庫(kù)淆攻,可拉取以標(biāo)準(zhǔn)化形式呈現(xiàn)的數(shù)據(jù)并進(jìn)行存儲(chǔ),同時(shí)實(shí)現(xiàn)了一種稱為 PromQL的查詢范式掉缺,內(nèi)置數(shù)十種聚合算子。此外戈擒,Prometheus 還有一個(gè)伴生的告警管理組件 AlertManager眶明,可用于管理 Prometheus 發(fā)出的告警,并將告警信息分發(fā)至相應(yīng)的接收通道筐高。于是乎搜囱,最初需求的第 2~5 點(diǎn)似乎都能立馬得到滿足,一切看上去都很完美柑土。那么蜀肘,接下來我們只需實(shí)現(xiàn)第1點(diǎn),即數(shù)據(jù)源的互通稽屏,就能打造我們想要的業(yè)務(wù)監(jiān)控告警引擎了扮宠。下圖為Prometheus 的整體架構(gòu)。
一開始狐榔,我們以 Prometheus 標(biāo)準(zhǔn)化導(dǎo)入數(shù)據(jù)的方式坛增,開發(fā)Exporter從 Clickhouse 向 Prometheus 同步數(shù)據(jù)。由于 Prometheus 本身接收數(shù)據(jù)采用的是拉取的模式薄腻,因此這期間涉及到拉取頻率收捣、拉取時(shí)效等問題,并且不同的數(shù)據(jù)集照樣需要通過在 Exporter 中添加代碼才能進(jìn)行導(dǎo)出庵楷。這種數(shù)據(jù)同步算不上非常完美罢艾。有沒有更好的選擇呢楣颠?進(jìn)一步探索,我們發(fā)現(xiàn) Prometheus 有個(gè)很強(qiáng)大的功能咐蚯,叫Remote Storage童漩,即只要以特定的協(xié)議進(jìn)行通訊,Prometheus 不一定要將數(shù)據(jù)存放在自身的數(shù)據(jù)庫(kù)中仓蛆,可也存放在遠(yuǎn)端的其他數(shù)據(jù)源中睁冬,其工作原理如下圖所示。這意味著 Prometheus 可以作為一個(gè)純粹的告警計(jì)算引擎使用看疙。于是接下來要做的豆拨,是實(shí)現(xiàn)將 Clickhouse 作為Prometheus 的 Remote Storage。正當(dāng)想實(shí)現(xiàn)協(xié)議時(shí)能庆,發(fā)現(xiàn)強(qiáng)大的開源世界里已經(jīng)有人貢獻(xiàn)了一波施禾,Prom2Click。
于是搁胆,所有的拼圖都齊全了弥搞,結(jié)合現(xiàn)有的數(shù)據(jù)中心架構(gòu),我們想要的通用業(yè)務(wù)告警引擎的框架如下:
系統(tǒng)構(gòu)建
Clickhouse 配置
由于 Clickhouse 本身支持類 Graphite 數(shù)據(jù)表渠旁,可定期通過減少時(shí)間精度的方式壓縮舊數(shù)據(jù)攀例。我們就以這種數(shù)據(jù)表類型來存儲(chǔ) Prometheus 的數(shù)據(jù)。需要在 Clickhouse 集群每個(gè)實(shí)例的配置文件 config.xml 中最后部分添加如下內(nèi)容:
<!-- Settings for the ReplicatedGraphiteMergeTree engine. Adjust the retention and rollup entries as needed. -->
<graphite_rollup>
<path_column_name>tags</path_column_name>
<time_column_name>ts</time_column_name>
<value_column_name>val</value_column_name>
<version_column_name>updated</version_column_name>
<default>
<function>avg</function>
<retention>
<age>0</age>
<precision>10</precision>
</retention>
<retention>
<age>86400</age>
<precision>30</precision>
</retention>
<retention>
<age>172800</age>
<precision>300</precision>
</retention>
</default>
</graphite_rollup>
數(shù)據(jù)中間件部署配置
原始版本的 Prom2Click 存在無法支持配置文件顾腊、缺少 log 等問題粤铭,我們將其定制添加相應(yīng)功能后已打成 rpm 包放入內(nèi)部 YUM 源中。執(zhí)行如下命令進(jìn)行安裝:
1yum install prom2click
修改 Prom2Click 配置 /usr/local/prom2click/etc/config.yml杂靶,填寫正確的數(shù)據(jù)庫(kù)連接信息梆惯。然后啟動(dòng)服務(wù)
1systemctl start prom2click
Prometheus 部署配置
目前 Prometheus 已下載至內(nèi)部 YUM 源中,只需執(zhí)行如下指令安裝
1yum install prometheus2 alertmanager
AlertManager 是 Prometheus 用于告警管理的子模塊吗垮。其本身并不產(chǎn)生告警垛吗,而是接收 Prometheus 根據(jù)業(yè)務(wù)規(guī)則持續(xù)計(jì)算產(chǎn)生的告警數(shù)據(jù),并對(duì)其進(jìn)行管理和分發(fā)至各種通知通道烁登。
完成安裝后怯屉,在默認(rèn)情況下啟動(dòng),Prometheus 會(huì)持續(xù)采集自身性能數(shù)據(jù)饵沧,并將采集的數(shù)據(jù)保存在內(nèi)置的時(shí)序數(shù)據(jù)庫(kù)中蚀之。為了讓 Prometheus 能夠?qū)?shù)據(jù)保存于 Clickhouse 中并加以使用,我們需在 Prometheus 配置文件(默認(rèn)位于 /etc/prometheus/prometheus.yml)中添加如下配置項(xiàng)捷泞。
read_recent: true # 這個(gè)參數(shù)很重要足删,不設(shè)置會(huì)導(dǎo)致 Prometheus 讀取 Remote storage 數(shù)據(jù)有各種異常,之后重載服務(wù)
1systemctl reload prometheus
系統(tǒng)運(yùn)營(yíng)
回到最初的業(yè)務(wù)監(jiān)控需求锁右,當(dāng)需要配置某種數(shù)據(jù)源特定維度上的監(jiān)控規(guī)則時(shí)失受,應(yīng)該怎么做讶泰?摒棄先前的開發(fā)數(shù)據(jù)接口以及開發(fā)告警規(guī)則,我們現(xiàn)在只要在數(shù)據(jù)源進(jìn)行簡(jiǎn)單配置拂到,然后在 Prometheus 端編寫規(guī)則配置痪署。
數(shù)據(jù)轉(zhuǎn)換視圖
雖然現(xiàn)在業(yè)務(wù)數(shù)據(jù)和 Prometheus 所需的數(shù)據(jù)都在同一數(shù)據(jù)源內(nèi),但其存儲(chǔ)的庫(kù)兄旬、表以及結(jié)構(gòu)都不一致狼犯,因此我們需要將待監(jiān)控的業(yè)務(wù)數(shù)據(jù)集從各自的庫(kù)表中導(dǎo)入到 Prometheus 的庫(kù)表中。Clickhouse 支持 materialized view领铐,以下簡(jiǎn)稱 MV悯森,它能將一張表中的數(shù)據(jù)執(zhí)行特定的查詢語(yǔ)句后轉(zhuǎn)存至另一張表。以客戶绪撵、分頻道流量表(存放于xcloud 庫(kù)的 cdn_nginx_log_flow 表中)為例瓢姻,我們通過建立如下的 MV,將其導(dǎo)入到 metrics 庫(kù)的 samples 表中音诈。需要注意的是幻碱,這個(gè) MV 只會(huì)影響到它建立后新插入到 xcloud.cdn_nginx_log_flow 的數(shù)據(jù),如需轉(zhuǎn)換先前的數(shù)據(jù)细溅,需建立一張臨時(shí)表褥傍,然后在這張臨時(shí)表上建立同樣內(nèi)容不同名稱的臨時(shí) MV,將舊數(shù)據(jù) select 到臨時(shí)表中進(jìn)行轉(zhuǎn)換喇聊。最后再刪除臨時(shí) MV 和臨時(shí)表恍风。
此外有個(gè)風(fēng)險(xiǎn)點(diǎn)是,一旦 MV 的執(zhí)行邏輯有問題承疲,則會(huì)使數(shù)據(jù)插入到原始表中出錯(cuò)邻耕。因此新建 MV 前必須確保邏輯的正確性鸥咖,可現(xiàn)在內(nèi)網(wǎng)環(huán)境中以測(cè)試表進(jìn)行驗(yàn)證燕鸽。后續(xù)將通過工具進(jìn)行校驗(yàn) MV 的合法性。
以上 MV 將會(huì)產(chǎn)生一個(gè)名稱為 cdn_customer_flow 的關(guān)于客戶啼辣、分頻道流量的度量指標(biāo)(metric)啊研,其數(shù)據(jù)維度有 customer, channel, view 和 serverType 這四個(gè)。在 Prometheus 的查詢頁(yè)面鸥拧,我們可通過 PromQL 來對(duì)這個(gè)度量指標(biāo)進(jìn)行查詢党远,如以下語(yǔ)句
1sum by (channel) (sum_over_time(cdn_customer_flow{serverType='0'}[5m]))
可查詢最近 5m 各分頻道流量的加總。
告警規(guī)則配置
在建立數(shù)據(jù)轉(zhuǎn)換視圖后富弦,一旦有新數(shù)據(jù)插入到原始表沟娱,MV 便會(huì)持續(xù)不斷將其變換為 Prometheus 數(shù)據(jù)表所需格式。此時(shí)我們可在 Prometheus 中以標(biāo)準(zhǔn)的規(guī)則配置方法對(duì)該度量指標(biāo)進(jìn)行監(jiān)控腕柜。以下是簡(jiǎn)要的 Prometheus 配置
則通過 expr 內(nèi)的計(jì)算公式济似,我們定義了一條告警規(guī)則矫废,其內(nèi)容為:無論哪個(gè)客戶,只要最近5分鐘帶寬超過150Mbps砰蠢,且最近5分鐘與上一個(gè)5分鐘帶寬均值變化率超過 10%蓖扑,則觸發(fā)告警。Promethues 的告警會(huì)由 Alertmanager 進(jìn)行接收台舱,通過匹配告警名稱律杠、標(biāo)簽等,可將告警路由分發(fā)至不同的告警通道竞惋,比如我們可以定義一個(gè)CDN 告警的郵件組專門用于接收以上的告警郵件柜去。
Prometheus 的告警規(guī)則很強(qiáng)大,更多的資料可參考官方文檔碰声,或是一些不錯(cuò)的第三方文檔诡蜓。
后記
通過以上步驟,我們可以配置絕大多數(shù)業(yè)務(wù)數(shù)據(jù)的監(jiān)控規(guī)則胰挑,利用 Prometheus 的算子蔓罚,我們甚至可以對(duì)某些維度的數(shù)據(jù)進(jìn)行預(yù)測(cè)型監(jiān)控。但不可否認(rèn)的是瞻颂,目前 Prometheus 無論是查詢語(yǔ)言或是告警規(guī)則的配置豺谈,都有一定的學(xué)習(xí)門檻。我們后續(xù)需要做的事贡这,是將整個(gè)流程盡可能地界面化茬末,通過在網(wǎng)頁(yè)頁(yè)面上選定數(shù)據(jù)維度、聚合公式盖矫、觸發(fā)閾值丽惭、告警通道,來生成相應(yīng)的告警規(guī)則辈双,從而減輕運(yùn)營(yíng)人員的操作門檻责掏,讓整個(gè)系統(tǒng)更易運(yùn)營(yíng)。