溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

開源監(jiān)控系統(tǒng)Prometheus的前世今生

發(fā)布時(shí)間:2020-08-06 16:15:45 來源:ITPUB博客 閱讀:252 作者:沃趣科技 欄目:云計(jì)算

Prometheus是SoundCloud公司開源的監(jiān)控系統(tǒng),同時(shí)也是繼Kubernetes之后,第二個(gè)加入CNCF的項(xiàng)目。Prometheus是一個(gè)優(yōu)秀的監(jiān)控系統(tǒng),沃趣圍繞著Prometheus先后開發(fā)了多個(gè)組件,包括基礎(chǔ)告警組件,服務(wù)發(fā)現(xiàn)組件、各種采集的Exporters等,這些組件結(jié)合Prometheus支撐了沃趣大部分的監(jiān)控業(yè)務(wù)。本文主要介紹Prometheus,從他的來源,架構(gòu)以及一個(gè)具體的例子等方面來說明,以及沃趣圍繞Prometheus做了哪些工作。

起源

SoundCloud公司的之前的應(yīng)用架構(gòu)是巨石架構(gòu),也就是所有的功能放在一個(gè)大的模塊里,各個(gè)功能之間沒有明顯的界線。巨石架構(gòu)的應(yīng)用主要存在兩方面的問題,一方面在于很難對(duì)其進(jìn)行水平擴(kuò)展,只能垂直擴(kuò)展,但是單臺(tái)機(jī)器的能力畢竟是有限的;另外一方面在于各個(gè)功能耦合在一塊,新增一個(gè)功能需要在已有的技術(shù)棧上進(jìn)行開發(fā),并且要確保不會(huì)對(duì)已有的功能造成影響。于是他們轉(zhuǎn)向了微服務(wù)架構(gòu),將原有的功能拆分成了幾百個(gè)獨(dú)立的服務(wù),整個(gè)系統(tǒng)運(yùn)行上千個(gè)實(shí)例。遷移到微服務(wù)架構(gòu)給監(jiān)控帶來一定的挑戰(zhàn),現(xiàn)在不僅需要知道某個(gè)組件的運(yùn)行的情況,還要知道服務(wù)的整體運(yùn)行情況。他們當(dāng)時(shí)的監(jiān)控方案是:StatsD + Graphite + Nagios,StatsD結(jié)合Graphite構(gòu)建監(jiān)控圖表,各個(gè)服務(wù)將樣本數(shù)據(jù)推送給StatsD,StatsD將推送來的樣本數(shù)據(jù)聚合在一起,定時(shí)地推送給Graphite,Graphite將樣本數(shù)據(jù)保存在時(shí)序數(shù)據(jù)庫中,用戶根據(jù)Graphite提供的API,結(jié)合自身監(jiān)控的需求,構(gòu)建監(jiān)控圖表,通過圖表分析服務(wù)的指標(biāo)(例如,延遲,每秒的請(qǐng)求數(shù),每秒的錯(cuò)誤數(shù)等)。

開源監(jiān)控系統(tǒng)Prometheus的前世今生
開源監(jiān)控系統(tǒng)Prometheus的前世今生


