Prometheus

基础

Prometheus 是一个开源的完整监控解决方案,其对传统监控系统的测试和告警模型进行了彻底的颠覆,形成了基于中央化的规则计算、统一分析和告警的新模型,基于 Golang 编写。

优点

易于管理

Prometheus 基于 Pull 模型的架构方式,可以在任何地方(本地电脑,开发环境,测试环境)搭建我们的监控系统。对于一些复杂的情况,还可以使用 Prometheus 服务发现 (Service Discovery) 能力动态管理监控目标。

强大的数据模型

所有采集的监控数据均以指标 metric 的形式保存在内置的时间序列数据库当中 TSDB。所有的样本除了基本的指标名称以外,还包含一组用于描述该样本特征的标签。

如下所示:

1
2
http_request_status{code='200',content_path='/api/path', environment='produment'} => [value1@timestamp1,value2@timestamp2...]
http_request_status{code='200',content_path='/api/path2', environment='produment'} => [value1@timestamp1,value2@timestamp2...]

每一条时间序列由指标名称 Metrics Name 以及一组标签 Labels 唯一标识。每条时间序列按照时间的先后顺序存储一系列的样本值。表示维度的标签可能来源于你的监控对象的状态,比如 code=404 或者 content_path=/api/path。基于这些 Labels ,我们可以方便地对监控数据进行聚合、过滤、裁剪。

强大的查询语言 PromSQL

Prometheus 内置了一个强大的数据查询语言 PromQL。 通过 PromQL 可以实现对监控数据的查询、聚合。同时 PromQL 也被应用于数据可视化(如 Grafana )以及告警当中。

高效

对于监控系统而言,大量的监控任务必然导致有大量的数据产生。而Prometheus 可以高效地处理这些数据,对于单一 Prometheus Server 实例而言它可以处理:

  • 数以百万的监控指标
  • 每秒处理数十万的数据点

易于集成

Prometheus 社区还提供了大量第三方实现的监控数据采集支持:MySQLConsulRedis 等等。

可视化

Prometheus Server 中自带了一个 Prometheus UI,通过这个 UI 可以方便地直接对数据进行查询,并且支持直接以图形化的形式展示数据。开源第三方可视化工具 Grafana 也已经提供了完整的 Prometheus 支持,基于 Grafana 可以创建更加精美的监控图标。

缺点:相比于 zabbix,更加消耗资源

架构

Prometheus architecture

Prometheus Server:是 Prometheus 组件中的核心部分,负责实现对监控数据的获取、存储以及查询。

  • Prometheus Server 可以通过静态配置管理监控目标(prometheus.yml),也可以配合使用 Service Discovery 的方式动态管理监控目标,并从这些监控目标中获取数据。
  • Prometheus Server 需要对采集到的监控数据进行存储,它本身就是一个时序数据库,将采集到的监控数据按照时间序列的方式存储在本地磁盘当中。
  • Prometheus Server 对外提供了自定义的 PromQL 语言,实现对数据的查询以及分析。

exporters:负责将监控数据采集的端点通过 HTTP 服务的形式暴露给 Prometheus ServerPrometheus Server 通过访问该 exporter 提供的 Endpoint 端点,即可获取到需要采集的监控数据。一般来说可以将exporter 分为 2 类:

  • 直接采集:这一类 exporter 直接内置了对 Prometheus 监控的支持,例如:Kubernetes
  • 间接采集:原有监控目标并不直接支持 Prometheus,因此我们需要通过 Prometheus 提供的 Client Library 编写该监控目标的监控采集程序。例如:监控主机有 node_exporter,监控 MySQLmysqld_exporter

Pushgateway:由于 Prometheus 数据采集基于 Pull 模型进行设计,因此在网络环境的配置上必须要让Prometheus Server 能够直接与 exporter 进行通信。 当这种网络需求无法直接满足时,就可以利用PushGateway 来进行中转。可以通过 PushGateway 将内部网络的监控数据主动 PushGateway 当中。而 Prometheus Server 则可以采用同样 Pull 的方式从 PushGateway 中获取到监控数据。

