服務(wù)網(wǎng)格可觀測(cè)性之平臺(tái)化監(jiān)控報(bào)警
一.項(xiàng)目背景
近期,汽車之家正在加速云原生服務(wù)網(wǎng)格化改造,以進(jìn)一步提高業(yè)務(wù)系統(tǒng)的可擴(kuò)展性和穩(wěn)定性。目前汽車之家看選業(yè)務(wù)、資訊業(yè)務(wù)、買用業(yè)務(wù)等多個(gè)業(yè)務(wù)線已經(jīng)陸續(xù)接入服務(wù)網(wǎng)格,累計(jì)接入應(yīng)用數(shù)量200+、網(wǎng)格流量每日15億+。
服務(wù)網(wǎng)格(Istio)以其強(qiáng)大的功能和擴(kuò)展能力,為應(yīng)用提供了更好的服務(wù)治理和可觀測(cè)能力。服務(wù)的可觀測(cè)性對(duì)于業(yè)務(wù)方以及運(yùn)維來(lái)說(shuō)都至關(guān)重要。Istio網(wǎng)格提供了豐富的監(jiān)控和追蹤工具,使得我們可以實(shí)時(shí)地監(jiān)控服務(wù)的狀態(tài)、性能指標(biāo)和日志數(shù)據(jù)。
我們?cè)诳捎^測(cè)性體系建設(shè)過(guò)程中使用了Opentelemetry、Jaeger、Prometheus、Grafana等插件以及為應(yīng)用定制可觀測(cè)性基礎(chǔ)鏡像,從而實(shí)現(xiàn)了業(yè)務(wù)側(cè)接入服務(wù)網(wǎng)格便可自動(dòng)接入可觀測(cè)性體系,實(shí)現(xiàn)網(wǎng)格進(jìn)出流量、源站進(jìn)出流量、服務(wù)整體性能[QPS\響應(yīng)時(shí)間等]、源站性能[接口QPS、響應(yīng)時(shí)間、TP99等]、鏈路追蹤等,而不需要進(jìn)行額外開(kāi)發(fā)與配置。至此我們可以輕松地進(jìn)行服務(wù)調(diào)用鏈追蹤和指標(biāo)監(jiān)控,幫助快速定位問(wèn)題并提高系統(tǒng)的穩(wěn)定性和性能。以下是可觀測(cè)性部分截圖:
1.1全鏈路
全鏈路展示-圖1
1.2指標(biāo)大盤(pán)
網(wǎng)格全局流量大盤(pán)
網(wǎng)格全局流量大盤(pán)展示-圖2
網(wǎng)格應(yīng)用級(jí)流量大盤(pán)
網(wǎng)格應(yīng)用級(jí)進(jìn)流量大盤(pán)展示--圖03
網(wǎng)格應(yīng)用級(jí)出流量大盤(pán)展示--圖04
源站應(yīng)用級(jí)大盤(pán)
服務(wù)源站進(jìn)流量大盤(pán)展示--圖05
服務(wù)源站出流量大盤(pán)展示-圖06
1.3異常報(bào)警
異常報(bào)警釘釘展示-圖07
可觀測(cè)體系中“指標(biāo)大盤(pán)系統(tǒng)”與“異常報(bào)警系統(tǒng)”我們采用了Opentelemetry+Prometheus+Grafana 的技術(shù)選型。
本篇文章我們將主要描述“異常報(bào)警系統(tǒng)”的技術(shù)方案。在“異常報(bào)警系統(tǒng)”的建設(shè)過(guò)程中,我們面臨了兩類Prometheus Metrics數(shù)據(jù)的處理。首先是來(lái)自Istio架構(gòu)本身的Metrics數(shù)據(jù),其次是應(yīng)用源站產(chǎn)生的Metrics數(shù)據(jù),例如:進(jìn)出流量等關(guān)鍵指標(biāo)。作為業(yè)務(wù)方,我們希望能夠快速構(gòu)建一個(gè)獨(dú)立的報(bào)警系統(tǒng)來(lái)監(jiān)控這些數(shù)據(jù),并及時(shí)發(fā)現(xiàn)和響應(yīng)異常情況。盡管運(yùn)維側(cè)可能已經(jīng)提供了Prometheus Alertmanager,但考慮到獨(dú)立性和靈活性的需求,我們選擇了使用“Grafana Alert 警報(bào)模塊”來(lái)實(shí)現(xiàn)自主報(bào)警管理。
二. Grafana 警報(bào)模塊介紹
grafana 8.0 以后添加了新的警報(bào)模塊"unified_alerting",以下簡(jiǎn)稱為“統(tǒng)一警報(bào)模塊”。
“統(tǒng)一警報(bào)模塊” 是一個(gè)基于 Grafana 的插件,它能夠輕松地創(chuàng)建和管理報(bào)警規(guī)則,并將報(bào)警發(fā)送到多個(gè)渠道,例如電子郵件、Slack 、釘釘、webhook等。這個(gè)工具的主要特點(diǎn)包括:
- 可視化警報(bào)配置:“統(tǒng)一警報(bào)模塊” 提供了一個(gè)可視化界面,讓用戶可以方便地創(chuàng)建和管理報(bào)警規(guī)則。您可以通過(guò)簡(jiǎn)單地設(shè)置觸發(fā)條件、定義報(bào)警接收者以及報(bào)警通知方式,輕松實(shí)現(xiàn)警報(bào)功能。
- 多數(shù)據(jù)源支持:“統(tǒng)一警報(bào)模塊” 警報(bào)規(guī)則可以配置多種數(shù)據(jù)源作為數(shù)據(jù)來(lái)源,比如:prometheus、mysql、es等。
- 多維度警報(bào):警報(bào)規(guī)則可以為每個(gè)警報(bào)規(guī)則創(chuàng)建多個(gè)單獨(dú)的警報(bào)實(shí)例(稱為多維警報(bào)),使你能夠強(qiáng)大而靈活地通過(guò)單個(gè)警報(bào)來(lái)了解整個(gè)系統(tǒng)。
- 多種報(bào)警通知方式:“統(tǒng)一警報(bào)模塊” 支持多種報(bào)警通知方式,包括電子郵件、Slack、PagerDuty 等。根據(jù)實(shí)際需求選擇適合您的報(bào)警通知方式。
- 報(bào)警歷史記錄:“統(tǒng)一警報(bào)模塊” 記錄每次觸發(fā)的報(bào)警事件,并提供報(bào)警歷史記錄查詢功能。通過(guò)查看歷史記錄,您可以更好地了解您的系統(tǒng)狀態(tài)并進(jìn)行優(yōu)化。
- 自定義報(bào)警模板:“統(tǒng)一警報(bào)模塊” 允許用戶自定義報(bào)警模板,以適應(yīng)不同場(chǎng)景下的報(bào)警需求。通過(guò)自定義警報(bào)模板,可以使報(bào)警信息更加精準(zhǔn)和有效。
- 抑制警報(bào):抑制警報(bào)允許您停止接收來(lái)自一個(gè)或多個(gè)警報(bào)規(guī)則的持久通知。您還可以根據(jù)特定條件部分暫停警報(bào)。比如:使用抑制警報(bào)時(shí)間段設(shè)置,您可以指定不希望生成或發(fā)送新通知的時(shí)間間隔。您還可以將警報(bào)通知凍結(jié)在重復(fù)時(shí)間段內(nèi),例如在維護(hù)期間。
2.1主要概念
下圖向您概述了Grafana警報(bào)的工作原理,并向您介紹了一些關(guān)鍵概念,這些概念一起工作,形成了我們靈活而強(qiáng)大的警報(bào)引擎的核心。
概念架構(gòu)-圖08
- Alert rules [警報(bào)規(guī)則] 設(shè)置評(píng)估標(biāo)準(zhǔn),該標(biāo)準(zhǔn)確定警報(bào)實(shí)例是否會(huì)背觸發(fā)。警報(bào)規(guī)則包括一個(gè)或多個(gè)查詢和表達(dá)式、條件、評(píng)估頻率以及滿足條件的持續(xù)時(shí)間(可選)。
- Labels[標(biāo)簽] 將警報(bào)規(guī)則及其實(shí)例與通知策略(Notification policies)和靜默(Silences)匹配。它們還可以用于按嚴(yán)重程度對(duì)警報(bào)進(jìn)行分組。
- Notification policies[通知策略] 通過(guò)配置“通知策略” 可以實(shí)現(xiàn)警報(bào)的通知時(shí)間以及匹配具體的警報(bào)規(guī)則。每個(gè)“通知策略”通過(guò)一組標(biāo)簽匹配器來(lái)匹配警報(bào)規(guī)則。警報(bào)的"聯(lián)絡(luò)點(diǎn)"也是在此進(jìn)行關(guān)聯(lián)。
- Contact points[聯(lián)絡(luò)點(diǎn)] 定義警報(bào)觸發(fā)時(shí)如何通知聯(lián)系人。支持多種通訊工具[dingding、email、webhook等],以確保警報(bào)到達(dá)您的團(tuán)隊(duì)。
2.2 警報(bào)工作原理
下圖向您概述了"統(tǒng)一警報(bào)模塊"工作原理,并向您介紹了一些關(guān)鍵概念,這些概念一起工作,形成了我們靈活而強(qiáng)大的警報(bào)引擎的核心。
工作原理-圖09
你可以直接在Grafana UI中創(chuàng)建警報(bào)資源(警報(bào)規(guī)則,通知策略等),如下圖所示:
告警規(guī)則示例-圖10
? 2.2.1 Alert rules [警報(bào)規(guī)則]
可以為你的警報(bào)規(guī)則添加摘要/注釋[Summary and annotations],為報(bào)警提供額外的信息。還可以添加標(biāo)簽,通過(guò)此標(biāo)簽可以配置路由規(guī)則。標(biāo)簽將警報(bào)規(guī)則與通知策略相關(guān)聯(lián),因此您可以輕松管理哪個(gè)策略應(yīng)處理哪些警報(bào)以及誰(shuí)應(yīng)該收到通知。
一個(gè)警報(bào)規(guī)則可以產(chǎn)生多個(gè)警報(bào)實(shí)例,詳見(jiàn)【**Alert instances[警報(bào)實(shí)例]**】。
創(chuàng)建警報(bào)規(guī)則后,它們會(huì)經(jīng)歷各種狀態(tài)轉(zhuǎn)換。狀態(tài)一般為:Normal, Pending, Firing 。例如,如果一個(gè)警報(bào)實(shí)例正在觸發(fā)[firing],則警報(bào)規(guī)則的狀態(tài)也將是觸發(fā)[firing]。
? 2.2.2 Alert instances[警報(bào)實(shí)例]
對(duì)于grafana管理的警報(bào)規(guī)則,可以根據(jù)一個(gè)警報(bào)規(guī)則創(chuàng)建多個(gè)警報(bào)實(shí)例(也稱為多維警報(bào))。它可以幫你在單個(gè)表達(dá)式中觀察多個(gè)實(shí)例。比如:
比如:
sum by(cpu) ( rate(node_cpu_seconds_total{mode!="idle"}[1m]) )
使用此表達(dá)式的“警報(bào)規(guī)則”將創(chuàng)建與第一次求值后觀察到的CPU數(shù)量相同數(shù)量的“警報(bào)實(shí)例”,從而為每個(gè)CPU都生成一條報(bào)警實(shí)例。
多維報(bào)警示例-圖11
grafana管理的警報(bào)實(shí)例都可以處于Normal、Pending、Alerting、No Data、Error狀態(tài)。
? 2.2.3 Notification policy[通知策略]
每個(gè)通知策略都包含一組標(biāo)簽匹配器[labels matcher],以指示它負(fù)責(zé)哪些警報(bào)規(guī)則或?qū)嵗?/p>
通知策略-圖12
可以添加聯(lián)絡(luò)點(diǎn)[Contact point]來(lái)配置警報(bào)規(guī)則觸發(fā)后通知的渠道[dingding、email、webhook等];還可以配置靜默時(shí)間[Mute timings]用來(lái)配置報(bào)警觸發(fā)后通知的時(shí)間,比如:凌晨1點(diǎn)到5點(diǎn)不發(fā)送報(bào)警信息。
? 2.2.4 Message templates[消息模板]
為通知消息創(chuàng)建可重用的自定義模板,并在聯(lián)絡(luò)點(diǎn)[Contact point]中使用它們。模板語(yǔ)法以Go templating system [https://pkg.go.dev/text/template]為基礎(chǔ)。
? 2.2.5 Silences and mute timings[靜默與靜音時(shí)間]
Sliences: 添加靜默配置可在一段時(shí)間內(nèi)停止某個(gè)告警規(guī)則的通知。是一種快速而有效的方法,可以將不必要的告警暫停,從而避免不必要的干擾和誤報(bào)。例如,在系統(tǒng)維護(hù)期間,可以將某些告警規(guī)則設(shè)置為靜音以減少通知,也可以在進(jìn)行緊急修復(fù)時(shí)暫停某些告警。
Mute timings:指定了通知被禁止的時(shí)間段,這些時(shí)間段可以是重復(fù)的,例如,每周五晚上。這種方式適用于計(jì)劃的活動(dòng)或預(yù)定的維護(hù)窗口,其中需要在一段時(shí)間內(nèi)暫停特定的告警通知。
下面章節(jié)將通過(guò)一個(gè)具體案例展示grafana “統(tǒng)一警報(bào)模塊”的使用。
三. Grafana 警報(bào)實(shí)戰(zhàn)
3.1安裝
參考:https://grafana.com/docs/grafana/latest/setup-grafana/installation/
開(kāi)啟"統(tǒng)一警報(bào)模塊"
#################################### Unified Alerting ####################
[unified_alerting]
#開(kāi)啟統(tǒng)一報(bào)警模塊
enabled = true
配置"統(tǒng)一警報(bào)模塊"高可用
#################################### Unified Alerting ####################
[unified_alerting]
#開(kāi)啟統(tǒng)一報(bào)警模塊
enabled = true
#監(jiān)聽(tīng)地址/主機(jī)名和端口,用于接收其他Grafana實(shí)例的統(tǒng)一警報(bào)消息。
ha_listen_address = "${POD_IP}:9094"
#監(jiān)聽(tīng)地址/主機(jī)名和端口,用于接收其他Grafana實(shí)例的統(tǒng)一警報(bào)消息。
ha_advertise_address = "${POD_IP}:9094"
#以“主機(jī):端口”的格式列出初始實(shí)例(逗號(hào)分隔),這些實(shí)例將組成HA集群。配置此設(shè)置將啟用警報(bào)的高可用模式。
#注: 此pod申請(qǐng)固定IP,也可以將grafna部署為statefulset模式。
ha_peers = 10.23.2.32:9094,10.23.2.33:9094,10.23.2.34:9094
3.2案例說(shuō)明
下面是此案例的數(shù)據(jù)流圖:
數(shù)據(jù)流圖-圖13
此案例中聯(lián)絡(luò)點(diǎn)為webhook實(shí)現(xiàn)方式,采用webhook方式定制自己的webhook服務(wù)可以更靈活的配置報(bào)警消息的發(fā)送策略,比如:配置多渠道的發(fā)送機(jī)制[釘釘+短信+郵件]、可通過(guò)服務(wù)名稱匹配到具體的應(yīng)用相關(guān)人。
報(bào)警規(guī)則
計(jì)算服務(wù)名稱為"vehicle_service"的服務(wù)所提供的所有接口響應(yīng)時(shí)間,對(duì)5分鐘內(nèi)99百分位大于70ms的接口進(jìn)行分組報(bào)警。
Metrics數(shù)據(jù)格式
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="0.0", service="vehicle_service"} 0.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="5.0", service="vehicle_service"} 102356.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="10.0", service="vehicle_service"} 136099.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="25.0", service="vehicle_service"} 163764.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="50.0", service="vehicle_service"} 175603.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="75.0", service="vehicle_service"} 179163.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="100.0", service="vehicle_service"} 180891.0
http_server_duration_bucket{http_method="GET", http_route="/v1/app/getVehicleList", http_status_code="200", instance="10.29.2.9:9464", le="250.0", service="vehicle_service"} 182806.0
數(shù)據(jù)說(shuō)明:此Metrics數(shù)據(jù)描述了HTTP 服務(wù)的響應(yīng)時(shí)間分布數(shù)據(jù),通過(guò)這些 metrics 數(shù)據(jù)可以得到該 HTTP 接口在不同響應(yīng)時(shí)間區(qū)間的請(qǐng)求數(shù)量,以及每個(gè)區(qū)間的響應(yīng)時(shí)間度量值。例如,在此數(shù)據(jù)中,le=5.0 的 bucket 中有 102356 次請(qǐng)求,對(duì)應(yīng)的響應(yīng)時(shí)間在 0 到 5 秒之間,le=250.0 的 bucket 中有 182806 次請(qǐng)求,對(duì)應(yīng)的響應(yīng)時(shí)間在 0 到 250 秒之間。
下面將演示通過(guò)Grafana “統(tǒng)一警報(bào)模塊”實(shí)現(xiàn)上面的報(bào)警規(guī)則:
3.3案例配置說(shuō)明
? 3.3.1 配置prometheus數(shù)據(jù)源
數(shù)據(jù)源-圖14
? 3.3.2 配置警報(bào)規(guī)則
配置報(bào)警規(guī)則-圖15
配置表達(dá)式:
round(histogram_quantile(0.99, sum(irate(http_server_duration_bucket{service=~"vehicle_service",http_route!="/**",http_status_code="200"}[5m])) by (service,http_route,http_method,http_status_code, le)) > 60,0.01)
添加標(biāo)簽-圖16
配置標(biāo)簽 name=vehicle_service-rt99 ,此標(biāo)簽為通知策略匹配關(guān)聯(lián)。
? 3.3.3 配置聯(lián)絡(luò)點(diǎn)
配置聯(lián)絡(luò)點(diǎn)-圖17
webhook URL:
http://alert-webhook.zhijiajishu.com/mc/multiMessage?serviceName=vehicle_service&channels=dingding
此webhook接口實(shí)現(xiàn)的功能為:接收到alert請(qǐng)求以后,通過(guò)serviceName匹配到相應(yīng)的應(yīng)用相關(guān)人,并通過(guò)釘釘?shù)姆绞竭M(jìn)行報(bào)警消息發(fā)送。
更多webhook參數(shù)可以參照:https://grafana.com/docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/manage-contact-points/webhook-notifier/
? 3.3.4 配置消息模板
配置消息模板-圖18
模板內(nèi)容:
{{ define "vehicle_service_rt99_tpl" }}
{{ if .Alerts.Firing -}}
{{ range .Alerts.Firing }}
{{ .Labels.service }} ## 報(bào)警詳情:應(yīng)用名[{{ .Labels.service }}] 接口 [{{ .Labels.http_route }}],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[{{.Values.B}}] 超過(guò)閾值[70ms].
{{ end }}
{{- end }}
{{ if .Alerts.Resolved -}}
{{- range .Alerts.Resolved }}
{{ .Labels.service }} ## 報(bào)警詳情[恢復(fù)]:應(yīng)用名[{{ .Labels.service }}] 接口 [{{ .Labels.http_route }}],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[{{.Values.B}}] 超過(guò)閾值[70ms].
{{- end }}
{{- end }}
{{- end }}
? 3.3.5 配置通知策略
配置通知策略-圖19
通過(guò)Labels Matcher 匹配 name=vehicle_service-rt99 的警報(bào)規(guī)則,并通過(guò) contact point = vehicle_service-rt99-webhook-point01 的聯(lián)絡(luò)點(diǎn)進(jìn)行報(bào)警。
? 3.3.6 配置靜默規(guī)則
配置靜默規(guī)則-圖20
? 3.3.7 警報(bào)消息
[AutoMesh報(bào)警] CarAPI 99%請(qǐng)求的的平均處理時(shí)間超閾值報(bào)警
報(bào)警詳情:應(yīng)用名[vehicle_service] 接口 [/v1/app/getVehicleList],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[79.79] 超過(guò)閾值[70ms].
報(bào)警詳情:應(yīng)用名[vehicle_service] 接口 [/v1/app/getVehicleDetails],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[84.84] 超過(guò)閾值[70ms].
報(bào)警詳情:應(yīng)用名[vehicle_service] 接口 [/v1/app/updateVehicleInfo],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[82.62] 超過(guò)閾值[70ms].
報(bào)警詳情:應(yīng)用名[vehicle_service] 接口 [/v1/app/countVehicles],5分鐘內(nèi)接口平均響應(yīng)時(shí)間為[91.49] 超過(guò)閾值[70ms].
四. 總結(jié)
通過(guò)本篇文章,大家應(yīng)該可以了解了Grafana 警報(bào)模塊的工作原理以及具體使用方式。如果想更深入的了解grafana 的警報(bào)模塊的更多功能還應(yīng)該閱讀官方文檔。另:如果不用使用Grafana UI配置相關(guān)警報(bào)規(guī)則,大家還可以通過(guò)Grafana 提供的API[https://grafana.com/docs/grafana/latest/developers/http_api/]定制自己的告警系統(tǒng).