那么這樣一種方案能滿足微服務(wù)架構(gòu)對(duì)監(jiān)控的要求么?什么要求呢:既能知道服務(wù)整體的運(yùn)行情況,也能夠保持足夠的粒度,知道某個(gè)組件的運(yùn)行情況。答案是很難,為什么呢?例如,我們要統(tǒng)計(jì)api-server服務(wù)響應(yīng)POST /tracks請(qǐng)求錯(cuò)誤的數(shù)量,指標(biāo)的名稱為api-server.tracks.post.500,這個(gè)指標(biāo)可以通過http狀態(tài)碼來測(cè)量,服務(wù)響應(yīng)的狀態(tài)碼為500就是錯(cuò)誤的。Graphite指標(biāo)名稱的結(jié)構(gòu)是一種層次結(jié)構(gòu),api-server指定服務(wù)的名稱,tracks指定服務(wù)的handler,post指定請(qǐng)求的方法,500指定請(qǐng)求響應(yīng)的狀態(tài)碼,api-server服務(wù)實(shí)例將該指標(biāo)推送給StatsD,StatsD聚合各個(gè)實(shí)例推送來的指標(biāo),然后定時(shí)推送給Graphite。查詢api-server.tracks.post.500指標(biāo),我們能獲得服務(wù)錯(cuò)誤的響應(yīng)數(shù),但是,如果我們的api-server服務(wù)跑了多個(gè)實(shí)例,想知道某個(gè)實(shí)例錯(cuò)誤的響應(yīng)數(shù),該怎么查詢呢?問題出在使用這樣一種架構(gòu),往往會(huì)將各個(gè)服務(wù)實(shí)例發(fā)送來的指標(biāo)聚合到一塊,聚合到一起之后,實(shí)例維度的信息就丟失掉了,也就無法統(tǒng)計(jì)某個(gè)具體實(shí)例的指標(biāo)信息。

開源監(jiān)控系統(tǒng)Prometheus的前世今生


StatsD與Graphite的組合用來構(gòu)建監(jiān)控圖表,告警是另外一個(gè)系統(tǒng)-Nagios-來做的,這個(gè)系統(tǒng)運(yùn)行檢測(cè)腳本,判斷主機(jī)或服務(wù)運(yùn)行的是否正常,如果不正常,發(fā)送告警。Nagios最大的問題在于告警是面向主機(jī)的,每個(gè)告警的檢查項(xiàng)都是圍繞著主機(jī)的,在分布式系統(tǒng)的環(huán)境底下,主機(jī)down掉是正常的場(chǎng)景,服務(wù)本身的設(shè)計(jì)也是可以容忍節(jié)點(diǎn)down掉的,但是,這種場(chǎng)景下Nagios依然會(huì)觸發(fā)告警。

開源監(jiān)控系統(tǒng)Prometheus的前世今生


如果大家之前看過這篇 https://landing.google.com/sre ... arker 介紹Google Borgmon的文章,對(duì)比Prometheus,你會(huì)發(fā)現(xiàn)這兩個(gè)系統(tǒng)非常相似。實(shí)際上,Prometheus深受Borgmon系統(tǒng)的影響,并且當(dāng)時(shí)參與構(gòu)建Google監(jiān)控系統(tǒng)的員工加入了SoundCloud公司??傊?,種種因素的結(jié)合,促使了Prometheus系統(tǒng)的誕生。

Prometheus的解決方案

那么,Prometheus是如何解決上面這些問題的?之前的方案中,告警與圖表的構(gòu)建依賴于兩個(gè)不同的系統(tǒng),Prometheus采取了一種新的模型,將采集時(shí)序數(shù)據(jù)作為整個(gè)系統(tǒng)的核心,無論是告警還是構(gòu)建監(jiān)控圖表,都是通過操縱時(shí)序數(shù)據(jù)來實(shí)現(xiàn)的。Prometheus通過指標(biāo)的名稱以及l(fā)abel(key/value)的組合來識(shí)別時(shí)序數(shù)據(jù),每個(gè)label代表一個(gè)維度,可以增加或者減少label來控制所選擇的時(shí)序數(shù)據(jù),前面提到,微服務(wù)架構(gòu)底下對(duì)監(jiān)控的要求:既能知道服務(wù)整體的運(yùn)行情況,也能夠保持足夠的粒度,知道某個(gè)組件的運(yùn)行情況。借助于這種多維度的數(shù)據(jù)模型可以很輕松的實(shí)現(xiàn)這個(gè)目標(biāo),還是拿之前那個(gè)統(tǒng)計(jì)http錯(cuò)誤響應(yīng)的例子來說明,我們這里假設(shè)api_server服務(wù)有三個(gè)運(yùn)行的實(shí)例,Prometheus采集到如下格式的樣本數(shù)據(jù)(其中intance label是Prometheus自動(dòng)添加上去的):

