初识Prometheus

一:什么是Prometheus?

Prometheus 是由前 Google 工程师从 2012 年开始在 Soundcloud 以开源软件的形式进行研发的系统监控和告警工具包,自此以后,许多公司和组织都采用了 Prometheus 作为监控告警工具。Prometheus 的开发者和用户社区非常活跃,它现在是一个独立的开源项目,可以独立于任何公司进行维护。为了证明这一点,Prometheus 于 2016 年 5 月加入 CNCF 基金会,成为继 Kubernetes 之后的第二个 CNCF 托管项目。

Github项目地址:https://github.com/prometheus

官方网站:https://prometheus.io/

二:Prometheus的特点和组件

Prometheus 的主要优势有:

由指标名称和和键/值对标签标识的时间序列数据组成的多维数据模型。

强大的查询语言 PromQL。

不依赖分布式存储;单个服务节点具有自治能力。

时间序列数据是服务端通过 HTTP 协议主动拉取获得的。

也可以通过中间网关来推送时间序列数据。

可以通过静态配置文件或服务发现来获取监控目标。

支持多种类型的图表和仪表盘。

Prometheus 生态系统由多个组件组成,其中有许多组件是可选的:

Prometheus Server 作为服务端,用来存储时间序列数据。

客户端库用来检测应用程序代码。

用于支持临时任务的推送网关。

Exporter 用来监控 HAProxy,StatsD,Graphite 等特殊的监控目标,并向 Prometheus 提供标准格式的监控样本数据。

alartmanager 用来处理告警。

其他各种周边工具。

注:其中大多数组件都是用 Go 编写的,因此很容易构建和部署为静态二进制文件。

三:Prometheus的系统架构

img

Prometheus Server 直接从监控目标中或者间接通过推送网关来拉取监控指标,它在本地存储所有抓取到的样本数据,并对此数据执行一系列规则,以汇总和记录现有数据的新时间序列或生成告警。可以通过 Grafana 或者其他工具来实现监控数据的可视化。

四:应用场景

Prometheus 适用于记录文本格式的时间序列,它既适用于以机器为中心的监控,也适用于高度动态的面向服务架构的监控。在微服务的世界中,它对多维数据收集和查询的支持有特殊优势。Prometheus 是专为提高系统可靠性而设计的,它可以在断电期间快速诊断问题,每个 Prometheus Server 都是相互独立的,不依赖于网络存储或其他远程服务。当基础架构出现故障时,你可以通过 Prometheus 快速定位故障点,而且不会消耗大量的基础架构资源。

注:Prometheus 非常重视可靠性,即使在出现故障的情况下,你也可以随时查看有关系统的可用统计信息。如果你需要百分之百的准确度,例如按请求数量计费,那么 Prometheus 不太适合你,因为它收集的数据可能不够详细完整。这种情况下,你最好使用其他系统来收集和分析数据以进行计费,并使用 Prometheus 来监控系统的其余部分。

五:Prometheus和其他的监控系统对比

1、Prometheus vs. Zabbix

Zabbix 使用的是 C 和 PHP, Prometheus 使用 Golang, 整体而言 Prometheus 运行速度更快一点。

Zabbix 属于传统主机监控,主要用于物理主机、交换机、网络等监控,Prometheus 不仅适用主机监控,还适用于 Cloud、SaaS、Openstack、Container 监控。

Zabbix 在传统主机监控方面,有更丰富的插件。

Zabbix 可以在 WebGui 中配置很多事情,Prometheus 需要手动修改文件配置。

2、Prometheus vs. Nagios

Nagios 数据不支持自定义 Labels, 不支持查询,告警也不支持去噪、分组, 没有数据存储,如果想查询历史状态,需要安装插件。

Nagios 是上世纪 90 年代的监控系统,比较适合小集群或静态系统的监控Nagios 太古老,很多特性都没有,Prometheus 要优秀很多。

3、Prometheus vs Sensu

Sensu 广义上讲是 Nagios 的升级版本,它解决了很多 Nagios 的问题,如果你对 Nagios 很熟悉,使用 Sensu 是个不错的选择。

Sensu 依赖 RabbitMQ 和 Redis,数据存储上扩展性更好。

4、Prometheus vs InfluxDB

InfluxDB 是一个开源的时序数据库,主要用于存储数据,如果想搭建监控告警系统,需要依赖其他系统。

