1.1 Prometheus介绍
Prometheus是基于Golang实现的一个开源系统监控和警报工具包(诞生于2012年),最初在SoundCloud(音频分享服务平台)使用,目前许多公司和组织都采用了Prometheus,该项目拥有非常活跃的开发者和用户社区,并在2016年加入云原生计算基金会(CNCF),成为继Kubernetes之后的第二个托管项目。Prometheus主要用于提供近实时的、基于动态云环境和容器的微服务、服务和应用程序的内省监控,数据存储时将其书籍的指标存储为时间序列数据,即指标信息、记录时的时间戳和标签的键值对一起存储。
1.2 特点
可提供多维度数据模型和灵活的查询方式,将监控指标关联多个标签,将监控数据任意的组合,并且提供PromQL查询方式,还提供了HTTP查询接口,可以很方便地结合Grafana等GUI组件展示数据;
在不依赖外部存储的情况下,支持服务器节点的本地存储,Prometheus自带的时序数据库可以完成每秒千万级的数据存储,而且Prometheus还可以对接第三方时序数据库如OpenTSDB;
定义了开放指标数据标准,以基于HTTP的Pull方式采集时序数据,只有实现了Prometheus监控数据格式的监控数据才可以被采集、汇总、并支持以push方式向中间网关推送数据;
支持静态文件配置和动态发现机制发现监控对象,自动完成数据采集。目前支持Kubernetes、etcd、Consul等多种服务发现机制,减少手动配置环节;
易于维护,可以通过二进制文件直接启动,也可以通过容器化部署镜像;
支持数据的分区采样和联邦部署,支持大规模集群监控。
1.3 Prometheus的适用场景
Prometheus能很好的记录任何纯数字时间序列,既适合以机器为中心的监控,也适合监控动态的面向服务的架构。在微服务项目中,对多维数据收集和查询的支持也是一种特殊的优势;
Prometheus重视可靠性,即使在发生故障的情况下也可以随时查看有关系统的可用统计信息。但是如果需要100%的准确性,例如按请求计费,最好选择其他系统进行收集和分析数据进行计费,因为Prometheus收集的数据可能不够完整。
2.1 Prometheus的组成
Promethus生态系统由多个组件组成的(部分是可选的):
Promethus服务器,用于抓取和存储时间序列数据;
客户端库:用于检测应用程序代码;
支持短期工作的推送网关;
HAProxy(提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理)、StatsD(一个简单的网络守护进程,基于 Node.js 平台,通过 UDP 或者 TCP 方式侦听各种统计信息,包括计数器和定时器,并发送聚合信息到后端服务)、Graphite(一个用于采集网站实时信息并进行统计的开源项目,可用于采集多种网站服务运行状态信息)等服务组件;
处理警报的警报管理器;
各种支持工具。
2.2 架构模型
Prometheus的基本原理是通过 HTTP周期性抓取被监控组件的状态,任意组件只要提供对应的 HTTP 接口并且符合 Prometheus 定义的数据格式就可以接入Prometheus监控。下图为Prometheus 的整体架构图(来自 Prometheus 官网):
正在上传…重新上传取消正在上传…重新上传取消正在上传…重新上传取消
Prometheus Server负责定时在目标上抓取 metrics (指标)数据,每个抓取目标都需要暴露一个HTTP服务接口用于Prometheus定时抓取。这种调用被监控对象获取监控数据的方式被称为Pull(拉)。Pull方式体现了Prometheus独特的设计与大多数采用了Push(推)方式的监控系统不同。
Pull方式的优势是能够自动进行上游监控和水平监控,配置更少,更容易扩展,更灵活,更容易实现高可用,总的来说就是Pull方式可以降低耦合。由于在推送系统中很容易出现因为向监控系统推送数据失败而导致被监控系统瘫痪的问题,而通过Pull方式,被采集端无须感知监控系统的存在,完全独立于监控系统之外,这样数据的采集完全由监控系统控制,增强了整个系统的可控性。
Prometheus 通过 Pull 方式采集数据,它支持两种方式:
通过配置文件、文本文件等进行静态配置;
支持ZooKeeper、Consul、Kubernetes等方式进行动态发现,例如对于Kubernetes的动态发现,Prometheus使用Kubernetes的API查询和监控容器信息的变化,动态更新监控对象,这样容器的创建和删除就都可以被Prometheus感知。
Storage通过一定的规则清理和整理数据,并把得到的结果存储到新的时间序列中,这里有两种存储方式:
本地存储。通过 Prometheus 自带的时序数据库将数据保存到本地磁盘,但本地存储的容量毕竟有限,建议不要保存超过一个月的数据。
远端存储,适用于存储大量监控数据。通过中间层的适配器的转化,目前Prometheus支持OpenTSDB、InfluxDB、Elasticsearch等后端存储,通过适配器实现Prometheus存储的远程读写接口,就可以接入Prometheus作为远端存储使用。
Prometheus通过PromQL和其他 API可视化地展示收集的数据。Prometheus支持多种方式的图表可视化,例如Grafana、自带的PromDash及自身提供的模版引擎等。Prometheus还提供HTTP API查询方式,自定义所需要的输出。
Prometheus通过Pull方式拉取数据,但某些现有系统是通过 Push方式实现的,为了接入这些系统,Prometheus提供了对 PushGateway的支持,这些系统主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。
AlertManager 是独立于 Prometheus 的一个组件,在触发了预先设置在Prometheus 中的高级规则后,Prometheus 便会推送告警信息到 AlertManager。AlertManager提供了十分灵活的告警方式,可以通过邮件、slack或者钉钉等途径推送。并且 AlertManager支持高可用部署,为了解决多个AlertManager重复告警的问题,引入了Gossip,在多个AlertManager之间通过Gossip同步告警信息。
3.1 时序数据库和时序数据
时序数据库(Time Database,TSDB)用于保存时间序列(按时间顺序变化)的海量数据,是一种高性能、低成本、稳定可靠的专业化数据库。它可以提供高效的读写、高压缩比低成本存储、降精度、插值、多维聚合计算和查询功能,解决由于设备采集点数据量巨大、数据采集频率高而造成的存储成本高、写入和查询分析效率低的问题。时序数据库广泛用于物联网监控系统、企业能源管理系统、生产安全监控、电力检测系统等行业场景。
时序数据是基于时间的一系列数据,在有时间的坐标系中将这些数据点连成线,可以做成多维度报表、揭示其趋势性、规律性、异常性,也可以做大数据分析、机器学习实现预测和告警;对比传统数据库仅记录了数据的当前值,时序数据库则记录了所有的历史数据,同时时序数据的查询也总会带上时间作为过滤条件。
3.2 常见的时序数据库
3.2.1 Prometheus的时序数据库
Prometheus包括一个本地磁盘时间序列数据库,但也可以选择与远程存储系统集成,Prometheus 的本地时间序列数据库以自定义、高效的格式存储数据。存储文件格式如下 :
chunks:用于保存具体的监控数据;
index:监控数据的记录索引;
meta.json:用来记录元数据;
wal:是Write ahead log的缩写,记录的是监控预习日志。
3.2.2 InfluxDB时序数据库
InfluxDB是使用Golang语言编写的一个开源分布式时序、事件和指标数据库,无需外部依赖。
其主要特点是:
读写性能:在时序数据写入、数据压缩及实时查询方面相较于其他时序数据库有较大的优势;
支持多种接口:提供了多种通用接口,如:HTTP API和GRPC等,也支持多种时序数据库协议,例如Graphite和OpenTSDB等,方便时序数据库写入及与其他时序数据库之间的数据迁移;
支持类SQL的查询语句:可以通过InfluxDBQL语句查询InfluDB中的时序数据,InfluxDBQL是一种类SQL的查询语言,极大地降低了influxDB的使用门槛,同时也支持多种函数表达式;
数据压缩:对于近期的时序数据,会保留其原始数据,对于较久的时序数据,InfluxDB会对数据进行聚合处理,聚合后的数据精度会降低,进而降低磁盘的空间占用率。
3.2.3 Graphite时序数据库
Graphite是一个企业级的监控工具,能够在配置较低的硬件上运行,Graphite一般用于监控机器指标,如CPU使用率、内存使用量、I/O利用率和网络延迟等,Graphite也可以用于记录应用监控。
Graphite和InfluxDB类似,本身并不收集时序数据,只是提供了写入时序数据的接口,常与Graphite搭配使用的采集工具是Collectd,Collectd的功能非常强大,几乎可以捕获全部的机器信息,目前也支持Java应用的基础信息和Redis的监控信息。
优点:Graphite拥有众多的插件、庞大的社区支持、完备的文档和资料。此外其集成方案比较成熟、安装使用也相对简单。
缺点:查询时序的接口比较简单,不支持类SQL的查询语言;缺乏复制和一致性的保证;时序数据的读写效率不高;使用RDB格式的存储,要求时序数据写入间隔固定,但在某些场景中,需要进行一些额外操作,处理乱序到达的数据。
3.2.4 OpenTSDB
OpenTSDB是一款基于Hbase存储的时序数据库。时序数据在OpenTSDB中的逻辑模型与Prometheus基本类似,两者都是通过metric以及tag(label标签)标识一条时序数据。
OpenTSDB本身是无状态的,可以部署多个节点实现高可用,底层存储依赖于HBase进行持久化,由于HBase自身就拥有多副本、高可用性,因此OpenTSDB不必关注这些问题,但是OpenTSDB也并不是一个完美的解决方案,它自身也存在一些问题:
底层依赖的Hadoop和HBase本身也会引入一些复杂性;
OpenTSDB的RowKey设计在某个指标出现大量时序数据时,会造成HBase的热点问题;
OpenTSDB没有针对时序数据的特性进行压缩,而是依赖底层的HBase对数据进行压缩的;
OpenTSDB不支持类SQL的查询语句,且支持的函数较少;
OpenTSDB不提供告警的相关组件。
3.2.5 Open-Falcon
Open-Falcon是由小米开源的一套基于Golang和python的监控系统,在国内很多互联网企业都有应用,从本质上说,Open-Falcon并不仅仅是时序数据库,还是一套完整的监控方案,Open-Falcon是一个比较大的分布式系统,总共有十多个组件。
Open-Falcon涉及的组件虽然多,但是大多都是无状态的,可以进行水平扩展。Open-Falcon依赖的存储,例如MySQL、Redis等,也都有成熟的高可用方案;
Graph实际上是以RDB格式进行存储的,当监控数据量逐渐变大的时候,磁盘IO就会出现瓶颈,“高需求低产出”的评价也多次出现在Open-lcon的社区中;
精确的历史数据保存时间短,不利于历史的现场回收;
Open-Falcon整个结构中的最大的问题在于Alarm是单点的。
Prometheus提供了一种名称为PromQL(Prometheus Query Language)的功能性查询语言,让用户可以实时选择和聚合时间序列数据,表达式的结果既可以显示为图形,也可以在Prometheus表达式浏览器中以表格数据的形式显示,或者由外部系统通过HTTP API使用。
PromQL虽然是以QL结尾,但它不是类似SQL的语言,因为在时间序列上执行计算类型时,SQL语言相对缺乏表达能力,而PromQL语言表现力非常丰富,可以使用标签任意聚合,还可以使用标签将不同指标连接在一起进行算术操作。内置了日期和数据等很多的函数可供使用。
4.1 Prometheus的数据模型
Prometheus为了处理收集的时间序列数据,使用了一个多维时间序列数据模型,这个时间序列数据模型结合了时间序列名称和标签(label的键值对),这些标签提供了维度,每个时间序列以时间序列名称和标签的组合为唯一标识。
4.2 PromQL的数据类型
PromQL的数据类型共有四种,分别是即时向量(瞬时向量)、范围向量(区间向量)、标量、字符串;
即时向量/瞬时向量(instant vector):是指同一时刻的一组时间序列,每一个时间序列包含一个样本,所有样本共享相同的时间戳,即每个时序只有一个点;
范围向量/区间向量(range vector):是指在任何一个时间范围的一组时间序列,包含每个时间序列随时间变化的一系列时间点,这时每个时序有多个点;
标量(scalar):一个简单的数字浮点值,即纯量数据,只有一个数字,没有时序;
字符串(String):一个简单的字符串值,目前未使用。
4.3 Prometheus的指标类型
Prometheus定义了四种不同的指标类型:Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)
Counter类型的指标其工作方式和计数器一样,只增不减(除非系统发生重置)。常见的监控指标有http_request_tatal,node_cpu都是Counter类型的监控指标。一般在定义Counter类型指标名称时使用_total作为后缀。
Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如:node_memory_MemFree(主机当前空闲的内存大小)、node_memory_MemAvailable(可用内存大小)都是Gauge类型的监控指标。
Histogram 和 Summary主要用于统计和分析样本的分布情况。
4.4 时间序列选择器
即时矢量选择器:即时向量选择器允许在给定的时间戳(即时)选择一组时间序列和单个样本值:在最简单的形式中,只指定一个度量名称。这会产生一个即时向量,其中包含具有此度量名称的所有时间序列的元素,可以通过在花括号 {} 中附加一个逗号分隔的标签匹配器列表来进一步过滤这些时间序列;
范围矢量选择器:范围向量字面量的工作方式类似于即时向量字面量,只是它们从当前时刻选择一系列样本。从语法上讲,持续时间附加在 [] 向量选择器末尾的方括号中,以指定应该为每个结果范围向量元素获取多远的时间值。
4.5 标签匹配运算符和时间单位
标签匹配运算符:
=:选择与提供的字符串完全相等的标签;
!=:选择不等于提供的字符串的标签;
=~:选择与提供的字符串进行正则表达式匹配的标签;
!~:选择与提供的字符串不匹配的标签。
时间单位:
ms:毫秒
s:秒
m:分钟
h:小时
d:天
w:周
y:年
4.6 偏移修改器
使用offset修饰符可以更改查询中各个瞬间和范围向量的时间偏移量;
node_load1:该指标表示节点的负载;
例如:node_load1 offset 5m
node_load1 offset 5m :查询5分钟之前的负载,结果为瞬时向量;
例如:node_load1 [5m] offset 1d
表示1天前的现在到1天前现在的前5分钟范围内的负载,结果为范围向量。
4.7 PromQL的聚合操作
Prometheus为使用者提供了内置的聚合操作符,这些操作符仅仅适用于对单个向量进行聚合操作。他们可以将即时向量聚合后生成一个包含少量元素的新的时间序列。
聚合操作的语法:
<聚合操作>(指标查询表达式)[without | by (标签列表)]
例如:sum(node_cpu_seconds_total)
sum(node_cpu_seconds_total) by (mode)
更多函数参考:
https://prometheus.io/docs/prometheus/latest/querying/functions/
4.8 PromQL运算符
算数运算符:
+:加法
-:减法
*:乘法
/:除法
%:取模
^:幂运算
关系运算符:
==:等于
!=:不等于
>:大于
<:小于
>=:大于等于
<=:小于等于
逻辑运算符:
and:与
or:或
unless:非
在了解如何计算CPU 5分钟内的利用率之前,我们首先来看一下CPU的几种工作模式:
user:用户进程使用CPU的时间
system:内核进程使用CPU的时间
nice:用户进程空间内改变过优先级的进程使用CPU的时间
idle:空闲(没有使用)CPU的时间
iowait:等待IO的CPU的时间
irq:硬件中断的CPU时间
sioftirq:软件中断的CPU时间
steal:虚拟机管理程序使用CPU的时间
计算CPU5分钟内的利用率:1-CPU的空闲时间 / CPU的总时间
第一步:计算CPU5分钟内的空闲时间:
sum(increase(node_cpu_seconds_total{mode = "idle"} [5 m] )) by (instance)
第二步:计算CPU的总时间 :
sum(increase(node_cpu_seconds_total [5 m] )) by (instance)
第三步:整合结果:
(1-(sum(increase(node_cpu_seconds_total{mode = "idle"} [5 m] )) by (instance))/(sum(increase(node_cpu_seconds_total [5 m] )) by (instance))) * 100%
本期内容就到这里了,如果喜欢就点个关注吧,微信公众号搜索“数 新 网 络 科 技 号”可查看更多精彩内容~