api_server_http_requests_total{method="POST",handler="/tracks",status="500",instance="sample1"} -> 34
api_server_http_requests_total{method="POST",handler="/tracks",status="500",instance="sample2"} -> 28
api_server_http_requests_total{method="POST",handler="/tracks",status="500",instance="sample3"} -> 31


如果我們只關(guān)心特定實(shí)例的錯(cuò)誤數(shù),只需添加instance label即可,例如我們想要查看實(shí)例名稱為sample1的錯(cuò)誤的請(qǐng)求數(shù),那么我就可以用api_server_http_requests_total{method="POST",handler="/tracks",status="500",instance="sample1"}這個(gè)表達(dá)式來選擇時(shí)序數(shù)據(jù),選擇的數(shù)據(jù)如下:

api_server_http_requests_total{method="POST",handler="/tracks",status="500",instance="sample1"} -> 34


如果我們關(guān)心整個(gè)服務(wù)的錯(cuò)誤數(shù),只需忽略instance label去除,然后將結(jié)果聚合到一塊,即可,例如
sum without(instance) (api_server_http_requests_total{method="POST",handler="/tracks",status="500"})計(jì)算得到的時(shí)序數(shù)據(jù)為:

api_server_http_requests_total{method="POST",handler="/tracks",status="500"} -> 93


告警是通過操縱時(shí)序數(shù)據(jù)而不是運(yùn)行一個(gè)自定義的腳本來實(shí)現(xiàn)的,因此,只要能夠采集到服務(wù)或主機(jī)暴露出的指標(biāo)數(shù)據(jù),那么就可以告警。

架構(gòu)

我們?cè)賮砗唵蔚姆治鲆幌翽rometheus的架構(gòu),看一下各個(gè)組件的功能,以及這些組件之間是如何交互的。

Prometheus Server是整個(gè)系統(tǒng)的核心,它定時(shí)地從監(jiān)控目標(biāo)(Exporters)暴露的API中拉取指標(biāo),然后將這些數(shù)據(jù)保存到時(shí)序數(shù)據(jù)庫中,如果是監(jiān)控目標(biāo)是動(dòng)態(tài)的,可以借助服務(wù)發(fā)現(xiàn)的機(jī)制動(dòng)態(tài)地添加這些監(jiān)控目標(biāo),另外它還會(huì)暴露執(zhí)行PromQL(用來操縱時(shí)序數(shù)據(jù)的語言)的API,其他組件,例如Prometheus Web,Grafana可以通過這個(gè)API查詢對(duì)應(yīng)的時(shí)序數(shù)據(jù)。Prometheus Server會(huì)定時(shí)地執(zhí)行告警規(guī)則,告警規(guī)則是PromQL表達(dá)式,表達(dá)式的值是true或false,如果是true,就將產(chǎn)生的告警數(shù)據(jù)推送給alertmanger。告警通知的聚合、分組、發(fā)送、禁用、恢復(fù)等功能,并不是Prometheus Server來做的,而是Alertmanager來做的,Prometheus Server只是將觸發(fā)的告警數(shù)據(jù)推送給Alertmanager,然后Alertmanger根據(jù)配置將告警聚合到一塊,發(fā)送給對(duì)應(yīng)的接收人。

如果我們想要監(jiān)控定時(shí)任務(wù),想要instrument任務(wù)的執(zhí)行時(shí)間,任務(wù)執(zhí)行成功還是失敗,那么如何將這些指標(biāo)暴露給Prometheus Server?例如每隔一天做一次數(shù)據(jù)庫備份,我們想要知道每次備份執(zhí)行了多長時(shí)間,備份是否成功,我們備份任務(wù)只會(huì)執(zhí)行一段時(shí)間,如果備份任務(wù)結(jié)束了,Prometheus Server該如何拉取備份指標(biāo)的數(shù)據(jù)呢?解決這種問題,可以通過Prometheus的pushgateway組件來做,每個(gè)備份任務(wù)將指標(biāo)推送pushgateway組件,pushgateway將推送來的指標(biāo)緩存起來,Prometheus Server從Pushgateway中拉取指標(biāo)。

