一.项目背景
近期,汽车之家正在加速云原生服务网格化改造,以进一步提高业务系统的可扩展性和稳定性。目前汽车之家看选业务、资讯业务、买用业务等多个业务线已经陆续接入服务网格,累计接入应用数量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等。这个工具的主要特点包括:
2.1主要概念
下图向您概述了Grafana警报的工作原理,并向您介绍了一些关键概念,这些概念一起工作,形成了我们灵活而强大的警报引擎的核心。
概念架构-图08
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/]定制自己的告警系统.