【Prometheus】内置的数据查询语言 ---PromQL 保姆级
PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言。支持用户进行实时的数据查询及聚合操作Prometheus 基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列指标名称代表着监控目标上某类可测量属性的基本特征标识标签则是这个基本特征上再次细分的多个可测量维度基于 PromQL 表达式,用户可以
目录
2.2时间序列选择器(Time series Selectors)
2.2.1即时向量选择器(Instant Vector Selectors)
2.2.2区间向量选择器(Range Vector Selectors)
5.3.2修改 alertmanager 配置文件,添加邮件告警路由信息
5.3.5修改 prometheus 配置文件,添加 Alertmanager 实例的配置
作为一种开源的系统监控和警报工具,Prometheus提供了功能强大的查询语言PromQL,用于解析和分析指标数据
一、PromQL 简介
1.1PromQL概念
PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言。支持用户进行实时的数据查询及聚合操作
Prometheus 基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列
- 指标名称代表着监控目标上某类可测量属性的基本特征标识
- 标签则是这个基本特征上再次细分的多个可测量维度
基于 PromQL 表达式,用户可以针对指定的特征及其细分的纬度进行过滤、聚合、统计等运算从而产生期望的计算结果
- PromQL 使用表达式(expression)来表述查询需求
- 根据其使用的指标和标签,以及时间范围,表达式的查询请求可灵活地覆盖在一个或多个时间序列的一定范围内的样本之上,甚至是只包含单个时间序列的单个样本
PromQL是Prometheus的查询语言,用于从Prometheus服务器中获取和处理时间序列数据。它采用了类似SQL的语法,但专门设计用于处理指标数据。PromQL具有灵活的查询能力,可以对指标进行过滤、聚合、计算和变换,以生成有意义的监控数据
1.2Prometheus 数据模型
Prometheus 中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识
格式为:<metric_name>{<label_name>=<label_value>, ...}
- 指标名称:通常用于描述系统上要测定的某个特征
例如,prometheus_http_requests_total 表示接收到的 HTTP 请求总数
- 标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;可选项
例如,prometheus_http_requests_total{code="200"} 和 prometheus_http_requests_total{code="302"} 代表着两个不同的时间序列
- 双下划线的标签(例如 __address__ )是 Prometheus 系统默认标签,是不会显示在 /metrics 页面里面的;
- 系统默认标签在 target 页面中也是不显示的,需要鼠标放到 label 字段上才会显示。
1.2.1常见的系统默认标签
__address__ :当前 target 实例的套接字地址 <host>:<port>
__scheme__ :采集当前 target 上指标数据时使用的协议(http 或 https)
__metrics_path__ :采集当前 target 上的指标数据时使用 URI 路径,默认为 /metrics
__param_<name> :传递的 URL 参数中第一个名称为 <name> 的参数的值
__name__ : 此标签是标识指标名称的预留标签,能够使用标签选择器对指标名称进行过滤
1.2.2指标名称及标签使用注意事项
- 指标名称和标签的特定组合代表着一个时间序列;指标名称相同,但标签不同的组合分别代表着不同的时间序列;不同的指标名称自然更是代表着不同的时间序列
- PromQL支持基于定义的指标维度进行过滤和聚合;更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列;应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个动态的数据环境,并使得监控的数据源难以跟踪,从而导致建立在该指标之上的图形、告警及记录规则变得无效
1.3样本数据格式
Prometheus 的每个数据样本由两部分组成
- 毫秒精度的时间戳
- float64 格式的数据
prometheus_http_requests_total{code="200", handler="/targets", instance="localhost:9090", job="prometheus"} @1434317560885 28
prometheus_http_requests_total{code="200", handler="/targets", instance="localhost:9090", job="prometheus"} @1434317561483 35
prometheus_http_requests_total{code="200", handler="/targets", instance="localhost:9090", job="prometheus"} @1434317562589 42
prometheus_http_requests_total{code="200", handler="/targets", instance="localhost:9090", job="prometheus"} @1434317563654 50
| || | | | |
---------- 指标名称 -------- ------------------------ 标签 --------------------------------------------- -- 时间戳 -- 样本值
1.4PromQL语法基础
PromQL的语法相对简单,以下是几个基本概念和语法元素的介绍:
- 时间序列:时间序列是Prometheus中的核心概念,它由指标名称和一组标签键值对组成。时间序列代表了一系列按时间排序的数据点。例如,
http_requests_total{method="GET"}
是一个时间序列,表示GET方法的HTTP请求数量。 - 表达式:PromQL的表达式用于从时间序列中提取、计算和转换数据。表达式可以是简单的指标名称,也可以是复杂的函数和操作符的组合。例如,
http_requests_total{method="GET"} / http_requests_total
是一个表达式,计算GET方法的HTTP请求数量占总请求数量的比例。 - 函数:PromQL提供了丰富的内置函数,用于对指标数据进行操作和计算。函数可以用于聚合、过滤、计算和变换指标数据。例如,
sum()
函数用于计算时间序列数据的总和,rate()
函数用于计算时间序列数据的速率。
1.5常见的PromQL用法
PromQL支持多种查询和操作方式,以下是几个常见的用法示例:
- 简单查询:通过指定指标名称和标签条件,可以从Prometheus中获取指定的时间序列数据。例如,
http_requests_total{method="GET"}
将返回所有GET方法的HTTP请求数量的时间序列数据。 - 聚合查询:使用内置的聚合函数(如
sum()
、avg()
、max()
等)可以对时间序列数据进行聚合计算。例如,sum(http_requests_total)
将返回所有HTTP请求数量的总和。 - 矢量操作:PromQL支持矢量操作,可以对多个时间序列进行操作和计算。例如,
http_requests_total{method="GET"} / http_requests_total
将返回GET方法的HTTP请求数量占总请求数量的比例。 - 告警条件:PromQL还可以用于定义和配置警报规则。通过指定警报条件和触发规则,可以在满足特定条件时触发警报。例如,
http_requests_total > 100
将触发一个警报,当HTTP请求数量超过100时。
PromQL是Prometheus强大而灵活的查询语言,为我们提供了丰富的工具和功能,用于解析和分析指标数据。通过灵活运用PromQL的查询语法、函数和操作符,我们可以深入理解指标数据的趋势、计算关键性能指标以及设置有效的警报规则。
二、PromQL 的数据类型
2.1PromQL 的表达式中支持 4 种数据类型
- 即时向量 (Instant vector): 特定或全部的时间序列集合上,具有相同时间戳的一组样本值
- 区间向量 (Range vector): 特定或全部的时间序列集合上,在指定的同一时间范围内的所有样本值
- 标量数据 (Scalar): 一个浮点型的数据值
- 字符串 (String): 一个字符串,支持使用单引号、双引号进行引用
2.2时间序列选择器(Time series Selectors)
PromQL 的查询操作可能需要针对若干个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式式最为关键的一步;
用户可使用向量选择器表达式来挑选出给定指标名称下的所有时间序列或部分时间序列的即时样本值或至过去某个时间范围内的样本值,前者称为瞬时向量选择器,后者称为区间向量选择器。
2.2.1即时向量选择器(Instant Vector Selectors)
瞬时向量选择器可以返回 0 个、1 个或多个时间序列上在给定时间戳(instant)上的各自的一个样本。
#即时向量选择器由两部分组成:
- 指标名称:用于限定特定指标下的时间序列,即负责过滤指标;可选
- 标签选择器:用于过滤时间序列上的标签;定义在 {} 之中;可选
#定义即时向量选择器时,以上两个部分应该至少给出一个;因此存在以下三种组合:
◆仅给定指标名称,或在标签名称上使用了空值的标签选择器:返回给定的指标下的所有时间序列各自的即时样本
例如,prometheus_http_requests_total 和 prometheus_http_requests_total{} 的功能相同,都是用于返回这个指标下各时间序列的即时样本
◆仅给定标签选择器:返回所有符合给定的标签选择器的所有时间序列上的即时样本
例如,{code="200", job="prometheus"} ,这样的时间序列可能会有着不同的指标名称
◆指标名称和标签选择器的组合:返回给定的指标下的,且符合给定的标签过滤器的所有时间序列上的即时样本
例如,prometheus_http_requests_total{code="200", job="prometheus"},用于返回这个指标 code 为 200, 并且 job 为 prometheus 的时间序列的即时样本
匹配器
#标签选择器用于定义标签过滤条件,目前支持如下4种匹配操作符:
= :完全相等
!= : 不相等
=~ : 正则表达式匹配
!~ : 正则表达式不匹配
注意事项:
◆🌹匹配到空标签值的标签选择器时,所有未定义该标签的时间序列同样符合条件
例如,prometheus_http_requests_total{handler= ""},则该指标名称上所有未使用该标签(handler)的时间序列也符合条件
◆🌹正则表达式将执行完全锚定机制,它需要匹配指定的标签的整个值
◆🌹向量选择器至少要包含一个指标名称,或者至少有一个不会匹配到空字符串的标签选择器
例如,{ job=""} 为非法的向量选择器
◆🌹使用 __name__ 做为标签名称,还能够对指标名称进行过滤
例如,{__name__=~".*http_requests_total"} 能够匹配所有以 http_requests_total 为后缀的所有指标
2.2.2区间向量选择器(Range Vector Selectors)
区间向量选择器可以返回 0 个、1 个或多个时间序列上在给定时间范值围内的各自的一组样本。
区间向量选择器的不同之处在于,需要通过在瞬时向量选择器表达式后面添加包含在 [] 里的时长来表达需在时间时序上返回的样本所处的时间范围。
时间范围:以当前时间为基准时间点,指向过去一个特定的时间长度;例如,[5m] 是指过去 5 分钟之内。
◆可用的时间单位有 ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周)和 y(年)
◆必须使用整数时间,且能够将多个不同级别的单位进行串联组合,以时间单位由大到小为顺序,例如 1h30m,但不能使用 1.5h
2.2.3偏移向量选择器
前面介绍的选择器默认都是以当前时间为基准时间,偏移修饰器用来调整基准时间,使其往前偏移一段时间。偏移修饰器紧跟在选择器后面,使用关键字 offset 来指定要偏移的量。
例如,prometheus_http_requests_total offset 5m ,表示获取以 prometheus_http_requests_total 为指标名称的所有时间序列在过去 5 分钟之时的即时样本;
prometheus_http_requests_total[5m] offset 1d ,表示获取距此刻 1 天时间之前的 5 分钟之内的所有样本
向量表达式使用要点:
- 表达式的返回值类型亦是即时向量、范围向量、标题或字符串4种数据类型其中之一,但是,有些使用场景要求表达式返回值必须满足特定的条件,例如:
(1)需要将返回值绘制成图形时,仅支持即时向量类型的数据;
(2)对于诸如 rate、irate 之类的速率函数来说,其要求使用的却又必须是区间向量型的数据
- 由于区间向量选择器的返回的是区间向量型数据,它不能用于表达式浏览器中图形绘制功能
- 区间向量选择器通常会结合速率类的函数 rate、irate 一同使用
三、PromQL 的指标类型
-
3.1PromQL 有四个指标类型
- Counter :计数器,用于保存单调递增型的数据;例如站点访问次数等。数据单调递增,不支持减少,不能为负值,重启进程后,会被重置回 0 ;
- Gauge :仪表盘,用于存储有着起伏特征的指标数据,例如内存空闲大小等。数据可变大,可变小;重启进程后,会被重置;
- Histogram :累积直方图,将时间范围内的数据划分成不同的时间段,并各自评估其样本个数及样本值之和,因而可计算出分位数;
◆可用于分析因异常值而引起的平均值过大的问题;
◆分位数计算要使用专用的 histogram_quantile 函数;
- Summary :类似于 Histogram,但会在客户端直接计算并上报分位数;
3.1.1Counter
通常,Counter 的总数并没有直接作用,而是需要借助于 rate、topk、increase 和 irate 等函数来生成样本数据的变化状况(增长率/变化率):
●topk(3, prometheus_http_requests_total),获取该指标下 http 请求总数排名前 3 的时间序列
●rate(prometheus_http_requests_total[1h]) ,获取 1 小内,该指标下各时间序列上的 http 总请求数的增长速率
●irate(prometheus_http_requests_total[1h])
irate 为高灵敏度函数,用于计算指标的瞬时速率,基于样本范围内的最后两个样本进行计算,相较于 rate 函数来说,irate 更适用于短期时间范围内的变化速率分析。
3.1.2Gauge
Gauge 用于存储其值可增可减的指标的样本数据,常用于进行求和、取平均值、最小值、最大值等聚合计算;
也会经常结合 PromQL 的 delta 和 predict_linear 函数使用:
●delta 函数计算范围向量中每个时间序列元素的第一个值与最后一个值之差,从而展示不同时间点上的样本值的差值
例如,delta(cpu_temp_celsius{host="node01"}[2h]) ,返回该服务器上的CPU温度与2小时之前的差异
●predict_linear 函数可以预测时间序列 v 在 t 秒后的值,它通过线性回归的方式,对样本数据的变化趋势做出预测
例如,predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) ,基于 2 小时的样本数据,来预测主机可用磁盘空间在 4 个小时之后的剩余情况
3.1.3Histogram
对于 Prometheus 来说,Histogram 会在一段时间范围内对数据进行采样(通常是请求持续时长或响应大小等),并将其计入可配置的 bucket(存储桶)中 ,后续可通过指定区间筛选样本,也可以统计样本总数,最后一般将数据展示为直方图。
Prometheus 取值间隔的划分采用的是累积区间间隔机制,即每个 bucket 中的样本均包含了其前面所有 bucket 中的样本,因而也称为累积直方图。
Histogram 类型的每个指标有一个基础指标名称 <basename>,它会提供多个时间序列:
●<basename>_sum :所有样本值的总和
●<basename>_count :总的采样次数,它自身本质上是一个 Counter 类型的指标
●<basename>_bucket{le="<上边界>"} :观测桶的上边界,即样本统计区间,表示样本值小于等于上边界的所有样本数量
<basename>_bucket{le="+Inf"} :最大区间(包含所有样本)的样本数量
#使用 histogram
在大多数情况下人们一般倾向于使用某些量化指标的平均值,例如 CPU 的平均使用率、页面的平均响应时间。这种方式的问题很明显,以系统 API 调用的平均响应时间为例:如果大多数 API 请求都维持在 100ms 的响应时间范围内,而个别请求的响应时间需要 5s,那么就会导致某些 Web 页面的响应时间落到中位数的情况,而这种现象被称为长尾问题。
为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。例如,统计延迟在 0~10 ms 之间的请求数有多少,而 10~20 ms 之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram和Summary都是为了能够解决这样问题的存在,通过 Histogram 和 Summary 类型的监控指标,我们可以快速了解监控样本的分布情况。
http 请求响应时间 <= 0.005 秒 的请求次数为 10
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.005"} 10
http 请求响应时间 <= 0.01 秒 的请求次数为 15
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.01"} 15
http 请求响应时间 <= 0.025 秒 的请求次数为 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.025"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.05"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.075"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.1"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.25"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.5"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.75"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="1.0"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="2.5"} 18
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="5.0"} 20
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="7.5"} 20
prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="+Inf"} 20
所有样本值的大小总和,命名为 <basename>_sum
prometheus_http_request_duration_seconds_sum{handler="/metrics"} 10.107670803000001
样本总数,命名为 <basename>_count ,效果与 <basename>_bucket{le="+Inf"} 相同
prometheus_http_request_duration_seconds_count{handler="/metrics"} 20
注意:
bucket 可以理解为是对数据指标值域的一个划分,划分的依据应该基于数据值的分布。注意后面的样本是包含前面的样本,假设 prometheus_http_request_duration_seconds_bucket{...,le="0.01"} 的值为 10,而 prometheus_http_request_duration_seconds_bucket{...,le="0.05"} 的值为 30 ,那么意味着这 30 个样本中,有 10 个是小于 0.01s 的,其余 20 个采样点的响应时间是介于 0.01s 和 0.05s 之间的。
累积间隔机制生成的样本数据需要额外使用内置的 histogram_quantile 函数即可根据 Histogram 指标来计算相应的分位数(quantile),即某个 bucket 的样本数在所有样本数中占据的比例。
●histogram_quantile 函数在计算分位数时会假定每个区间内的样本满足线性分布状态,因而它的结果仅是一个预估值,并不完全准确
●预估的准确度取决于bucket区间划分的粒度;粒度越大,准确度越低
例如,假设 http 请求响应时间的样本的 9 分位数(quantile=0.9)的上边界为 0.01,即表示小于等于 0.01 的样本值的数量占总体样本值的 90%
histogram_quantile(prometheus_http_request_duration_seconds_bucket{handler="/metrics",le="0.01"}) 0.9
3.1.4Summary
Histogram 在客户端仅是简单的桶划分和分桶计数,分位数计算由 Prometheus Server 基于样本数据进行估算,因而其结果未必准确,甚至不合理的 bucket 划分会导致较大的误差。
Summary 是一种类似于 Histogram 的指标类型,但它在客户端于一段时间内(默认为 10 分钟)的每个采样点进行统计,计算并存储了分位数数值,Server 端直接抓取相应值即可。
对于每个指标,Summary 以指标名称 <basename> 为前缀,生成如下几个指标序列:
●<basename>_sum :统计所有样本值之和
●<basename>_count :统计所有样本总数
●<basename>{quantile="x"} :统计样本值的分位数分布情况,分位数范围:0 ≤ x ≤ 1
示例:
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173
prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002
prometheus_tsdb_wal_fsync_duration_seconds_count 216
从上面的样本中可以得知当前Promtheus Server进行 wal_fsync 操作的总次数为 216 次,耗时 2.888716127000002s。 其中中位数(quantile=0.5)的耗时为 0.012352463s,9分位数(quantile=0.9)的耗时为0.014458005s。
#Histogram 与 Summary 的异同:
它们都包含了 <basename>_sum 和 <basename>_count 指标,Histogram 需要通过 <basename>_bucket 来计算分位数,而 Summary 则直接存储了分位数的值。
四、Prometheus 的聚合函数
一般说来,单个指标的价值不大,监控场景中往往需要联合并可视化一组指标,这种联合机制即是指“聚合”操作,例如,将计数、求和、平均值、分位数、标准差及方差等统计函数应用于时间序列的样本之上生成具有统计学意义的结果等。
对查询结果事先按照某种分类机制进行分组(group by)并将查询结果按组进行聚合计算也是较为常见的需求,例如分组统计、分组求平均值、分组求和等。
Prometheus 的聚合操作由聚合函数针对一组值进行计算并返回值作为结果。
4.1聚合运算符
#Prometheus 内置提供的 11 个聚合函数,也称为聚合运算符:
●sum():对样本值求和
●min() :求取样本值中的最小者
●max() :求取样本值中的最大者
●avg() :对样本值求平均值
●count() :对分组内的时间序列进行数量统计
●stddev() :对样本值求标准差,以帮助用户了解数据的波动大小(或称之为波动程度)
●stdvar() :对样本值求方差,它是求取标准差过程中的中间状态
●topk() :逆序返回分组内的样本值最大的前 k 个时间序列及其值,即最大的 k 个样本值
●bottomk() :顺序返回分组内的样本值最小的前 k 个时间序列及其值,即最小的 k 个样本值
●quantile() :分位数,用于评估数据的分布状态,该函数会返回分组内指定的分位数的值,即数值落在小于等于指定的分位区间的比例
●count_values() :对分组内的时间序列的样本值进行数量统计,即等于某值的样本个数
4.2PromQL 的聚合表达式
PromQL 中的聚合操作语法格式可采用如下面两种格式之一:
- <聚合函数>(向量表达式) by|without (标签)
- <聚合函数> by|without (标签) (向量表达式)
分组聚合:先分组、后聚合
by :仅使用by子句中指定的标签进行聚合,结果向量中出现但未被 by 指定的标签则会被忽略;
为了保留上下文信息,使用 by 子句时需要显式指定其结果中原本出现的 job、instance 等一类的标签。
without:从结果向量中删除由 without 指定的标签,未指定的那部分标签则用作分组标准
示例:
(1)每台主机 CPU 在最近 5 分钟内的平均使用率
(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100
(2)查询 1 分钟的 load average 的时间序列是否超过主机 CPU 数量 2 倍
node_load1 > on (instance) 2 * count (node_cpu_seconds_total{mode="idle"}) by (instance)
(3)计算主机内存使用率
可用内存空间:空闲内存、buffer、cache 指标之和
node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes
已用内存空间:总内存空间减去可用空间
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
使用率:已用空间除以总空间
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100
(4)计算所有 node 节点所有容器总计内存:
sum by (instance) (container_memory_usage_bytes{instance=~"node*"})/1024/1024/1024
(5)计算 node01 节点最近 1m 所有容器 cpu 使用率:
sum (rate(container_cpu_usage_seconds_total{instance="node01"}[1m])) / sum (machine_cpu_cores{instance="node01"}) * 100
#container_cpu_usage_seconds_total 代表容器占用CPU的时间总和
(6)计算最近 5m 每个容器 cpu 使用情况变化率
sum (rate(container_cpu_usage_seconds_total[5m])) by (container_name)
(7)查询 K8S 集群中最近 1m 每个 Pod 的 CPU 使用情况变化率
sum (rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m])) by (pod_name)
#由于查询到的数据都是容器相关的,所以最好按照 Pod 分组聚合
每台主机 CPU 在最近 5 分钟内的平均使用率
(1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance)) * 100
浏览器输入node的ip:端口 查看数据哦
(2)查询 1 分钟的 load average 的时间序列是否超过主机 CPU 数量 2 倍
node_load1 > on (instance) 2 * count (node_cpu_seconds_total{mode="idle"}) by (instance)
(3)计算主机内存使用率
可用内存空间:空闲内存、buffer、cache 指标之和
node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes
五、部署 Alertmanager 发送告警
警报一直是整个监控系统中的重要组成部分,Prometheus监控系统中,采集与警报是分离的。警报规则在 Prometheus 定义,警报规则触发以后,才会将信息转发到给独立的组件
Alertmanager ,经过 Alertmanager r对警报的信息处理后,最终通过接收器发送给指定用户,另外在 Alertmanager 中没有通知组的概念,只能自己对软件重新Coding,或者使用第三方插件来实现。
注意,这个通知组不是Alertmanager中的group概念
Prometheus 对指标的收集、存储与告警能力分属于 Prometheus Server 和 AlertManager 两个独立的组件,前者仅负责定义告警规则生成告警通知, 具体的告警操作则由后者完成。
Alertmanager 负责处理由 Prometheus Server 发来的告警通知,Alertmanager对告警通知进行分组、去重后,根据路由规则将其路由到不同的receiver,如
Email、钉钉或企业微信等。
5.1AlertManager的4个概念
除了基本的告警通知能力外,Altermanager还支持对告警进行去重、分组、抑制、静默和路由等功能:
●分组(Grouping):将相似告警合并为单个告警通知的机制,在系统因大面积故障而触发告警潮时,分组机制能避免用户被大量的告警噪声淹没,进而导致关键信息的隐没
●抑制(Inhibition):系统中某个组件或服务故障而触发告警通知后,那些依赖于该组件或服务的其它组件或服务可能也会因此而触发告警,抑制便是避免类似的级联告警的一种特性,从而让用户能将精力集中于真正的故障所在
●静默(Silent):是指在一个特定的时间窗口内,即便接收到告警通知,Alertmanager也不会真正向用户发送告警信息的行为;通常,在系统例行维护期间,需要激活告警系统的静默特性
●路由(route):用于配置Alertmanager如何处理传入的特定类型的告警通知,其基本逻辑是根据路由匹配规则的匹配结果来确定处理当前告警通知的路径和行为
5.2Alertmanager工作机制
在Prometheus生态架构里,警报是由独立的俩部分组成,可以通过上图很清晰的了解到 Prometheus 的警报工作机制。其中 Prometheus 与 Alertmanager 是分离的俩个组件。我们使用Prometheus Server端通过静态或者动态配置
去拉取 pull
部署在k8s或云主机上的各种类别的监控指标数据,然后基于我们前面讲到的 PromQL
对这些已经存储在本地存储 HDD/SSD
的 TSDB
中的指标定义阈值警报规则 Rules
。Prometheus会根据配置的参数周期性的对警报规则进行计算,
如果满足警报条件,生产一条警报信息,将其推送到 Alertmanager 组件,Alertmanager 收到警报信息之后,会对警告信息进行处理,进行 分组 Group
并将它们通过定义好的路由 Routing
规则转到 正确的接收器 receiver
,
比如 Email
Slack
钉钉、企业微信 Robot(webhook)
企业微信
等,最终异常事件 Warning
、Error
通知给定义好的接收人,其中如钉钉是基于第三方通知来实现的,对于通知人定义是在钉钉的第三方组件中配置。
Alertmanager最新版本的下载地址可以从Prometheus官方网站Download | Prometheus获取。
5.3部署 Alertmanager
5.3.1准备安装包
上传 alertmanager-0.24.0.linux-amd64.tar.gz 到 /opt 目录中,并解压
cd /opt/
tar xf alertmanager-0.24.0.linux-amd64.tar.gz
mv alertmanager-0.24.0.linux-amd64 /usr/local/alertmanager
5.3.2修改 alertmanager 配置文件,添加邮件告警路由信息
vim /usr/local/alertmanager/alertmanager.yml
global: #在全局配置段设置发件人邮箱信息
resolve_timeout: 5m #定义持续多长时间未接收到告警通知后,就将告警状态标记为resolved
smtp_smarthost: 'smtp.qq.com:25'
smtp_from: '124481457@qq.com'
smtp_auth_username: '124481457@qq.com'
smtp_auth_password: 'yoevnefvknmqbjia' #此处为授权码,登录QQ邮箱【设置】->【账户】中的【生成授权码】获取
smtp_require_tls: false #禁用TLS的传输方式
route: #设置告警的分发策略
group_by: ['alertname'] #采用哪个标签来作为分组依据,这里使用告警名称做为规则,满足规则的告警将会被合并到一个通知中
group_wait: 20s #一组告警第一次发送之前等待的时延,即产生告警20s将组内新产生的消息合并发送,通常是0s~几分钟(默认是30s)
group_interval: 5m #一组已发送过初始告警通知的告警,接收到新告警后,下次发送通知前等待时延,通常是5m或更久(默认是5m)
repeat_interval: 20m #一组已经发送过通知的告警,重复发送告警的间隔,通常设置为3h或者更久(默认是4h)
receiver: 'my-email' #定义告警接收人
receivers: #设置收件人邮箱信息
- name: 'my-email'
email_configs:
- to: '960027936@139.com' #设置收件人邮箱地址
send_resolved: true
#global 配置段用于定义全局配置
#templates 配置段负责自定义告警内容模板文件
#route 配置段用于指定如何处理传入的告警
#receiver 配置段则定义了告警信息的接收器,每个接收器都应该有其具体的定义
5.3.3配置启动文件
cat > /usr/lib/systemd/system/alertmanager.service <<'EOF'
[Unit]
Description=alertmanager
Documentation=https://prometheus.io/
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/alertmanager/alertmanager \
--config.file=/usr/local/alertmanager/alertmanager.yml \
--log.level=debug
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
#启动 Alertmanager
systemctl start alertmanager
systemctl enable alertmanager
netstat -natp | grep :9093
5.3.4添加告警规则
mkdir /usr/local/prometheus/alert_rules
vim /usr/local/prometheus/alert_rules/instance_down.yaml
groups:
#若某个 Instance 的 up 指标的值转为 0 持续超过 1 分钟后,将触发告警
- name: AllInstances
rules:
- alert: InstanceDown #告警规则的名称,一个组内的告警规则名称必须惟一
# Condition for alerting
expr: up == 0 #基于PromQL表达式的告警触发条件(布尔表达式)
for: 1m #控制在触发告警之前,测试表达式的值必须为true的时长
#表达式值为true,但其持续时间未能满足for定义的时长时,相关的告警状态为pending
#满足该时长之后,相关的告警将被触发,并转为firing状态
#表达式的值为false时,告警将处于inactive状态
# Annotation - additional informational labels to store more information
annotations: #附加在告警之上的注解信息
title: 'Instance down'
description: Instance has been down for more than 1 minute.'
# Labels - additional labels to be attached to the alert
labels:
severity: 'critical' #在告警上附加的自定义的标签
#CPU 使用率大于 80% 触发告警
- name: node_alert
rules:
- alert: cpu_alert
expr: 100 -avg(irate(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)* 100 > 80
for: 5m
labels:
level: warning
annotations:
description: "instance: {{ $labels.instance }} ,cpu usage is too high ! value: {{$value}}"
summary: "cpu usage is too high"
5.3.5修改 prometheus 配置文件,添加 Alertmanager 实例的配置
vim /usr/local/prometheus/prometheus.yml
......
alerting:
alertmanagers:
- static_configs:
- targets:
- 192.168.10.19:9093
rule_files:
- "/usr/local/prometheus/alert_rules/*.yaml"
systemctl reload prometheus
5.3.6测试告警
systemctl stop node_exporter
5.4使用钉钉告警
5.4.1准备安装包
上传 prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz 到 /opt 目录中,并解压
cd /opt/
tar xf prometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gz
mv prometheus-webhook-dingtalk-2.1.0.linux-amd64 /usr/local/dingtalk
5.4.2在钉钉上进行群设置
创建群 -> 群设置 -> 智能群助手 -> 添加机器人 -> 添加机器人 -> 自定义
消息推送 开启
Webhook 复制
安全设置 -> 勾选 加签 -> 复制
点击完成
5.4.3修改 dingtalk 告警插件配置文件
cd /usr/local/dingtalk
cp -p config.example.yml config.yml
vim config.yml
timeout: 5s
## Uncomment following line in order to write template from scratch (be careful!)
#no_builtin_template: true
## Customizable templates path
templates:
- contrib/templates/legacy/template.tmpl
## You can also override default template using `default_message`
## The following example to use the 'legacy' template from v0.3.0
default_message:
title: '{{ template "legacy.title" . }}'
text: '{{ template "legacy.content" . }}'
## Targets, previously was known as "profiles"
targets:
webhook1:
url: <粘贴Webhook的内容>
# secret for signature
secret: <粘贴加签的内容>
#启动服务
./prometheus-webhook-dingtalk
5.4.4修改 alertmanager 配置文件
vim /usr/local/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
route:
group_by: [alertname]
group_wait: 10s
group_interval: 15s
repeat_interval: 20m
receiver: 'dingding.webhook1'
receivers:
- name: 'dingding.webhook1'
webhook_configs:
- url: 'http://192.168.10.80:8060/dingtalk/webhook1/send' #注意地址
send_resolved: true
systemctl reload alertmanager
5.4.5测试告警
systemctl stop node_exporter
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)