開源監(jiān)控系統(tǒng)Prometheus的前世今生

例子

前面都是從比較大的層面——背景、架構(gòu)——來介紹Prometheus,現(xiàn)在,讓我們從一個(gè)具體的例子出發(fā),來看一下如何借助Prometheus來構(gòu)建監(jiān)控圖表、分析系統(tǒng)性能以及告警。

我們有個(gè)服務(wù),暴露出四個(gè)API,每個(gè)API只返回一些簡單的文本數(shù)據(jù),現(xiàn)在,我們要對(duì)這個(gè)服務(wù)進(jìn)行監(jiān)控,希望借助監(jiān)控能夠查看、分析服務(wù)的請(qǐng)求速率,請(qǐng)求的平均延遲以及請(qǐng)求的延遲分布,并且當(dāng)應(yīng)用的延遲過高或者不可訪問時(shí)能夠觸發(fā)告警,代碼示例如下:

package main
import (
"math/rand"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
Latency = promauto.NewHistogramVec(prometheus.HistogramOpts{
    Help: "latency of sample app",
    Name: "sample_app_latency_milliseconds",
    Buckets: prometheus.ExponentialBuckets(10, 2, 9),
}, []string{"handler", "method"})
)
func instrumentationFilter(f http.HandlerFunc) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
    now := time.Now()
    f(writer, request)
    duration := time.Now().Sub(now)
    Latency.With(prometheus.Labels{"handler": request.URL.Path, "method": request.Method}).
        Observe(float64(duration.Nanoseconds()) / 1e6)
}
}
// jitterLatencyFilter make request latency between d and d*maxFactor
func jitterLatencyFilter(d time.Duration, maxFactor float64, f http.HandlerFunc) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
    time.Sleep(d + time.Duration(rand.Float64()*maxFactor*float64(d)))
    f(writer, request)
}
}
func main() {
rand.Seed(time.Now().UnixNano())
http.Handle("/metrics", promhttp.Handler())
http.Handle("/a", instrumentationFilter(jitterLatencyFilter(10*time.Millisecond, 256, func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("success"))
})))
http.Handle("/b", instrumentationFilter(jitterLatencyFilter(10*time.Millisecond, 128, func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("success"))
})))
http.Handle("/c", instrumentationFilter(jitterLatencyFilter(10*time.Millisecond, 64, func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("success"))
})))
http.Handle("/d", instrumentationFilter(jitterLatencyFilter(10*time.Millisecond, 32, func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("success"))
})))
http.ListenAndServe(":5001", nil)
}


我們按照instrumentation、exposition、collection、query這樣的流程構(gòu)建監(jiān)控系統(tǒng),instrumentation關(guān)注的是如何測(cè)量應(yīng)用的指標(biāo),有哪些指標(biāo)需要測(cè)量;exposition關(guān)注的是如何通過http協(xié)議將指標(biāo)暴露出來;collection關(guān)注的是如何采集指標(biāo);query關(guān)注的是如何構(gòu)建查詢時(shí)序數(shù)據(jù)的PromQL表達(dá)式。我們首先從instrumentation這里,有四個(gè)指標(biāo)是我們關(guān)心的:

  • 請(qǐng)求速率
  • 請(qǐng)求的平均延遲
  • 請(qǐng)求的延遲分布
  • 訪問狀態(tài)
var (
Latency = promauto.NewHistogramVec(prometheus.HistogramOpts{
    Help: "latency of sample app",
    Name: "sample_app_latency_milliseconds",
    Buckets: prometheus.ExponentialBuckets(10, 2, 9),
}, []string{"handler", "method"})
)


