Prometheus简介

  • Prometheus是由前Google工程师从 2012 年开始在Soundcloud以开源软件的形式进行研发的系统监控和告警工具包,自此以后,许多公司和组织都采用了Prometheus作为监控告警工具,Prometheus的开发者和用户社区非常活跃,它现在是一个独立的开源项目,可以独立于任何公司进行维护
  • 为了证明这一点,Prometheus于2016年5月加入CNCF基金会,成为继Kubernetes之后的第二个CNCF托管项目
  • 在Kubernetes容器管理系统中,通常会搭配Prometheus进行监控,同时也支持多种Exporter采集数据,还支持Pushgateway进行数据上报,Prometheus性能足够支撑上万台规模的集群

Prometheus优势

Prometheus的主要优势有:

  • 由指标名称和和键/值对标签标识的时间序列数据组成的多维数据模型
  • 强大的查询语言 PromQL:可以对采集的metrics指标进行加法,乘法,连接等操作
  • 可以直接在本地部署,不依赖分布式存储;单个服务节点具有自治能力
  • 时间序列数据是服务端通过 HTTP 协议主动拉取获得的
  • 可以通过中间网关pushgateway的方式把时间序列数据推送到prometheus server端
  • 可以通过静态配置文件或服务发现来获取监控目标
  • 有多种可视化图像界面,如Grafana等
  • 高效的存储,每个采样数据占3.5 bytes左右,300万的时间序列,30s间隔,保留60天,消耗磁盘大概200G

Prometheus适用于什么场景

Prometheus适用于记录文本格式的时间序列,它既适用于以机器为中心的监控,也适用于高度动态的面向服务的监控,在微服务的世界中,它对多维数据收集和查询的支持有特殊优势

Prometheus是专为提高系统可靠性而设计的,它可以在断电期间快速诊断问题,每个Prometheus Server都是相互独立的,不依赖于网络存储或者其他远程服务

当基础架构出现问题时,可以通过Prometheus快速定位故障点,而且不会消耗大量的基础架构资源

Prometheus不适用于什么场景

Prometheus非常重视可靠性,即使在出现故障的情况下,也可以随时统计有关系统的可用系统信息

但是如果需要百分之百的准确度,例如按请求数量计费,那么Prometheus可能不太适合,因为它收集的数据可能不够详细完整精确

Prometheus组件

Prometheus 的整体架构以及生态系统组件如下图所示:

Prometheus介绍与部署 - 图1

从上图来看,Prometheus中包含的主要组件有:Prometheus server、Exporter、Pushgateway、Alertmanger

Prometheus server

Prometheus server是Prometheus架构中的核心组件,由Go语言编写而成,无第三方依赖关系,可以独立部署在物理服务器上、云主机、Docker容器内

主要是用于收集每个监控目标的数据,它本身就是一个实时数据库,将采集到的监控数据按照时间序列的形式存储在本地磁盘当中,并且可以对外提供查询支持和告警规则配置管理

Prometheus server又由三个部分组成

Retrieval:负责在活跃的目标主机上抓取监控指标数据

Storage:主要是把采集到的数据存储到磁盘中

PromQL:是Prometheus提供的查询语言模块

Exporter

Exporter用于输出被监控组件信息的HTTP接口统称为Exporter(导出器)

目前互联网公司常用的组件大部分都有Expoter供直接使用,比如Nginx、MySQL、Linux系统信息等

将监控数据采集的端点通过HTTP服务的形式暴露给Prometheus Server,Prometheus Server通过访问该Exporter提供的Endpoint端点,即可以获取到需要采集的监控数据

Pushgateway

Pushgateway是指用于支持短期临时或批量计划任务工作的汇聚节点

主要用于短期的job,此类存在的job时间较短,可能在Prometheus来拉取之前就自动消失了,所以针对这类job,设计成被监控端可以直接向Pushgateway推送Metric,这样Prometheus服务器端便可以定时去Pushgateway拉取Metric