Alertmanager:在 Prometheus Server 中支持基于 PromQL 创建告警规则,如果满足 PromQL 定义的规则,则会产生一条告警,而告警的后续处理流程则由 AlertManager 进行管理。在 AlertManager 中我们可以与邮件,Slack 等等内置的通知方式进行集成,也可以通过 Webhook 自定义告警处理方式。AlertManagerPrometheus 体系中的告警处理中心。

Web UI:数据可视化,主要使用第三方工具 Grafana 来实现。

安装

Prometheus Server

二进制包方式安装

(1)下载最新版本 软件包

(2)解压

1
2
3
wget https://github.com/prometheus/prometheus/releases/download/v2.12.0/prometheus-2.12.0.linux-amd64.tar.gz
tar -xzf prometheus-2.12.0.linux-amd64.tar.gz
cd prometheus-2.12.0.linux-amd64

(3)配置文件 promethes.yml,修改 job_name

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.

static_configs:
- targets: ['localhost:9090']

(4)创建数据存储目录,默认的存储路径为 data/,用户也可以通过参数 --storage.tsdb.path="data/" 修改本地数据存储的路径。

1
mkdir -p data

(5)启动 prometheus 服务,http://10.133.0.53:9090

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ./prometheus
level=info ts=2019-08-26T07:33:43.420Z caller=main.go:293 msg="no time or size retention was set so using the default time retention" duration=15d
level=info ts=2019-08-26T07:33:43.420Z caller=main.go:329 msg="Starting Prometheus" version="(version=2.12.0, branch=HEAD, revision=43acd0e2e93f9f70c49b2267efa0124f1e759e86)"
level=info ts=2019-08-26T07:33:43.420Z caller=main.go:330 build_context="(go=go1.12.8, user=root@7a9dbdbe0cc7, date=20190818-13:53:16)"
level=info ts=2019-08-26T07:33:43.421Z caller=main.go:331 host_details="(Linux 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 ptdsmapp05 (none))"
level=info ts=2019-08-26T07:33:43.421Z caller=main.go:332 fd_limits="(soft=65536, hard=65536)"
level=info ts=2019-08-26T07:33:43.421Z caller=main.go:333 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2019-08-26T07:33:43.423Z caller=web.go:448 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2019-08-26T07:33:43.423Z caller=main.go:654 msg="Starting TSDB ..."
level=info ts=2019-08-26T07:33:43.442Z caller=head.go:509 component=tsdb msg="replaying WAL, this may take awhile"
level=info ts=2019-08-26T07:33:43.445Z caller=head.go:557 component=tsdb msg="WAL segment loaded" segment=0 maxSegment=0
level=info ts=2019-08-26T07:33:43.446Z caller=main.go:669 fs_type=XFS_SUPER_MAGIC
level=info ts=2019-08-26T07:33:43.446Z caller=main.go:670 msg="TSDB started"
level=info ts=2019-08-26T07:33:43.446Z caller=main.go:740 msg="Loading configuration file" filename=prometheus.yml
level=info ts=2019-08-26T07:33:43.448Z caller=main.go:768 msg="Completed loading of configuration file" filename=prometheus.yml
level=info ts=2019-08-26T07:33:43.448Z caller=main.go:623 msg="Server is ready to receive web requests."

docker 方式安装

直接使用 Prometheus 的镜像即可启动 Prometheus Server。启动完成后,可以通过 http://10.133.0.53:9090 访问 UI 界面:

1
docker run -p 9090:9090 -v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

Prometheus UI

node_exporter

采集主机的运行指标如 CPU、内存、磁盘等信息。同样采用 Golang 编写,并且不存在任何的第三方依赖。

1
2
3
4
5
wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz
tar -xzf node_exporter-0.18.1.linux-amd64.tar.gz
cd node_exporter-0.18.1.linux-amd64
cp node_exporter-0.18.1.linux-amd64/node_exporter /usr/local/bin
./node_exporter

启动成功后,可以看到如下输出:

1
INFO[0000] Listening on :9100                            source="node_exporter.go:170"

访问 http://10.133.0.53:9100/metrics,可以看到采集到的监控数据:

1
2
3
4
5
6
# HELP node_cpu Seconds the cpus spent in each mode.
# TYPE node_cpu counter
node_cpu{cpu="cpu0",mode="idle"} 362812.7890625
# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 3.0703125

HELP:解释当前指标的含义。