首先將指標(biāo)注冊(cè)進(jìn)來,然后追蹤、記錄指標(biāo)的值。用Prometheus提供的golang客戶端庫可以方便的追蹤、記錄指標(biāo)的值,我們將instrumentation code放到應(yīng)用的代碼里,每次請(qǐng)求,對(duì)應(yīng)的指標(biāo)狀態(tài)的值就會(huì)被記錄下來。

client golang提供了四種指標(biāo)類型,分別為Counter, Gauge, Histogram, Summary,Counter類型的指標(biāo)用來測(cè)量只會(huì)增加的值,例如服務(wù)的請(qǐng)求數(shù);Gauge類型的指標(biāo)用來測(cè)量狀態(tài)值,即可以變大,也可以變小的值,例如請(qǐng)求的延遲時(shí)間;Histogram與Summary指標(biāo)類似,這兩個(gè)指標(biāo)取樣觀察的值,記錄值的分布,統(tǒng)計(jì)觀察值的數(shù)量,累計(jì)觀察到的值,可以用它來統(tǒng)計(jì)樣本數(shù)據(jù)的分布。為了采集請(qǐng)求速率、平均延遲以及延遲分布指標(biāo),方便起見用Histogram類型的指標(biāo)追蹤、記錄每次請(qǐng)求的情況,Histogram類型的指標(biāo)與普通類型(Counter、Gauge)不同的地方在于會(huì)生成多條樣本數(shù)據(jù),一個(gè)是觀察樣本的總數(shù),一個(gè)是觀察樣本值的累加值,另外是一系列的記錄樣本百分位數(shù)的樣本數(shù)據(jù)。訪問狀態(tài)可以使用up指標(biāo)來表示,每次采集時(shí),Prometheus會(huì)將采集的健康狀態(tài)記錄到up指標(biāo)中。

http.Handle("/metrics", promhttp.Handler())


instrumentation完成之后,下一步要做的就是exposition,只需將Prometheus http handler添加進(jìn)來,指標(biāo)就可以暴露出來。訪問這個(gè)Handler返回的樣本數(shù)據(jù)如下(省略了一些無關(guān)的樣本數(shù)據(jù)):

sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="10"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="20"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="40"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="80"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="160"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="320"} 0
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="640"} 1
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="1280"} 1
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="2560"} 1
sample_app_latency_milliseconds_bucket{handler="/d",method="GET",le="+Inf"} 1
sample_app_latency_milliseconds_sum{handler="/d",method="GET"} 326.308075
sample_app_latency_milliseconds_count{handler="/d",method="GET"} 1


僅僅將指標(biāo)暴露出來,并不能讓prometheus server來采集指標(biāo),我們需要進(jìn)行第三步collection,配置prometheus server發(fā)現(xiàn)我們的服務(wù),從而采集服務(wù)暴露出的樣本數(shù)據(jù)。我們簡單地看下prometheus server的配置,其中,global指定采集時(shí)全局配置, scrape_interval 指定采集的間隔, evaluation_interval 指定 alerting rule (alerting rule是PromQL表達(dá)式,值為布爾類型,如果為true就將相關(guān)的告警通知推送給Alertmanager)也就是告警規(guī)則的求值時(shí)間間隔,scrape_timeout指定采集時(shí)的超時(shí)時(shí)間;alerting指定Alertmanager服務(wù)的地址;scrape_configs指定如何發(fā)現(xiàn)監(jiān)控對(duì)象,其中job_name指定發(fā)現(xiàn)的服務(wù)屬于哪一類,static_configs指定服務(wù)靜態(tài)的地址,前面我們也提到,Prometheus支持動(dòng)態(tài)服務(wù)發(fā)現(xiàn),例如文件、kubernetes服務(wù)發(fā)現(xiàn)機(jī)制,這里我們使用最簡單的靜態(tài)服務(wù)發(fā)現(xiàn)機(jī)制。

# my global config
global:
  scrape_interval:     2s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).
