关于prometheus:第04期Prometheus-数据采集三

2次阅读

共计 6682 个字符,预计需要花费 17 分钟才能阅读完成。

本期作者:罗韦

爱可生上海研发核心成员,研发工程师,次要负责 DMP 平台监控告警性能的相干工作。


Prometheus 的监控对象各式各样,没有统一标准。为了解决这个问题,Prometheus 制订了一套监控标准,合乎这个标准的样本数据能够被 Prometheus 采集并解析样本数据。Exporter 在 Prometheus 监控零碎中是一个采集监控数据并通过 Prometheus 监控标准对外提供数据的组件,针对不同的监控对象能够实现不同的 Exporter,这样就解决了监控对象规范不一的问题。从狭义上说,所有能够向 Prometheus 提供监控样本数据的程序都能够称为 Exporter,Exporter 的实例也就是咱们上期所说的 ”target”。

Exporter 的运行形式

Exporter 有两种运行形式

  • 集成到利用中

    应用 Prometheus 提供的 Client Library,能够很不便地在应用程序中实现监控代码,这种形式能够将程序外部的运行状态裸露给 Prometheus,实用于须要较多自定义监控指标的我的项目。目前一些开源我的项目就减少了对 Prometheus 监控的原生反对,如 Kubernetes,ETCD 等。

  • 独立运行

    在很多状况下,对象没法间接提供监控接口,可能起因有:

    1. 我的项目公布工夫较早,并不反对 Prometheus 监控接口,如 MySQL、Redis;

    2. 监控对象不能间接提供 HTTP 接口,如监控 Linux 零碎状态指标。

    对于上述情况,用户能够抉择应用独立运行的 Exporter。除了用户自行实现外,Prometheus 社区也提供了许多独立运行的 Exporter,常见的有 Node Exporter、MySQL Server Exporter。更多详情能够到官网理解:https://prometheus.io/docs/in…

Exporter 接口数据标准

Exporter 通过 HTTP 接口以文本模式向 Prometheus 裸露样本数据,格局简略,没有嵌套,可读性强。每个监控指标对应的数据文本格式如下:

# HELP < 监控指标名称 > < 监控指标形容 >
# TYPE < 监控指标名称 > < 监控指标类型 >
< 监控指标名称 >{< 标签名称 >=< 标签值 >,< 标签名称 >=< 标签值 >...} < 样本值 1 > < 工夫戳 >
< 监控指标名称 >{< 标签名称 >=< 标签值 >,< 标签名称 >=< 标签值 >...} < 样本值 2 > < 工夫戳 >
...
  • 以 # 结尾的行,如果前面跟着 ”HELP”,Prometheus 将这行解析为监控指标的形容,通常用于形容监控数据的起源;
  • 以 # 结尾的行,如果前面跟着 ”TYPE”,Prometheus 将这行解析为监控指标的类型,反对的类型有:Counter、Gauge、Histogram、Summary、Untyped。在往期文章中介绍过 Prometheus 在存储数据时是不辨别数据类型的,所以当你在犹豫一个数据类型应该用 Counter 或 Gauge 时,能够试试 Untype;
  • 以 # 结尾的行,如果前面没有跟着 ”HELP” 或 ”TYPE”,则 Prometheus 将这行视为正文,解析时疏忽;
  • 如果一个监控指标有多条样本数据,那么每条样本数据的标签值组合应该是惟一的;
  • 每行数据对应一条样本数据;
  • 工夫戳应为采集数据的工夫,是可选项,如果 Exporter 没有提供工夫戳的话,Prometheus Server 会在拉取到样本数据时将工夫戳设置为以后工夫;
  • Summary 和 Histogram 类型的监控指标要求提供两行数据别离示意该监控指标所有样本的和、样本数量,命名格局为:< 监控指标名称 >_sum、< 监控指标名称 >_count;
  • Summary 类型的样本数据格式:1. 依据 Exporter 提供的分位点,样本会被计算后拆分成多行数据,每行应用标签 ”quantile” 辨别,”quantile” 的值包含 Exporter 提供的所有分位点。2. 数据的排列程序必须是依照标签 ”quantile” 值递增;3. 举个栗子:一个名为 x 的监控指标,提供的分位点为:0.5, 0.9, 0.99,那么它裸露给 Prometheus 的接口数据格式如下:
# HELP x balabala
# TYPE x summary
x{quantile="0.5"} value1
x{quantile="0.9"} value2
x{quantile="0.99"} value3
x_sum sum(values)
x_count count(values)
  • Histogram 类型的样本数据格式:

1. 依据 Exporter 提供的 Bucket 值,样本会被计算后拆分成多行数据,每行应用标签 ”le” 辨别,”le” 为 Exporter 提供的 Buckets;
2. 数据的排列程序必须是依照标签 ”le” 值递增;
3. 必须要有一行数据的标签 le=”+Inf”,值为该监控指标的样本总数;
4. 举个栗子:一个名为 x 的监控指标,提供的 Buckets 为:20, 50, 70,那么它裸露给 Prometheus 的接口数据格式如下:

# HELP x The temperature of cpu
# TYPE x histogram
x_bucket{le="20"} value1
x_bucket{le="50"} value2
x_bucket{le="70"} value3
x_bucket{le="+Inf"} count(values)
x_sum sum(values)
x_count count(values)

这样的文本格式也有不足之处:
1. 文本内容可能过于简短;
2. Prometheus 在解析时不能校验 HELP 和 TYPE 字段是否缺失,如果缺失 HELP 字段,这条样本数据的起源可能就难以判断;如果缺失 TYPE 字段,Prometheus 对这条样本数据的类型就无从得悉;
3. 相比于 protobuf,Prometheus 应用的文本格式没有做任何压缩解决,解析老本较高。

MySQL Server Exporter

针对被宽泛应用的关系型数据库 MySQL,Prometheus 官网提供了 MySQL Server Exporter,反对 MySQL 5.6 及以上版本,对于 5.6 以下的版本,局部监控指标可能不反对。
MySQL Server Exporter 监控的信息包含了罕用的 global status/variables 信息、schema/table 的统计信息、user 统计信息、innodb 的信息以及主从复制、组复制的信息,监控指标比拟全面。然而因为它提供的监控指标中短少对 MySQL 实例的标识,所以当一台主机上存在多个 MySQL 实例,须要运行多个 MySQL Server Exporter 进行监控时,就会难以辨别实例信息。具体应用形式可参考:https://github.com/prometheus…

Node Exporter

Prometheus 官网的 Node Exporter 提供对 *NIX 零碎、硬件信息的监控,监控指标包含 CPU 使用率 / 配置、零碎均匀负载、内存信息、网络情况、文件系统信息统计、磁盘应用状况统计等。对于不同的零碎,监控指标会有所差别,如 diskstats 反对 Darwin, Linux, OpenBSD 零碎;loadavg 反对 Darwin, Dragonfly, FreeBSD, Linux, NetBSD, OpenBSD, Solaris 零碎。Node Exporter 的监控指标没有对主机身份的标识,能够通过 relabel 性能在 Prometheus Server 端减少一些标识标签。具体应用形式可参考:https://github.com/prometheus…

如何实现一个 Exporter

编写一个简略的 Exporter

应用 prometheus/client_golang 包,咱们来编写一个简略的 Exporter,包含 Prometheus 反对的四种监控指标类型

package main

import (
"log"
"net/http"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
// 应用 GaugeVec 类型能够为监控指标设置标签,这里为监控指标减少一个标签 "device"
speed = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "disk_available_bytes",
Help: "Disk space available in bytes",
}, []string{"device"})

tasksTotal = prometheus.NewCounter(prometheus.CounterOpts{
Name: "test_tasks_total",
Help: "Total number of test tasks",
})

taskDuration = prometheus.NewSummary(prometheus.SummaryOpts{
Name: "task_duration_seconds",
Help: "Duration of task in seconds",
//Summary 类型的监控指标须要提供分位点
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
})

cpuTemperature = prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "cpu_temperature",
Help: "The temperature of cpu",
//Histogram 类型的监控指标须要提供 Bucket
Buckets: []float64{20, 50, 70, 80},
})
)

func init() {
// 注册监控指标
prometheus.MustRegister(speed)
prometheus.MustRegister(tasksTotal)
prometheus.MustRegister(taskDuration)
prometheus.MustRegister(cpuTemperature)
}

func main() {
// 模仿采集监控数据
fakeData()

// 应用 prometheus 提供的 promhttp.Handler() 裸露监控样本数据
//prometheus 默认从 "/metrics" 接口拉取监控样本数据
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":10000", nil))
}