各个目标主机可上报数据到Pushgateway,然后Prometheus server再统一从Pushgateway拉取数据

还有一个作用就是,当Prometheus搭建在外网去监控内网应用的情况下,由于内网有诸多安全限制使得无法穿透,因此也需要Pushgateway,被监控目标会主动推送数据到Pushgateway,然后Prometheus再去Pushgateway获取数据

Alertmanger

主要用于处理从Prometheus服务器端接收到的alerts(警报)信息,对其去重数据、分组、路由到正确的接收方,发出告警,支持丰富的告警方式,常见的接收方式有:电子邮件,微信,钉钉等

Service Discovery

动态发现待监控的目标主机,从而完成监控配置的重要组件,在容器环境中尤为重要,该组件目前由Prometheus Server内建支持

工作流程

  1. Prometheus server直接从监控目标中或者间接通过推送网关来拉取监控指标(metrics)每个抓取目标需要暴露一个HTTP服务的接口
    • 直接方式:通过配置静态job方式被Prometheus server采集到;或者通过一些组件自带的Exporter采集相应组件的数据
    • 间接方式:Client主动推送metrics到PushGateway,然后Prometheus server定时去PushGateway上抓取数据
  2. Prometheus server把采集到的监控指标数据保存到本地磁盘或者数据库
  3. Prometheus server将存储的监控指标数据按时间序列存储
  4. 通过配置报警规则,把触发的报警发送到Alertmanger
  5. Alertmanager通过配置报警接收方,发送报警到邮件,微信或者钉钉等
  6. 可以在Prometheus自带的Web UI界面或者Grafana进行PromQL查询语言,查询监控数据

Prometheus介绍与部署 - 图2

Prometheus相关概念

数据模型

Prometheus所有采集的监控数据均以指标的形式保存在内置的时间序列数据库当中(TSDB):属于同一指标名称、同一标签集合的、有时间戳标记的数据流

除了存储的时间序列,Prometheus还可以根据查询请求产生临时的、衍生的时间序列作为返回结果

指标名称和标签

每一条时间序列数据由指标名称(Metric Name)以及一组标签(键值对)唯一标识

指标名称:

其中指标的名称 (Metric Name)可以反映被监控样本的含义(例如,httprequest_total可以看出来表示当前系统接收到的http请求总量),指标名称只能由ASCII字符、数字、下划线以及冒号组成,同时必须匹配正则表达式 `[a-zA-Z:][a-zA-Z0-9:]*`,其中以 _ 作为前缀的标签,是系统保留的关键字,只能在系统内部使用

冒号用来表示用户自定义的记录规则,不能在 exporter 中或监控对象直接暴露的指标中使用冒号来定义 指标名称

标签:

通过使用标签,Prometheus开启了强大的多维数据模型:对于相同的指标名称,通过不同标签列表的 集合,会形成特定的度量维度实例(例如,所有包含度量名称为 /api/tracks 的 HTTP 请求,打上 method=POST 的标签,就会形成具体的 HTTP 请求)

查询语言在这些指标和标签列表的基础上进行过滤和聚合,改变任何度量指标上的任何标签值(包括添加或删除指标),都会创建新的时间序列

样本

在时间序列中的每一个点称为样本,样本由以下三部分组成

  • 指标(metric):指标名称和描述当前样本特征的标签集(labelsets)
  • 时间戳:一个精确到时间毫秒的时间戳
  • 样本值:一个浮点型数据表示当前样本的值

表示方式

通过如下表示方式表示指定名称和指定标签集合的时间序列

  1. <metric name>{<label name>=<label value>, ...}

例如,指标名称为api_http_requests_total,标签为method="POST"handler="/messages"的时间序列可以表示为:

  1. api_http_requests_total{method="POST",handler="/messages"}

指标类型