rule_files:
- rule.yaml
# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - localhost:9093
scrape_configs:
- job_name: sample-app
  scrape_interval: 3s
  static_configs:
  - targets:
    - sample:5001


采集完指標(biāo),就可以利用Prometheus提供的PromQL語言來操縱采集的時(shí)序數(shù)據(jù),例如,我們想統(tǒng)計(jì)請(qǐng)求的平均速率,可以用這個(gè)表達(dá)式
irate(sample_app_latency_milliseconds_sum[1m]) / irate(sample_app_latency_milliseconds_count[1m])來計(jì)算。

有了時(shí)序數(shù)據(jù)之后,就可以借助Grafana來構(gòu)建監(jiān)控圖表,具體怎么配置Grafana圖表在這里就不展開了,核心點(diǎn)是利用PromQL表達(dá)式選擇、計(jì)算時(shí)序數(shù)據(jù)。

開源監(jiān)控系統(tǒng)Prometheus的前世今生


Prometheus的告警是通過對(duì)Alerting Rule求值來實(shí)現(xiàn)的,alerting rule是一系列的PromQL表達(dá)式,alerting rule保存在配置文件中。我們想要對(duì)應(yīng)用的延遲以及可用狀態(tài)進(jìn)行告警,當(dāng)應(yīng)用過高或者不可訪問時(shí)就觸發(fā)告警,規(guī)則可以如下這樣定義:

- name: sample-up
  rules:
  - alert: UP
    expr: up{instance="sample:5001"} == 0
    for: 1m
    labels:
      severity: page
    annotations:
      summary: Service health
  - alert: 95th-latency
    expr: histogram_quantile(0.95, rate(sample_app_latency_milliseconds_bucket[1m])) > 1000
    for: 1m
    labels:
      severity: page
    annotations:
      summary: 95th service latency


其中UP指定服務(wù)的可用狀態(tài),95th-latency指定95%的請(qǐng)求大于1000毫秒就觸發(fā)告警。Prometheus定時(shí)的對(duì)這些規(guī)則進(jìn)行求值,如果條件滿足,就將告警通知發(fā)送給Alertmanger,Alertmanger會(huì)根據(jù)自身路由配置,對(duì)告警進(jìn)行聚合,分發(fā)到指定的接收人,我們想通過郵箱接收到告警,可以如下進(jìn)行配置:

global:
  smtp_smarthost: <your_smtp_server>
  smtp_auth_username: <your_username>
  smtp_from: <from>
  smtp_auth_password: <secret>
  smtp_require_tls: false
  resolve_timeout: 5m
route:
  receiver: me
receivers:
- name: me
  email_configs:
  - to: example@domain.com
templates:
- '*.tmpl'


這樣,我們就可以通過郵箱收到告警郵件了。

相關(guān)的工作

無論是監(jiān)控圖表相關(guān)的業(yè)務(wù),還是告警相關(guān)的業(yè)務(wù),都離不開相關(guān)指標(biāo)的采集工作,沃趣是一家做數(shù)據(jù)庫產(chǎn)品的公司,我們花費(fèi)了很多的精力去采集數(shù)據(jù)庫相關(guān)的指標(biāo),從Oracle到MySQL,再到SQL Server,主流的關(guān)系型數(shù)據(jù)庫的指標(biāo)都有采集。對(duì)于一些通用的指標(biāo),例如操作系統(tǒng)相關(guān)的指標(biāo),我們主要是借助開源的Exporters來采集的。沃趣的產(chǎn)品是軟、硬一體交付的,其中有大量硬件相關(guān)的指標(biāo)需要采集,因此,我們也有專門采集硬件指標(biāo)的Expoters。