func fakeData() {tasksTotal.Inc()
// 设置该条样本数据的 "device" 标签值为 "/dev/sda"
speed.With(prometheus.Labels{"device": "/dev/sda"}).Set(82115880)

taskDuration.Observe(10)
taskDuration.Observe(20)
taskDuration.Observe(30)
taskDuration.Observe(45)
taskDuration.Observe(56)
taskDuration.Observe(80)

cpuTemperature.Observe(30)
cpuTemperature.Observe(43)
cpuTemperature.Observe(56)
cpuTemperature.Observe(58)
cpuTemperature.Observe(65)
cpuTemperature.Observe(70)
}

接下来编译、运行咱们的 Exporter

GOOS=linux GOARCH=amd64 go build -o my_exporter main.go
./my_exporter &

Exporter 运行起来之后,还要在 Prometheus 的配置文件中退出 Exporter 信息,Prometheus 能力从 Exporter 拉取数据。

static_configs:
- targets: ['localhost:9090','172.17.0.3:10000']

在 Prometheus 的 targets 页面能够看到方才新增的 Exporter 了

拜访 ”/metrics” 接口能够找到如下数据:

Gauge
因为咱们应用了 GaugeVec,所以产生了带标签的样本数据

# HELP disk_available_bytes disk space available in bytes
# TYPE disk_available_bytes gauge
disk_available_bytes{device="/dev/sda"} 8.211588e+07

Counter

# HELP test_tasks_total total number of test tasks
# TYPE test_tasks_total counter
test_tasks_total 1

Summary

# HELP task_duration_seconds Duration of task in seconds
# TYPE task_duration_seconds summary
task_duration_seconds{quantile="0.5"} 30
task_duration_seconds{quantile="0.9"} 80
task_duration_seconds{quantile="0.99"} 80
task_duration_seconds_sum 241
task_duration_seconds_count 6

Histogram

# HELP cpu_temperature The temperature of cpu
# TYPE cpu_temperature histogram
cpu_temperature_bucket{le="20"} 0
cpu_temperature_bucket{le="50"} 2
cpu_temperature_bucket{le="70"} 6
cpu_temperature_bucket{le="80"} 6
cpu_temperature_bucket{le="+Inf"} 6
cpu_temperature_sum 322
cpu_temperature_count 6

Exporter 实现形式的考量

下面的栗子中,咱们在程序一开始就初始化所有的监控指标,这种计划通常接下来会开启一个采样协程去定期采集、更新监控指标的样本数据,最新的样本数据将始终保留在内存中,在接到 Prometheus Server 的申请时,返回内存里的样本数据。这个计划的长处在于,易于控制采样频率;不必放心并发采样可能带来的资源抢占问题。不足之处有:

1. 因为样本数据不会被主动清理,当某个已被采样的采集对象生效了,Prometheus Server 仍然能拉取到它的样本数据,只是这个数据从监控对象生效时就曾经不会再被更新。这就须要 Exporter 本人提供一个对有效监控对象的数据清理机制;
2. 因为响应 Prometheus Server 的申请是从内存里取数据,如果 Exporter 的采样协程异样卡住,Prometheus Server 也无奈感知,拉取到的数据可能是过期数据;
3. Prometheus Server 拉取的数据不是即时采样的,对于某工夫点的数据一致性不能保障。
另一种计划是 MySQL Server Exporter 和 Node Exporter 采纳的,也是 Prometheus 官网举荐的计划。该计划是在每次接到 Prometheus Server 的申请时,初始化新的监控指标,开启一个采样协程。和计划一不同的是,这些监控指标只在申请期间存活。而后采样协程会去采集所有样本数据并返回给 Prometheus Server。相比于计划一,计划二的数据是即时拉取的,能够保障工夫点的数据一致性;因为监控指标会在每次申请时从新初始化,所以也不会存在生效的样本数据。不过计划二同样有不足之处:

1. 当多个拉取申请同时产生时,须要管制并发采集样本的资源耗费;

2. 当多个拉取申请同时产生时,在短时间内须要对同一个监控指标读取屡次,对于一个变动频率较低的监控指标来说,屡次读取意义不大,却减少了对资源的占用。


相干内容方面的常识,大家还有什么疑难或者想晓得的吗?连忙留言通知小编吧!

正文完
 0