Prometheus的客户端库中提供了四种核心的指标类型,但这些类型只是在客户端库(客户端可以根据不同的数据类型调用不同的API接口)和在线协议中

在Prometheus Server中并不对指标类型进行区分,而是简单地把这些指标统一视为无类型的时间序列

Counter计数器

  • Counter 用于累计值,例如记录服务请求次数、任务完成数、错误发生次数
  • 一直增加,不会减少
  • 重启进程后,会被重置

Counter类型数据可以让用户方便的了解事件发生的速率的变化,在PromQL内置的相关操作函数可以提供相应的分析,比如HTTP应用请求量来进行说明

  1. # 通过rate()函数获取HTTP请求量的增长率
  2. rate(http_requests_total[5m])
  3. # 查询当前系统中,访问量前10的HTTP地址
  4. topk(10, http_requests_total)

Gauge仪表盘

  • Gauge是常规数值,例如温度变化、内存使用变化、当前并发请求的数量
  • 可增加、可减少
  • 重启进程后,会被重置

通过PromQL内置的函数delta()可以获取样本在一段时间内的变化情况

  1. # 计算cpu温度在两小时内的差异
  2. dalta(cpu_temp_celsius{host="zeus"}[2h])

通过PromQL内置函数predict_linear()基于简单线性回归的方式,对样本数据的变化趋势做出预测

  1. # 基于两小时的样本数据,来预测主机可用磁盘空间在4个小时之后的剩余情况
  2. predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0

Histogram直方图

在大多数情况下人们都倾向于使用某些量化指标的平均值,例如CPU的平均使用率、页面的平均响应时间,这种方式的问题很明显,以系统API调用的平均响应时间为例:如果大多数API请求都维持在100ms的响应时间范围内,而个别请求的响应时间需要5秒,那么就会导致某些Web页面的响应落到中位数的情况,而这种现象被称为长尾问题

为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组

例如,统计延迟在0-10ms之间的请求数有多少而10-20ms之间的请求数又有多少,通过这种方式可以快速分析系统慢的原因,HistogramSummary都是为了能够解决这样问题的存在,通过Histogram和Summary类型的监控指标我们可以快速了解监控样本的分布情况

Prometheus介绍与部署 - 图3

Histogram是柱状图,在Prometheus系统的查询语言中,有三种作用:

  1. 在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等),并将其计入可配置的存储桶(bucket)中,后续可通过指定区间筛选样本,也可以统计样本总数,最后一般将数据展示为直方图
  2. 对每个采样点值累计和(sum)
  3. 对采样点的次数累计和(count)

如果定义一个度量类型为Histogram,则Prometheus会自动生成三个对应的指标

三种指标

假设指标名称为

  • 样本的值分布在 bucket 中的数量,命名为 <basename>_bucket{le="<上边界>"},这个值表示指标值小于等于上边界的所有样本数量
  1. # 在总共2次请求当中,http 请求响应时间 <=0.005 秒 的请求次数为0
  2. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.005",} 0.0
  3. # 在总共2次请求当中,http 请求响应时间 <=0.01 秒 的请求次数为0
  4. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.01",} 0.0
  5. # 在总共2次请求当中,http 请求响应时间 <=0.025 秒 的请求次数为0
  6. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.025",} 0.0
  7. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.05",} 0.0
  8. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.075",} 0.0
  9. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.1",} 0.0
  10. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.25",} 0.0
  11. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.5",} 0.0
  12. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.75",} 0.0
  13. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="1.0",} 0.0
  14. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="2.5",} 0.0
  15. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="5.0",} 0.0
  16. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="7.5",} 2.0
  17. # 在总共2次请求当中,http 请求响应时间 <=10 秒 的请求次数为2
  18. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="10.0",} 2.0
  19. io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="+Inf",} 2.0

bucket可以理解为是对数据指标值域的一个划分,假设 xxx_bucket{…,le=”0.01”} 的值为10,而 xxx_bucket{…,le=”0.05”} 的值为30,那么意味着这30个采样点中,有10个是小于10 ms的,其余 20 个采样点的响应时间是介于10 ms和50 ms之间的

  • 所有样本值的大小总和,命名为 <basename>_sum
  1. # 实际含义:发生的2次http请求总的响应时间为13.107670803000001秒
  2. io_namespace_http_requests_latency_seconds_histogram_sum{path="/",method="GET
  3. ",code="200",} 13.107670803000001
  • 样本总数,命名为 <basename>_count,值和 <basename>_bucket{le="+Inf"} 相同
  1. # 实际含义:当前一共发生了2次http请求
  2. io_namespace_http_requests_latency_seconds_histogram_count{path="/",method="GET",code="200",} 2.0

Summary分位图

与 Histogram 类型类似,用于表示一段时间内的数据采样结果(通常是请求持续时间或响应大小等),但它直接存储了分位数(通过客户端计算,然后展示出来),而不是通过区间来计算,有三种作用:

  1. 对于每个采样点进行统计,并形成分位图
  2. 统计班上所有同学的总成绩(sum)
  3. 统计班上同学的考试总人数(count)

三种指标

  • 样本值的分位数分布情况,命名为 <basename>{quantile="<φ>"}
  1. # 含义:这12次http请求中有50%的请求响应时间是 3.052404983s
  2. io_namespace_http_requests_latency_seconds_summary{path="/",method="GET",code="200",quantile="0.5",} 3.052404983
  3. # 含义:这12次http请求中有90%的请求响应时间是 8.003261666s
  4. io_namespace_http_requests_latency_seconds_summary{path="/",method="GET",code="200",quantile="0.9",} 8.003261666
  • 所有样本值的大小总和,命名为 <basename>_sum
  1. # 含义:这12次http请求的总响应时间为51.029495508s
  2. io_namespace_http_requests_latency_seconds_summary_sum{path="/",method="GET",code="200",} 51.029495508
  • 样本总数,命名为 <basename>_count
  1. # 含义:当前一共发生了 12 次 http 请求
  2. io_namespace_http_requests_latency_seconds_summary_count{path="/",method="GET",code="200",} 12.0

Histogram 与 Summary 的异同

它们都包含了<basename>_sum<basename>_count指标,Histogram 需要通过<basename>_bucket 来计算分位数,而Summary则直接存储了分位数的值

Jobs和Instances

在Prometheus中,任何被采集的目标,即每一个暴露监控样本数据的HTTP服务都称为一个实例instance,通常对应于单个进程

具有相同采集目的实例集合称为作业job

Prometheus Server部署

使用二进制文件进行部署

  1. [root@server1 ~]# wget
  2. https://github.com/prometheus/prometheus/releases/download/v2.25.0/prometheus
  3. -2.25.0.linux-amd64.tar.gz
  • 获取软件包的哈希值,与官网提供的软件包的哈希值进行对比,保证下载的Prometheus软件包的完整性
  1. [root@server1 ~]# sha256sum prometheus-2.25.0.linux-amd64.tar.gz
  2. 2dc529905e581927a4e879454e4142a4f5b7a8f3e6effe651e48e547e5bb7f15 prometheus-2.25.0.linux-amd64.tar.gz
  • 解压缩二进制软件包到指定的安装目录,运行Prometheus
  1. [root@server1 ~]# mkdir /data
  2. [root@server1 ~]# tar -zxvf prometheus-2.25.0.linux-amd64.tar.gz -C /data/
  3. [root@server1 ~]# cd /data/
  4. [root@server1 data]# chown -R root:root prometheus-2.25.0.linux-amd64
  5. # 建立软链接,方便访问
  6. [root@server1 data]# ln -sv prometheus-2.25.0.linux-amd64 prometheus
  7. "prometheus" -> "prometheus-2.25.0.linux-amd64"
  8. [root@server1 data]# ll
  9. 总用量 0
  10. lrwxrwxrwx 1 root root 29 3 2 20:53 prometheus -> prometheus-2.25.0.linux-amd64
  11. drwxr-xr-x 4 root root 132 2 18 2021 prometheus-2.25.0.linux-amd64
  • 启动Prometheus,当终端关闭或者按下Ctrl+c服务就会关闭
  1. [root@server1 data]# cd prometheus
  2. [root@server1 prometheus]# ./prometheus

Prometheus介绍与部署 - 图4

  • 热加载更新配置

在Prometheus日常维护中,会对配置文件prometheus.yml进行编辑操作,此时通常需要对Prometheus服务进行重新启动才可以完成对配置文件的加载;但是也可以通过动态的热加载来更新prometheus.yml中的配置信息

启动时加上参数--web.enable-lifecycle

  1. [root@server1 prometheus]# ./prometheus --web.enable-lifecycle

首先查看进程ID,向进程发送SIGHUP信号

  1. ps -aux | grep prometheus
  2. kill -HUP pid

通过HTTP API发送POST请求到/-/reload

  1. curl -X POST http://localhost:9090/-/reload # Prometheus端口号为9090
  • 关闭防火墙和SELinux
  1. [root@server1 prometheus]# systemctl stop firewalld
  2. [root@server1 prometheus]# setenforce 0
  • 访问Web UI界面,端口为9090

Prometheus介绍与部署 - 图5

Prometheus主配置文件

主配置文件介绍

  1. global # 此片段为全局配置
  2. scrape_interval # 每次数据采集的时间间隔,默认为1分钟
  3. scrape_timeout # 采集请求超时时间,默认为10秒
  4. evaluation_interval # 执行rules的频率,默认为1分钟
  5. '-----------------------------------------------------------'
  6. alerting # 此片段指定报警配置,这里主要是指定Prometheus将报警规则推送到指定的alertmanager实例地址
  7. '-----------------------------------------------------------'
  8. rule_files # 此片段指定报警规则文件,Prometheus根据这些规则信息,推送报警信息到alertmanager中
  9. '-----------------------------------------------------------'
  10. scrape_configs # 此片段主要用于配置被采集数据节点操作,每一个采集配置主要由以下几个参数
  11. job_name # 全局唯一名称
  12. static_configs # 静态指定服务job
  13. scrape_interval # 抓取间隔,默认继承global值
  14. scrape_timeout # 抓取超时时间,默认继承global值。
  15. metrics_path # 从targets获取meitric的HTTP资源路径,默认是/metrics
  16. honor_labels # Prometheus如何处理标签之间的冲突:若设置为True,则通过保留变迁来解决冲突;若设置为false,则通过重命名;
  17. scheme # 用于请求的协议方式,默认是http
  18. params # 数据采集访问时HTTP URL设定的参数
  19. relabel_configs # 采集数据重置标签配置
  20. metric_relabel_configs # 重置标签配置
  21. sample_limit # 对每个被已知样本数量的每次采集进行限制,如果超过限制,该数据将被视为失败,默认值为0,表示无限制
  22. targets # 指定抓取的端点
  23. '-----------------------------------------------------------'
  24. remote_write # 指定后端的存储的写入API地址
  25. remote_read # 指定后端的存储的读取API地址

示例prometheus.yml(去注释)

  1. global:
  2. scrape_interval: 15s
  3. evaluation_interval: 15s
  4. alerting:
  5. alertmanagers:
  6. - static_configs:
  7. - targets:
  8. rule_files:
  9. scrape_configs:
  10. - job_name: 'prometheus'
  11. static_configs:
  12. - targets: ['localhost:9090']
  13. - job_name: 'node_exporter'
  14. static_configs:
  15. - targets: ['192.168.31.20:9100']
  16. - job_name: 'mysqld_exporter'
  17. scrape_interval: 10s
  18. static_configs:
  19. - targets: ['192.168.31.20:9104']