TYPE:说明当前指标的数据类型。有四种数据类型,counter(计数器)、gauge(仪表盘)、histogram(直方图)、summary(求和)

除了这些之外,还可以看到如下监控指标:

  • node_boot_time:系统启动时间
  • node_cpu:系统 CPU 使用量
  • node_disk_*:磁盘 IO
  • node_filesystem_*:文件系统用量
  • node_load1:系统负载
  • node_memeory_*:内存使用量
  • node_network_*:网络带宽
  • node_time:当前系统时间
  • go_*:node_exportergo 相关指标
  • process_*:node_exporter 自身进程相关运行指标

mysqld_exporter

(1)下载二进制包

1
2
3
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.12.1/mysqld_exporter-0.12.1.linux-amd64.tar.gz
tar -xzf mysqld_exporter-0.12.1.linux-amd64.tar.gz
cd mysqld_exporter-0.12.1.linux-amd64

(2)编辑 .my.cnf

1
2
3
4
5
[client]
user=hdm
password=Hdm@123!
host=10.133.0.53
port=3306

(3)启动 mysqld_exporter,默认端口是 9104,可以看到采集到的 MySQL Metrics

1
./mysqld_exporter --config.my-cnf=/data/mysqld_exporter-0.12.1.linux-amd64/.my.cnf

数据收集

为了能够让 Prometheus Server 能够从当前 node_exporter 获取到监控数据,这里需要修改 Prometheus 配置文件,编辑 prometheus.yml 并在 scrape_configs 节点下添加以下内容:

1
2
3
4
5
6
7
8
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 采集node exporter监控数据
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

重新启动 Prometheus Server,访问 http://10.133.0.53:9090,进入到 Prometheus Server。如果输入 up 并且点击执行按钮以后,可以看到如下结果:

image-20190826215234095

如果 Prometheus 能够正常从 node_exporter 获取数据,则会看到以下结果:

1
2
up{instance="localhost:9090",job="prometheus"}	1
up{instance="localhost:9100",job="node"} 1

其中 "1" 表示正常,反之 "0" 则为异常。

数据模型

Prometheus 存储的是 时序数据,即按照相同时序(相同的名字和标签),以时间维度存储连续的数据的集合。时序(Time Series)是由名字(Metric),以及一组 key/value 标签定义的,具有相同的名字以及标签属于相同时序。时序的名字由 ASCII 字符、数字、下划线、以及冒号组成,它必须满足正则表达式 [a-zA-Z_:][a-zA-Z0-9_:]*, 其名字应该具有语义化,一般表示一个可以度量的指标,例如: http_requests_total, 可以表示 http 请求的总数。

时序的标签可以使 Prometheus 的数据更加丰富,能够区分具体不同的实例,例如 http_requests_total{method="POST"} 可以表示所有 Http 中的 POST 请求。标签名称由 ASCII 字符,数字,以及下划线组成, 其中 __ 开头属于 Prometheus 保留,标签的值可以是任何 Unicode 字符,支持中文。

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

数据可视化

Prometheus UI 提供了快速验证 PromQL 以及临时可视化支持的能力,而在大多数场景下引入监控系统通常还需要构建可以长期使用的监控数据可视化面板( Dashboard )。这时用户可以考虑使用第三方的可视化工具如GrafanaGrafana 是一个开源的可视化平台,并且提供了对 Prometheus 的完整支持。

安装 Grafana(使用向导:安装 -> 添加数据源 -> 创建 Dashboard -> 邀请成员 -> 安装应用和插件)

1
2
3
4
5
6
7
8
9
10
11
12
13
docker方式:
docker run -d -p 3000:3000 grafana/grafana

二进制包方式:
wget https://dl.grafana.com/oss/release/grafana-6.3.3.linux-amd64.tar.gz
tar -zxvf grafana-6.3.3.linux-amd64.tar.gz

rpm方式:
wget https://dl.grafana.com/oss/release/grafana-6.3.3-1.x86_64.rpm
sudo yum localinstall grafana-6.3.3-1.x86_64.rpm

Pie Chart插件:
grafana-cli plugins install grafana-piechart-panel

访问 http://10.133.0.53:3000 就可以进入到 Grafana 的界面中,默认情况下使用账户 admin/admin 进行登录