InfluxDB 在存储水平扩展以及高可用方面做的更好, 毕竟核心是数据库。

六:Prometheus 核心概念

1、数据模型

Prometheus 从根本上存储的所有数据都是时间序列数据(Time Serie Data,简称时序数据)。时序数据是具有时间戳的数据流,该数据流属于某个度量指标(Metric)和该度量指标下的多个标签(Label)。除了提供存储功能,Prometheus 还可以利用查询表达式来执行非常灵活和复杂的查询。

度量指标和标签

每个时间序列(Time Serie,简称时序)由度量指标和一组标签键值对唯一确定。

度量指标名称描述了被监控系统的某个测量特征(比如 http_requests_total 表示 http 请求总数)。

度量指标名称由 ASCII 字母、数字、下划线和冒号组成,须匹配正则表达式 [a-zA-Z_:][a-zA-Z0-9_:]*。

标签开启了 Prometheus 的多维数据模型。对于同一个度量指标,不同标签值组合会形成特定维度的时序。Prometheus 的查询语言可以通过度量指标和标签对时序数据进行过滤和聚合。改变任何度量指标上的任何标签值,都会形成新的时序。标签名称可以包含 ASCII 字母、数字和下划线,须匹配正则表达式 [a-zA-Z_][a-zA-Z0-9_]*,带有 _ 下划线的标签名称保留为内部使用。标签值可以包含任意 Unicode 字符,包括中文。

采样值(Sample)

时序数据其实就是一系列采样值。每个采样值包括:

一个 64 位的浮点数值

一个精确到毫秒的时间戳

注解(Notation)

一个注解由一个度量指标和一组标签键值对构成。形式如下:

[metric name]{[label name]=[label value], …}

例如,度量指标为 api_http_requests_total,标签为 method=”POST”、handler=”/messages” 的注解表示如下:

api_http_requests_total{method=”POST”, handler=”/messages”}

2、度量指标类型

Prometheus 里的度量指标有以下几种类型。

计数器(Counter)

计数器是一种累计型的度量指标,它是一个只能递增的数值。计数器主要用于统计类似于服务请求数、任务完成数和错误出现次数这样的数据。

计量器(Gauge)

计量器表示一个既可以增加, 又可以减少的度量指标值。计量器主要用于测量类似于温度、内存使用量这样的瞬时数据。

直方图(Histogram)

直方图对观察结果(通常是请求持续时间或者响应大小这样的数据)进行采样,并在可配置的桶中对其进行统计。有以下几种方式来产生直方图(假设度量指标为 \):

按桶计数,相当于 _bucket{le=””}

采样值总和,相当于 _sum

采样值总数,相当于 _count ,也等同于把所有采样值放到一个桶里来计数 _bucket{le=”+Inf”}

汇总(Summary)

类似于直方图,汇总也对观察结果进行采样。除了可以统计采样值总和和总数,它还能够按分位数统计。有以下几种方式来产生汇总(假设度量指标为 \):

按分位数,也就是采样值小于该分位数的个数占总数的比例小于 φ,相当于 {quantile=”<φ>”}

采样值总和,相当于 _sum 采样值总数,相当于 _count

任务(Job)和实例(Instance)

在 Prometheus 里,可以从中抓取采样值的端点称为实例,为了性能扩展而复制出来的多个这样的实例形成了一个任务。

例如下面的 api-server 任务有四个相同的实例:

job: api-server
instance 1: 1.2.3.4:5670
instance 2: 1.2.3.4:5671
instance 3: 5.6.7.8:5670
instance 4: 5.6.7.8:5671

Prometheus 抓取完采样值后,会自动给采样值添加下面的标签和值:

job: 抓取所属任务。

instance: 抓取来源实例。

另外每次抓取时,Prometheus 还会自动在以下时序里插入采样值:

up{job=”[job-name]”, instance=”instance-id”}:# 采样值为 1 表示实例健康,否则为不健康
scrape_duration_seconds{job=”[job-name]”, instance=”[instance-id]”}:# 采样值为本次抓取消耗时间
scrape_samples_post_metric_relabeling{job=”<job-name>”, instance=”<instance-id>”}:# 采样值为重新打标签后的采样值个数
scrape_samples_scraped{job=”<job-name>”, instance=”<instance-id>”}:# 采样值为本次抓取到的采样值个数

推荐文章