沃趣大部分場(chǎng)景中,要監(jiān)控的服務(wù)都是動(dòng)態(tài)的。比如,用戶從平臺(tái)上申請(qǐng)了一個(gè)數(shù)據(jù)庫,需要增加相關(guān)的監(jiān)控服務(wù),用戶刪除數(shù)據(jù)庫資源,需要移除相關(guān)的監(jiān)控服務(wù),要監(jiān)控的數(shù)據(jù)庫服務(wù)處于動(dòng)態(tài)的變化之中。沃趣每個(gè)產(chǎn)品線的基礎(chǔ)架構(gòu)都不相同,數(shù)據(jù)庫服務(wù)有跑在Oracle RAC上的,有跑在ZStack的,有跑在Kubernetes上的。對(duì)于跑在Kubernetes上的應(yīng)用來說,并需要擔(dān)心Prometheus怎么發(fā)現(xiàn)要監(jiān)控的服務(wù),只需要配置相關(guān)的服務(wù)發(fā)現(xiàn)的機(jī)制就可以了。對(duì)于其他類型的,我們主要借助Prometheus的file_sd服務(wù)發(fā)現(xiàn)機(jī)制來實(shí)現(xiàn),基于文件的服務(wù)發(fā)現(xiàn)機(jī)制是一種最通用的機(jī)制,我們將要監(jiān)控的對(duì)象寫到一個(gè)文件中,Prometheus監(jiān)聽這個(gè)文件的變動(dòng),動(dòng)態(tài)的維護(hù)要監(jiān)控的對(duì)象,我們?cè)趂ile_sd基礎(chǔ)上構(gòu)建了專門的組件去負(fù)責(zé)服務(wù)的動(dòng)態(tài)更新,其他應(yīng)用調(diào)用這個(gè)組件暴露的API來維護(hù)自身想要監(jiān)控的對(duì)象。

Prometheus本身的機(jī)制的并不能滿足我們業(yè)務(wù)上對(duì)告警的要求,一方面我們需要對(duì)告警通知進(jìn)行統(tǒng)計(jì),但是Alertmanager本身并沒有對(duì)告警通知做持久化,服務(wù)重啟之后告警通知就丟失掉了;另外一方面用戶通過Web頁面來配置相關(guān)的告警,告警規(guī)則以及告警通知的路由需要根據(jù)用戶的配置動(dòng)態(tài)的生成。為了解決這兩方面的問題,我們將相關(guān)的業(yè)務(wù)功能做成基礎(chǔ)的告警組件,供各個(gè)產(chǎn)品線去使用。針對(duì)Alertmanager不能持久化告警通知的問題,基礎(chǔ)告警組件利用Alertmanager webhook的機(jī)制來接收告警通知,然后將通知保存到數(shù)據(jù)庫中;另外用戶的告警配置需要?jiǎng)討B(tài)的生成,我們定義了一種新的模型來描述我們業(yè)務(wù)上的告警模型。

總結(jié)

Promtheus將采集時(shí)序數(shù)據(jù)作為整個(gè)系統(tǒng)的核心,無論是構(gòu)建監(jiān)控圖表還是告警,都是通過操縱時(shí)序數(shù)據(jù)來完成的。Prometheus借助多維度的數(shù)據(jù)模型,以及強(qiáng)大的查詢語言滿足了微服務(wù)架構(gòu)底下對(duì)監(jiān)控的要求:既能知道服務(wù)整體的運(yùn)行情況,也能夠保持足夠的粒度,知道某個(gè)組件的運(yùn)行情況。沃趣站在巨人的肩旁上,圍繞Prometheus構(gòu)建了自己的監(jiān)控系統(tǒng),從滿足不同采集要求的Exporters到服務(wù)發(fā)現(xiàn),最后到基礎(chǔ)告警組件,這些組件結(jié)合Prometheus,構(gòu)成了沃趣監(jiān)控系統(tǒng)的核心。

作者:郭振,沃趣科技開發(fā)工程師,多年的Python、Golang等語言的開發(fā)經(jīng)驗(yàn),熟悉Kubernetes、Prometheus等云原生應(yīng)用,負(fù)責(zé)QFusion RDS平臺(tái)以及基礎(chǔ)告警平臺(tái)的研發(fā)工作。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI