Prometheus技术讲义
1简介
Prometheus是一个开源的系统监控和告警系统,现在已经加入到CNCF基金会,成为继k8s之后第二个在CNCF维护管理的项目,在kubernetes容器管理系统中,通常会搭配prometheus进行监控,prometheus支持多种exporter采集数据,还支持通过pushgateway进行数据上报,prometheus在性能上可以支持上万台规模的集群。
作为新一代的监控框架,Prometheus 具有以下特点:
● 强大的多维度数据模型。
● 时间序列数据通过 metric 名和键值对来区分。
● 所有的 metrics 都可以设置任意的多维标签。
● 数据模型更随意,不需要刻意设置为以点分隔的字符串。
● 可以对数据模型进行聚合,切割和切片操作。
● 支持双精度浮点类型,标签可以设为全 unicode。
● 灵活而强大的查询语句(PromQL):在同一个查询语句,可以对多个metrics 进行乘法、加法、连接、取分数位等操作。
● 易于管理:Prometheus server 是一个单独的二进制文件,可直接在本地工作,不依赖于分布式存储。
● 高效:平均每个采样点仅占 3.5 bytes,且一个 Prometheus server 可以处理数百万的 metrics。
● 使用 pull 模式采集时间序列数据,这样不仅有利于本机测试而且可以避免有问题的服务器推送坏的 metrics。
● 可以采用 push gateway 的方式把时间序列数据推送至 Prometheus server 端。
● 可以通过服务发现或者静态配置去获取监控的 targets。
● 有多种可视化图形界面。
● 易于伸缩。
2架构图
3 prometheus组件介绍
● Prometheus Server: 用于收集和存储时间序列数据。
● Client Library: 客户端库,检测应用程序代码,当Prometheus抓取实例的HTTP端点时,客户端库会将所有跟踪的metrics指标的当前状态发送到prometheus server端。
● Exporters: prometheus支持多种exporter,通过exporter可以采集metrics数据,然后发送到prometheus server端
● Alertmanager: 从 Prometheus server 端接收到 alerts 后,会进行去重,分组,并路由到相应的接收方,发出报警,常见的接收方式有:电子邮件,微信,钉钉, slack等。
● Grafana:监控仪表盘
● pushgateway: 各个目标主机可上报数据到pushgatewy,然后prometheus server统一从pushgateway拉取数据。
4基本原理
Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。
5服务过程
● Prometheus Daemon负责定时去目标上抓取metrics(指标)数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。Prometheus采用PULL的方式进行监控,即服务器可以直接通过目标PULL数据或者间接地通过中间网关来Push数据。
● Prometheus在本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中。
● Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。
● PushGateway支持Client主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。
● Alertmanager是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。
6部署
解压prometheus-2.17.2.linux-amd64.tar.gz 到指定文件夹,修改配置文件prometheus.yml,配置需要抓取监控数据的服务的地址。使用命令./prometheus --config.file=prometheus.yml --web.listen-address=:9090启动prometheus。
7度量类型
7.1、Counter(计数器类型)
Counter类型的指标代表的是一种计数器,是随时间只增不减永远不会减少(除非系统或者服务发生了重置)的。Counter一般用于累计值,例如记录请求次数,任务完成数、错误发生次数;还可以计算其在一段时间范围内的增量和变化速率,如果是counter类型的数据,首先应该想到是否要使用rate()或者increase()函数来计算其变化速率。
不是Counter类型的度量却当做Counter类型来计算,会得到一个错误的结果。例如,使用计数器来计算当前正在运行的进程的数量;应该使用Gauge。
7.2、Gauge(仪表测量类型)
Gauge类型的指标值是可增可减的,可以用于反应当前应用的状态。比如在监控主机时,主机当前的内存大小(node_meomory_MemFree),可用内存大小(node_memory_MemAvailable)。或者主机CPU使用率,内存使用率,温度等。
7.3、Histogram(直方图类型)
Histogram是对数据进行采样的指标类型,用来展示数据集的频率分布。Histogram是表示数值分布的图形,它将数值分组到一个一个的bucket当中,然后计算每个bucket中值出现次数。在Histogram上,X轴表示表示数值的范围(例如人的身高/网站请求响应时间),Y轴表示对应数值出现的频次(对应身高/响应时间出现的次数)。在直方图上,对于各数值出现的次数,分布是否对称都显示的很清楚(对于这类数据如果只是简单的对数值取最小、最大或平均是没有多大意义的)。统计学上有一个段子是说:一个统计学家非常自信地去趟一条平均深度只有1米的河,后来他淹死了(类似把互联网大佬的身家和自己来平均一下)。这是取平均值的一个严重缺陷。
7.4、Summary(摘要类型)
Summary类型和Histogram类型相似,主要也用于表示一段时间内数据采样(通常是请求持续时间或响应时间)结果,它直接存储了quantile(分位数)数据,而不是根据统计区间计算出来的。
什么是分位数?大家可度娘一下。总之,分位数能更好地表示数值的分布,也可以找出异常数值,便于优化。
Summary与Histogram相比,区别如下:
都包含 < basename>_sum和< basename>_count;
Histogram需要通过< basename>_bucket计算quantile,而Summary直接存储了 quantile的值。
用例:
# 事件发生总的次数
# 事件产生的值的总和
# 事件产生的值的分布情况
8查询语法
常用表达式:fun(metric_name{Instant vector selectors}[Range Vector Selectors])
Prometheus提供了一种名为PromQL (Prometheus查询语言)的功能查询语言,该语言允许用户实时选择和聚合时间序列数据。查询的结果可以显示为图表,如在Prometheus本身内置的Web控制台展示,又或者使用诸如Grafana数据展示工具。
● 瞬时向量选择器(Instant vector selectors)可以即时为每个度量选择一个样本值(最近的一个值),最简单的形式就是只给定度量名称,这样将返回所有包含此度量名称的时间序列元素的瞬时向量。可以通过在度量名称后的大括号{}中附加以逗号分隔的标签匹配器列表来进一步筛选这些时间序列。
在PromQL中,使用以下符号对标签值进行正则匹配:
= (等于),标签的值必须相等,并且区分大小写。
!=(不等于),标签的值必须不相等,并且区分大小写。
=~(模糊匹配),标签的值正则(模糊)匹配。
!~(模糊匹配取反),标签的值正则(模糊)匹配后取反。
● 范围向量选择器(Range Vector Selectors)与瞬时向量类似,只是它从当前瞬间选择一个样本范围。从语法上讲,范围向量所持续的时间是放在瞬时向量选择器末尾的中括号[]中,用来获取指定的时间间隔内瞬时向量的所有值。
● 偏移修饰器(Offset modifier)
Offset 在瞬时/范围向量选择器中用于对过去一段时间的偏移计算,例如,计算5分钟前CPU的空闲率
avg(irate(node_cpu_seconds_total{nodename=~"monitor01", mode="idle"}[1m] offset 5m))
注意:offset 的使用范围是在:瞬时/范围向量选择器中
9常用函数
https://prometheus.io/docs/prometheus/latest/querying/functions/
● increase()函数,该函数结合counter数据类型使用,获取区间向量中的第一个和最后一个样本并返回其增长量。如果除以[区间]时间(秒)就可以获取该时间内的平均增长率。
# 获取近1分钟内网卡接收的字节数,如果不除以时间,则为区间内累计增量。
increase(node_network_receive_bytes_total{device=~"ens.*",nodename=~"monitor01"}[1m])
● rate()函数,该函数配置counter数据类型使用,用于获取在这个时间段内的平均每秒增量。
# 通过rate()函数获取在1分钟时间内网卡每秒接收字节数,如果再乘以区间时间,则同increase()函数。
rate(node_network_receive_bytes_total{device=~"ens.*",nodename=~"monitor01"}[1m])
以下查询结果同increase()函数。
rate(node_network_receive_bytes_total{device=~"ens.*",nodename=~"monitor01"}[1m]) * 60
● irate()函数,用于计算指定时间范围内每秒瞬时增长率,是基于该时间范围内最后两个数据点来计算。rate和irate函数都用于计算某个指标在一定时间间隔内的变化速率。但是它们的计算方法有所不同:irate取的是在指定时间范围内的最后两个数据点来算速率,而rate会取指定时间范围内所有数据点,算出一组速率,然后取平均值作为结果。
所以官网文档说:irate适合快速变化(fast-moving)的计数器(counter),而rate适合缓慢变化(slow-moving)的计数器(counter)。
● sum()函数,在实际工作中CPU大多是多核心,而node_cpu_seconds_total会将每个核的数据都单独显示出来,但我们关心的是CPU总的使用情况,因此可以使用sum()函数求和后得出一条总的数据,使用sum()函数获取实例在1分钟时间内,user在所有vCPU上的使用百分比之和
# sum(increase(node_cpu_seconds_total{nodename=~"monitor01",mode="user"}[1m])/60)
● count()函数,该函数用于进行统计,或用来做一些模糊判断,比如判断服务器连接数大于某个值,为真则返回1,否则返回null。
例如统计vCPU数
count(node_cpu_seconds_total{nodename="monitor01",mode="idle"})
或者统计当前TCP建立连接数是否大于200
count(node_netstat_Tcp_CurrEstab{nodename=~"monitor01"} >200 )
● topk()函数,该函数可以从大量数据中取出排行前N的数值,N可以自定义。
# 例如从所有主机中找出近5分钟网卡流量排名前3的主机(Counter类型数据)。
topk(3,rate(node_network_receive_bytes_total{device=~'ens.*'}[5m]))
或者用increase
topk(3,increase(node_network_receive_bytes_total{device=~'ens.*'}[5m])/300)
# 例如从所有主机中找出连接数前3的主机(Gauge类型数据)。
topk(3,node_netstat_Tcp_CurrEstab)
● predict_linear()函数,根据前一个时间段的值来预测未来某个时间点数据的走势。例如,我们可以用predict_linear()函数,根据近1天的磁盘使用来预测磁盘在未来2天增长情况,大概在未来多长时间可以将磁盘占满。
predict_linear(node_filesystem_free_bytes{device="rootfs",nodename=~"monitor01",mountpoint="/"}[1d],2*86400)