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