任务和实例

Prometheus 中,每一个暴露监控样本数据的 HTTP 服务称为一个实例。例如在当前主机上运行的 node_exporter 可以被称为一个实例Instance)。

1
2
3
4
5
6
7
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']

而一组用于相同采集目的的实例,或者同一个采集进程的多个副本则通过一个任务Job)进行管理。

1
2
3
* job: node
* instance 2: 1.2.3.4:9100
* instance 4: 5.6.7.8:9100

当前在每一个 Job 中主要使用了静态配置(static_configs)的方式定义监控目标,Prometheus 还支持与 ConsulKubernetes 等进行集成实现自动发现实例,并从这些实例上获取监控数据。可以访问 targets 直接查看当前所有的任务以及每个任务对应的实例信息。

服务发现

Push vs Pull

Push

如上所示,展示了 Push 系统和 Pull 系统的核心差异。相较于 Push 模式,Pull 模式的优点可以简单总结为以下几点:

  • 只要 exporter 在运行,你可以在任何地方(比如在本地),搭建你的监控系统;
  • 你可以更容易的查看监控目标实例的健康状态,并且可以快速定位故障;
  • 更利于构建 DevOps 文化的团队;
  • 松耦合的架构模式更适合于云原生的部署环境。

Consul

Consul:由 HashiCorp 开发的一个支持多数据中心的分布式服务发现和键值对存储服务的开源软件,被大量应用于基于微服务的软件架构当中,使用 Golang 语言开发。

安装

下载二进制包

与 Prometheus 集成

PromQL

PromQL(Prometheus Query Language),是 Prometheus 自己开发的数据查询 DSL 语言,PromQL 作为Prometheus 的核心能力除了实现数据的对外查询和展现,同时告警监控也是依赖 PromQL 实现的。

时间序列

Prometheus 可以采集到当前主机所有监控指标的样本数据,例如:

1
2
3
4
5
6
# HELP node_cpu Seconds the cpus spent in each mode.
# TYPE node_cpu counter
node_cpu{cpu="cpu0",mode="idle"} 362812.7890625
# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 3.0703125

其中非 # 开头的每一行表示当前 node_exporter 采集到的一个监控样本:node_cpu 和 node_load1 表明了当前指标的名称、大括号中的标签则反映了当前样本的一些特征和维度、浮点数则是该监控样本的具体值。

样本

Prometheus 会将所有采集到的样本数据以时间序列(time-series)的方式保存在内存数据库中,并且定时保存到硬盘上。如下所示,可以将 time-series 理解为一个以时间为 Y 轴的数字矩阵:

1
2
3
4
5
6
7
^
. . . . . . . . . . . . . . . . . . . node_cpu{cpu="cpu0",mode="idle"}
. . . . . . . . . . . . . . . . . . . node_cpu{cpu="cpu0",mode="system"}
. . . . . . . . . . . . . . . . . . node_load1{}
. . . . . . . . . . . . . . . . . .
v
<------------------ 时间 ---------------->

在 time-series 中的每一个点称为一个样本(sample),样本由以下三部分组成:

  • 指标 (metric):metric name 和描述当前样本特征的 label sets。
  • 时间戳 (timestamp):一个精确到毫秒的时间戳。
  • 样本值 (value): 一个 folat64 的浮点型数据表示当前样本的值。
1
2
3
4
5
6
7
8
9
<--------------- metric ---------------------><-timestamp -><-value->
http_request_total{status="200", method="GET"}@1434417560938 => 94355
http_request_total{status="200", method="GET"}@1434417561287 => 94334

http_request_total{status="404", method="GET"}@1434417560938 => 38473
http_request_total{status="404", method="GET"}@1434417561287 => 38544

http_request_total{status="200", method="POST"}@1434417560938 => 4748
http_request_total{status="200", method="POST"}@1434417561287 => 4785

指标 (Metric)

在形式上,所有的指标 (Metric) 都通过如下格式标示:

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

指标名称(metric name):反映监控样本的含义。

标签(label):反映当前样本的特征维度。

指标类型:Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)

Counter:只增不减的计数器

Gauge:可增可减的仪表盘

使用 Histogram 和 Summary 分析数据分布情况

告警