在第1章中为了采集主机的监控样本数据,我们在主机上安装了一个Node Exporter程序,该程序对外暴露了一个用于获取当前监控样本数据的HTTP访问地址。这样的一个程序称为Exporter,Exporter的实例称为一个Target。Prometheus通过轮询的方式定时从这些Target中获取监控数据样本,并且存储在数据库当中。前面的示例都是基于Node Exporter去讲解的,以及一些http数据的云讲解。这一章就详细讲述Exporter。
4.1 Exporter是什么
广义上讲所有可以向Prometheus提供监控样本数据的程序都可以被称为一个Exporter。而Exporter的一个实例称为target,如下所示,Prometheus通过轮询的方式定期从这些target中获取样本数据:
4.1.1 Exporter的来源
从Exporter的来源上来讲,主要分为两类:
- 社区提供的
Prometheus社区提供了丰富的Exporter实现,涵盖了从基础设施,中间件以及网络等各个方面的监控功能。这些Exporter可以实现大部分通用的监控需求。下表列举一些社区中常用的Exporter:
范围 | 常用Exporter |
---|---|
数据库 | MySQL Exporter, Redis Exporter, MongoDB Exporter, MSSQL Exporter等 |
硬件 | Apcupsd Exporter,IoT Edison Exporter, IPMI Exporter, Node Exporter等 |
消息队列 | Beanstalkd Exporter, Kafka Exporter, NSQ Exporter, RabbitMQ Exporter等 |
存储 | Ceph Exporter, Gluster Exporter, HDFS Exporter, ScaleIO Exporter等 |
HTTP服务 | Apache Exporter, HAProxy Exporter, Nginx Exporter等 |
API服务 | AWS ECS Exporter, Docker Cloud Exporter, Docker Hub Exporter, GitHub Exporter等 |
日志 | Fluentd Exporter, Grok Exporter等 |
监控系统 | Collectd Exporter, Graphite Exporter, InfluxDB Exporter, Nagios Exporter, SNMP Exporter等 |
其它 | Blockbox Exporter, JIRA Exporter, Jenkins Exporter, Confluence Exporter等 |
- 用户自定义的
除了直接使用社区提供的Exporter程序以外,用户还可以基于Prometheus提供的Client Library创建自己的Exporter程序,目前Promthues社区官方提供了对以下编程语言的支持:Go、Java/Scala、Python、Ruby。同时还有第三方实现的如:Bash、C++、Common Lisp、Erlang,、Haskeel、Lua、Node.js、PHP、Rust等。
4.1.2 Exporter的运行方式
从Exporter的运行方式上来讲,又可以分为:
- 独立使用的
以我们已经使用过的Node Exporter为例,由于操作系统本身并不直接支持Prometheus,同时用户也无法通过直接从操作系统层面上提供对Prometheus的支持。因此,用户只能通过独立运行一个程序的方式,通过操作系统提供的相关接口,将系统的运行状态数据转换为可供Prometheus读取的监控数据。 除了Node Exporter以外,比如MySQL Exporter、Redis Exporter等都是通过这种方式实现的。 这些Exporter程序扮演了一个中间代理人的角色。
- 集成到应用中的
为了能够更好的监控系统的内部运行状态,有些开源项目如Kubernetes,ETCD等直接在代码中使用了Prometheus的Client Library,提供了对Prometheus的直接支持。这种方式打破的监控的界限,让应用程序可以直接将内部的运行状态暴露给Prometheus,适合于一些需要更多自定义监控指标需求的项目。
4.1.3 Exporter规范
所有的Exporter程序都需要按照Prometheus的规范,返回监控的样本数据。以Node Exporter为例,当访问/metrics地址时会返回以下内容:
# HELP node_cpu_guest_seconds_total Seconds the cpus spent in guests (VMs) for each mode.
# TYPE node_cpu_guest_seconds_total counter
node_cpu_guest_seconds_total{cpu="0",mode="nice"} 0
这是一种基于文本的格式规范,在Prometheus 2.0之前的版本还支持Protocol buffer规范。相比于Protocol buffer文本具有更好的可读性,以及跨平台性。Prometheus 2.0的版本也已经不再支持Protocol buffer,这里就不对Protocol buffer规范做详细的阐述。
Exporter返回的样本数据,主要由三个部分组成:样本的一般注释信息(HELP),样本的类型注释信息(TYPE)和样本。Prometheus会对Exporter响应的内容逐行解析:
如果当前行以# HELP开始,Prometheus将会按照以下规则对内容进行解析,得到当前的指标名称以及相应的说明信息:
# HELP <metrics_name> <doc_string>
如果当前行以# TYPE开始,Prometheus会按照以下规则对内容进行解析,得到当前的指标名称以及指标类型:
# TYPE <metrics_name> <metrics_type>
TYPE注释行必须出现在指标的第一个样本之前。如果没有明确的指标类型需要返回为untyped。 除了# 开头的所有行都会被视为是监控样本数据。 每一行样本需要满足以下格式规范:
metric_name [
"{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}"
] value [ timestamp ]
其中metric_name和label_name必须遵循PromQL的格式规范要求。value是一个float格式的数据,timestamp的类型为int64(从1970-01-01 00:00:00以来的毫秒数),timestamp为可选默认为当前时间。具有相同metric_name的样本必须按照一个组的形式排列,并且每一行必须是唯一的指标名称和标签键值对组合。
需要特别注意的是对于histogram和summary类型的样本。需要按照以下约定返回样本数据:
类型为summary或者histogram的指标x,该指标所有样本的值的总和需要使用一个单独的x_sum指标表示。
类型为summary或者histogram的指标x,该指标所有样本的总数需要使用一个单独的x_count指标表示。
对于类型为summary的指标x,其不同分位数quantile所代表的样本,需要使用单独的x{quantile="y"}表示。
对于类型histogram的指标x为了表示其样本的分布情况,每一个分布需要使用x_bucket{le="y"}表示,其中y为当前分布的上位数。同时必须包含一个样本x_bucket{le="+Inf"},并且其样本值必须和x_count相同。
对于histogram和summary的样本,必须按照分位数quantile和分布le的值的递增顺序排序。
以下是类型为histogram和summary的样本输出示例:
# A histogram, which has a pretty complex representation in the text format:
# HELP http_request_duration_seconds A histogram of the request duration.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.2"} 100392
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320
# Finally a summary, which has a complex representation, too:
# HELP rpc_duration_seconds A summary of the RPC duration in seconds.
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.01"} 3102
rpc_duration_seconds{quantile="0.05"} 3272
rpc_duration_seconds{quantile="0.5"} 4773
rpc_duration_seconds_sum 1.7560473e+07
rpc_duration_seconds_count 2693
对于某些Prometheus还没有提供支持的编程语言,用户只需要按照以上规范返回响应的文本数据即可。
4.1.4 指定样本格式的版本
在Exporter响应的HTTP头信息中,可以通过Content-Type指定特定的规范版本,例如:
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 2906
Content-Type: text/plain; version=0.0.4
Date: Sat, 17 Mar 2018 08:47:06 GMT
其中version用于指定Text-based的格式版本,当没有指定版本的时候,默认使用最新格式规范的版本。同时HTTP响应头还需要指定压缩格式为gzip。
4.2 常用Exporter
4.2.1 容器监控:CAdvisor
使用CAdvisor
CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示。
启动CAdvisor非常简单,直接在要监控的Docker服务器上运行该容器即可:
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
我的Docker主机的IP为:192.168.113.70,打开8080端口即可看到当前主机的运行状态。
Advisor是一个简单易用的工具,相比于使用Docker命令行工具,用户不用再登录到服务器中即可以可视化图表的形式查看主机上所有容器的运行状态。
而在多主机的情况下,在所有节点上运行一个CAdvisor再通过各自的UI查看监控信息显然不太方便,同时CAdvisor默认只保存2分钟的监控数据。好消息是CAdvisor已经内置了对Prometheus的支持。访问http://192.168.113.70:8080/metrics即可获取到标准的Prometheus监控样本输出:
# HELP container_fs_limit_bytes Number of bytes that can be consumed by the container on this filesystem.
# TYPE container_fs_limit_bytes gauge
container_fs_limit_bytes{container_label_maintainer="",device="/dev/mapper/centos-root",id="/",image="",name=""} 2.146435072e+10
container_fs_limit_bytes{container_label_maintainer="",device="/dev/mapper/centos-root",id="/docker/0fb99e75206028cfb783e29af806393ee38df289fbbe0c324038832500db94e4",image="redis",name="redis-server"} 2.146435072e+10
container_fs_limit_bytes{container_label_maintainer="",device="/dev/mapper/centos-root",id="/docker/a91d3c038964bc6fd3da6c0023fd49c56d3dbf9e814f670d38331071e5e7cb20",image="google/cadvisor:latest",name="cadvisor"} 2.146435072e+10
下面表格中列举了一些CAdvisor中获取到的典型监控指标:
指标名称 | 类型 | 含义 |
---|---|---|
container_cpu_load_average_10s | gauge | 过去10秒容器CPU的平均负载 |
container_cpu_usage_seconds_total | counter | 容器在每个CPU内核上的累积占用时间 (单位:秒) |
container_cpu_system_seconds_total | counter | System CPU累积占用时间(单位:秒) |
container_cpu_user_seconds_total | counter | User CPU累积占用时间(单位:秒) |
container_fs_usage_bytes | gauge | 容器中文件系统的使用量(单位:字节) |
container_fs_limit_bytes | gauge | 容器可以使用的文件系统总量(单位:字节) |
container_fs_reads_bytes_total | counter | 容器累积读取数据的总量(单位:字节) |
container_fs_writes_bytes_total | counter | 容器累积写入数据的总量(单位:字节) |
container_memory_max_usage_bytes | gauge | 容器的最大内存使用量(单位:字节) |
container_memory_usage_bytes | gauge | 容器当前的内存使用量(单位:字节 |
container_spec_memory_limit_bytes | gauge | 容器的内存使用量限制 |
machine_memory_bytes | gauge | 当前主机的内存总量 |
container_network_receive_bytes_total | counter | 容器网络累积接收数据总量(单位:字节) |
container_network_transmit_bytes_total | counter | 容器网络累积传输数据总量(单位:字节) |
与Prometheus集成
修改prometheus.yml 文件,将cAdvisor添加监控数据采集任务目标当中:
- job_name: cadvisor
static_configs:
- targets:
- localhost:8080
重启Prometheus服务,在Prometheus UI中查看到当前所有的Target状态:
当能够正常采集到cAdvisor的样本数据后,可以通过以下表达式计算容器的CPU使用率:
sum(irate(container_cpu_usage_seconds_total{image!=""}[1m])) without (cpu)
查询容器内存使用量(单位:字节):
container_memory_usage_bytes{image!=""}
查询容器网络接收量速率(单位:字节/秒):
sum(rate(container_network_receive_bytes_total{image!=""}[1m])) without (interface)
查询容器网络传输量速率(单位:字节/秒):
sum(rate(container_network_transmit_bytes_total{image!=""}[1m])) without (interface)
当然,在Prometheus查询也不是办法,我们看下在Grafana下是怎样的一个表现吧。
这样是不是直观又帅气呢。
4.2.2 监控MySQL运行状态:MySQLD Exporter
mysqld_exporter是官方出品的mysql性能及资源利用率监控的exporter。可以在Prometheus的官网下载,最新版本0.12.1。这里就演示怎么下载安装,二进制包很简单的。
在我的测试环境下,刚好有个MariaDB,版本是10.4.6。考虑到MariaDB和MySQL师出同源,这里就用MariaDB来做演示了。
创建数据库用户
获取mysql的性能状态,首先要能登录mysql才行的,所以这里我们先创建一个用来获取mysql性能信息的本地账户。
CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'yourpasswd';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
启动mysqld exporter
按照之前我们新建目录的规范,新建一个目录用来存放各种exporter,然后解压下载好的mysqld exporter。
mkdir /usr/local/prometheus_exporter
tar -xf mysqld_exporter-0.11.0.linux-amd64.tar.gz
mv mysqld_exporter-0.11.0.linux-amd64 /usr/local/prometheus_exporter/
cd /usr/local/prometheus_exporter/
ln -s mysqld_exporter-0.11.0.linux-amd64 mysqld_exporter
接下来我们在该服务器上启动mysqld exporter,启动之前我们先要新建一个配置文件,里面配置了mysql的连接信息及刚刚创建的账号密码:
vim /usr/local/prometheus_exporter/mysqld_exporter/my.cnf
[client]
user=exporter
password="yourpasswd"
socket=/tmp/mysql.sock
保存退出后记得修改这个文件的权限,密码属于敏感信息:
chmod 600 /usr/local/prometheus_exporter/mysqld_exporter/my.cnf
然后启动mysqld exporter
cd /usr/local/prometheus_exporter/mysqld_exporter
nohup ./mysqld_exporter --config.my-cnf=my.cnf &
集成Prometheus
mysqld exporter默认会启动9104端口,我们在Prometheus的配置文件中添加对应的配置:
#采集mysqld运行数据
- job_name: mysqld
static_configs:
- targets:
- 192.168.1.174:9104
重启Prometheus,在target菜单下能看到新增的监控任务
Grafana展示
为了更好展现监控的结果,我们使用Grafana对数据进行展示,导入模板 7362,可以看到如下的界面:
这里可以很直观地看到很多游人的信息,比如QPS、连接数等等
4.2.3 网络探测:Blackbox Exporter
前面介绍的两种export都是属于白盒监控的,就是说你能看到监控目标里面几乎你想要的指标,让你对监控目标有个全面的了解。对比于白盒监控,黑盒监控看到的就是最表面的状态,比如说:网页打不开、服务连接不上。但是就是这种的状态,恰恰是我们非常需要的,这是非常贴合实际用户的。所以黑盒监控可以说是对白盒监控的一种补充。
在Prometheus中使用黑盒监控需要安装部署blackbox exporter,和其他的exporter,这是golang写的二进制包,可以直接使用。blackbox exporter内置了http、tcp、dns和icmp等探针类型,在启动blackbox exporter后,在Prometheus的配置文件中可以定义对目标的检测。大概流程如下:
- 启动blackbox exporter
nohup ./blackbox_exporter --config.file=blackbox.yml &
- 在Prometheus中添加探测的目标,这里用http探针去检测百度网站
- job_name: baidu_http2xx_probe
params:
module:
- http_2xx
target:
- baidu.com
metrics_path: /probe
static_configs:
- targets:
- 127.0.0.1:9115
重启Prometheus后可以在target菜单看到这个监控任务,可以点击连接看看返回的内容都有些什么。
点击链接打开 http://192.168.113.52:9115/probe?module=http_2xx&target=baidu.com
,查看返回的结果:
更加具体的介绍请自行百度,书本也没有太过详细。
4.3 使用Java自定义Exporter
直到现在为止,java仍然是企业应用中的首先开发语言。想要让自己开发的java产品能够使用Prometheus进行监控貌似也不大难,因为Prometheus有提供对应的方法给我们。因为我不是开发人员,这里就略过了这部分的内容。里面提到的方法有两个:使用Client Java构建Exporter程序、在应用中内置Prometheus支持。
可以看具体的这个连接: https://yunlzheng.gitbook.io/prometheus-book/part-ii-prometheus-jin-jie/exporter/custom_exporter_with_java