Prometheus – 服务监控系统

一、监控系统基础概念

1.1 监控系统发展史

  • SNMP监控时代:网络设备及网络流量,主要监控网络设备及操作系统,需要内置SNMP支持,产生于上世纪80年代;
  • 当今的监控系统:数据采集、存储、告警、展示等功能,zabbix、prometheus、cacti、Nagios、openfoam、Grafana;
  • 下一代监控系统: 依赖立体监控的,基于DataOps、AiOps的,对于系统运行状态的分析与监视,并回馈到系统上,达到自动处理的方案。

1.2 监控系统组件

  • 指标数据采集(抓取)
  • 指标数据存储
  • 指标数据趋势分析及可视化
  • 告警:WeChat、DingTalk、Email …

1.3 监控体系

  • 系统层监控
    • 系统监控:CPU、Load、Memory、Swap、Disk、IO、Processes、Kernel Parameter …
    • 网络监控:网络设备、工作负载、网络延迟、丢包率 …
  • 中间件及基础设施类服务监控
    • 消息中间件:Kafka、RocketMQ、RabbitMQ …
    • WEB服务容器:Tomcat、Jetty …
    • 数据库及缓存系统:MySQL、PostgreSQL、MonoDB、ElasticSearch、Redis …
    • 数据库连接池:ShardingSpere …
    • 存储系统:ceph …
  • 应用层监控
    • 用于衡量应用程序代码的状态和性能
  • 业务层监控
    • 用于衡量应用程序的价值,如电商网站上的销售量
    • QPS、DAU日活、转化率
    • 业务接口:登录数、注册数、订单量、搜索量、支付量 …
  • 端监控
    • App、特定程序 的特定的表现 …

1.4 云原生时代的可观测性

  • 可观测性系统
    • 指标监控(Metric):随着时间推移而产生的与监控相关的可聚合数据点;
    • 日志监控(Logging):离散式的日志或事件;
    • 链路监控(Tracing):分布式应用调用跟踪链,调用的性能数据及状态数据。
  • CNCF将可观测性和数据分析归类并划分为4个子类
    • 监控系统:以Prometheus等为代表;
    • 日志系统:以ElasticStack和PLG Stack等为代表;
    • 分布式调用链跟踪系统:以Zipkin、Jaeger、SkyWalking、Pinpoint等为代表;
    • 混沌工程系统:以ChaosMonkey、ChaosBlade等为代表。

1.5 著名的监控方法论

  • Google的四个黄金指标
    • 常用于在服务级别帮助衡量终端用户体验、服务中断、业务影响等层面的问题
    • 适用于应用及服务监控
  • Netflix的USE方法
    • 全称为“Utilization Saturation and Errors Method”,主要用于分析系统性能问题,可以指导用户快速识别资源瓶颈以及错误的方法
    • 适用于主机指标监控
  • Weave Cloud的RED方法
    • Weave Cloud基于Google的四个黄金指标的原则下结合Prometheus以及Kubernetes容器实践,细化和总结的方法论
    • 适用于云原生应用以及微服务架构应用的监控和度量

1.5.1 黄金指标

四个黄金指标源自Google的SRE一书
延迟(Latency)
– 服务请求所需要的时长,例如HTTP请求平均延迟;
– 需要区分失败请求和成功请求;
流量(Traffic)
– 衡量服务的容量需求, 例如每秒处理的HTTP请求数或者数据库系统的事务数量;
错误(Errors)
– 请求失败的速率,用于衡量错误发生的情况
– 例如,HTTP 500错误数等显式失败,返回错误内容或无效内容等隐式失败,以及由策略原因导致的失败(例如强制要求响应时间超过30毫秒的请求视为错误);
饱和度(Saturation)
– 衡量资源的使用情况,用于表达应用程序有多“满”
– 例如内存、CPU、I/O、磁盘等资源的使用量

1.5.2 USE方法

USE方法由Netflix的内核和性能工程师Rendan Gregg提出,主要用于分析系统性能问题
使用率(Utilization)
关注系统资源的使用情况。 这里的资源主要包括但不限于:CPU,内存,网络,磁盘等等,100%的使用率通常是系统性能瓶颈的标志
饱和度(Saturation)
例如CPU的平均运行排队长度,这里主要是针对资源的饱和度(注意,不同于4大黄金信号),任何资源在某种程度上的饱和都可能导致系统性能的下降
错误(Errors)
错误计数。例如:“网卡在数据包传输过程中检测到的以太网网络冲突了14次”。

1.5.3 RED方法

RED方法是Weave Cloud在基于Google的4个黄金指标的原则下结合Prometheus以及Kubernetes容器实践,细化和总结的方法论,特别适合于云原生应用以及微服务架构应用的监控和度量。

在四大黄金指标的原则下,RED方法可以有效地帮助用户衡量云原生以及微服务应用下的用户体验问题;

RED方法主要关注以下3种关键指标
(Request)Rate:每秒钟接收的请求数,即速率;
(Request)Errors:每秒失败的请求数,即错误数;
(Request)Duration:每个请求所花费的时长;

二、Prometheus入门

2.1 Prometheus基本概念

首先,Prometheus是一款时序(time series)数据库;但它的功能却并非止步于TSDB,而是一款设计用于进行目标(Target)监控的关键组件;

结合生态系统内的其它组件,例如Pushgateway、Altermanager和Grafana等,可构成一个完整的IT监控系统;

2.2 时序数据

时序数据,是在一段时间内通过重复测量(measurement)而获得的观测值集合;将这些观测值绘制于图形之上,它会有一个数据轴和一个时间轴;
– As our world gets increasingly instrumented, sensors and systems are constantly emitting a relentless stream of time series data.
– Weather records, economic indicators and patient health evolution metrics — all are time series data.

服务器指标数据、应用程序性能监控数据、网络数据等也都是时序数据;

2.3 Prometheus 能做什么

从配置文件中指定的网络端点(endpoint)上周期性获取指标数据

  • 基于HTTP call的形式,可以是http或https协议来实现
  • 仅支持pull拉取数据

白盒与黑盒机制

  • 白盒:拥有自醒方式,被监控的系统自己可以生成指标,当监控系统发起采集请求时,可以按需提供所需数据;
  • 黑盒:对于目标系统不具备侵入性,也称基于探针机制;

Prometheus 支持通过三种类型的途径从目标上“抓取(Scrape”指标数据

  • Exporters:获取指标数据的获取器/暴露器(收集客户端服务数据);
  • Instrumentation:测量系统(系统内嵌了符合Prometheus指标数据格式的数据);
  • Pushgateway:客户端将数据推送给Pushgateway,然后Prometheus获取Pushgateway中的数据。

  • By ‘instrumenting’ your application, meaning that your application will expose Prometheus compatible metrics on a given URL.

  • By using of the prebuilt exporters : Prometheus has an entire collection of exporters for existing technologies.

    You can for example find prebuilt exporters for Linux machine monitoring (node exporter), for very established databases (SQL exporter or MongoDB exporter) and even for HTTP load balancers (such as the HAProxy exporter).

  • By using the Pushgateway : sometimes you have applications or jobs that do not expose metrics directly.

    Those applications are either not designed for it (such as batch jobs for example), or you may have made the choice not to expose those metrics directly via your app.

2.4 拉取与推送数据(Pull and Push)

Prometheus同其它TSDB相比有一个非常典型的特性:它主动从各Target上“拉取(pull)”数据,而非等待被监控端的“推送(push)”

两个方式各有优劣,其中,Pull模型的优势在于:
– 集中控制:有利于将配置集在Prometheus Server上完成,包括指标及采取速率等;

  • Prometheus的根本目标在于收集在Target上预先完成聚合的聚合型数据,而非一款由事件驱动的存储系统;

2.5 Prometheus 的生态组件

Prometheus负责时序型指标数据的采集及存储,但数据的分析、聚合及直观展示以及告警等功能并非由Prometheus Server所负责;

Prometheus 生态圈中包含了多个组件,其中部分组件可选

  • Prometheus Server: 收集和存储时间序列数据;
    • Scraping:指标数据采集
    • Storage:内置TSDB(独立开发、对外开源的时序数据库,现阶段为3.0版本)
    • Rules and Alerts:也可称为PromQL接口
    • Service Discovery:动态发现待监控的Target,从而完成监控配置的重要组件,在容器化环境中尤为有用;该组件目前由Prometheus Server内建支持;
  • Client Library: 客户端库,目的在于为那些期望原生提供Instrumentation功能的应用程序提供便捷的开发途径;
  • Exporters: 用于暴露现有应用程序或服务(不支持Instrumentation)的指标给Prometheus Server;
  • Push Gateway: 接收那些通常由短期作业生成的指标数据的网关,并支持由Prometheus Server进行指标拉取操作;
  • Alertmanager: 从Prometheus Server接收到“告警通知”后,通过去重、分组、路由等预处理功能后以高效向用户完成告警信息发送;
  • Data Visualization:Prometheus Web UI (Prometheus Server内建),及Grafana等;

2.6 Prometheus 数据模型

Prometheus仅用于以”键值“形式存储时序式的聚合数据,它并不支持存储文本信息;

  • 其中的“键”称为指标(Metric),它通常意味着CPU速率、内存使用率或分区空闲比例等;

  • 同一指标可能会适配到多个目标或设备,因而它使用“标签”作为元数据,从而为Metric添加更多的信息描述纬度;

  • 这些标签还可以作为过滤器进行指标过滤及聚合运算;

2.7 指标类型(Metric Types)

Prometheus使用4种方法来描述监视的指标

  • Counter:计数器,用于保存单调递增型的数据,例如站点访问次数等;不能为负值,也不支持减少,但可以重置回0;

  • Gauge:仪表盘,用于存储有着起伏特征的指标数据,例如内存空闲大小等;

    Gauge是Counter的超集;但存在指标数据丢失的可能性时,Counter能让用户确切了解指标随时间的变化状态,而Gauge则可能随时间流逝而精准度越来越低;

  • Histogram:直方图,它会在一段时间范围内对数据进行采样,并将其计入可配置的bucket之中;Histogram能够存储更多的信息,包括样本值分布在每个bucket(bucket自身的可配置)中的数量、所有样本值之和以及总的样本数量,从而Prometheus能够使用内置的函数进行如下操作:

    • 计算样本平均值:以值的总和除以值的数量;

    • 计算样本分位值:分位数有助于了解符合特定标准的数据个数;例如评估响应时长超过1秒钟的请求比例,若超过20%即发送告警等;

  • Summary:摘要,Histogram的扩展类型,但它是直接由被监测端自行聚合计算出分位数,并将计算结果响应给Prometheus Server的样本采集请求;因而,其分位数计算是由由监控端完成;

2.8 作业(Job)和实例(Instance)

Instance:能够接收Prometheus Server数据Scrape操作的每个网络端点(endpoint),即为一个Instance(实例);

具有类似功能的Instance的集合称为一个Job,例如一个MySQL主从复制集群中的所有MySQL进程;

2.9 PromQL

Prometheus提供了内置的数据查询语言 PromQL(全称为Prometheus Query Language),支持用户进行实时的数据查询及聚合操作;

PromQL支持处理两种向量,并内置提供了一组用于数据处理的函数

  • 即时向量:最近一次的时间戳上跟踪的数据指标;

  • 时间范围向量:指定时间范围内的所有时间戳上的数据指标;

2.10 Instrumentation(程序仪表)

任何能够支持Scrape指标数据的应用程序都首先要具有一个测量系统;

在Prometheus的语境中,Instrumentation是指附加到应用程序中的那些用于暴露程序指标数据的客户端库;

  • 程序员借助于这些客户端库编写代码生成可暴露的指标数据;

2.11 Exporters

对于未内建Instrumentation,且也不便于自行添加该类组件以暴露指标数据的应用程序来说,常用的办法是于待监控的目标应用程序外部运行一个独立指标暴露程序,该类型的程序即统称为Exporter;

换句话说,Exporter负责从目标应用程序上采集和聚合原始格式的数据,并转换或聚合为Prometheus格式的指标向外暴露;

Prometheus站点上提供了大量的Exporter

2.12 Alerts

抓取到异常值后,Prometheus支持通过“告警(Alert)”机制向用户发送反馈或警示,以触发用户能够及时采取应对措施,

Prometheus Server仅负责生成告警指示,具体的告警行为由另一个独立的应用程序AlertManager负责;

  • 告警指示由Prometheus Server基于用户提供的“告警规则”周期性计算生成;

  • Alertmanager接收到Prometheus Server发来的告警指示后,基于用户定义的告警路由(route)向告警接收人(receivers)发送告警信息;

2.13 Prometheus 系统架构图

prometheus server:主服务,接受外部http请求,收集、存储与查询数据等
prometheus targets: 静态收集的目标服务数据
service discovery:动态发现服务
prometheus alerting:报警通知
pushgateway:数据收集代理服务器(类似于zabbix proxy)
data visualization and export: 数据可视化与数据导出(访问客户端)

参考:https://prometheus.io/docs/introduction/overview/

2.14 Prometheus的工作模式

Prometheus Server基于服务发现(Service Discovery)机制或静态配置获取要监视的目标(Target),并通过每个目标上的指标exporter来采集(Scrape)指标数据

Prometheus Server内置了一个基于文件的时间序列存储来持久存储指标数据,用户可使用PromDash或PromQL接口来检索数据,也能够按需将告警需求发往Alertmanager完成告警内容发送

一些短期运行的作业的生命周期过短,难以有效地将必要的指标数据供给到Server端,它们一般会采用推送(Push)方式输出指标数据,Prometheus借助于Pushgateway接收这些推送的数据,进而由Server端进行抓取

2.15 Prometheus的局限性

Prometheus是一款指标监控系统,不适合存储事件及日志等;它更多地展示的是趋势性的监控,而非精准数据;

Prometheus认为只有最近的监控数据才有查询的需要,其本地存储的设计初衷只是保存短期(例如一个月)数据,因而不支持针对大量的历史数据进行存储;

若需要存储长期的历史数据,建议基于远端存储机制将数据保存于InfluxDB或OpenTSDB等系统中;

Prometheus的集群机制成熟度不高,即便基于Thanos亦是如此;

三、部署及运行Prometheus

3.1 安装 Prometheus 介绍

3.1.1 使用预制的程序包

参考:https://prometheus.io/download/

3.1.2 使用包管理器

CentOS上可基于yum repository安装Prometheus-Server
– https://packagecloud.io/app/prometheus-rpm/release/search

[prometheus]
name=prometheus
baseurl=https://packagecloud.io/prometheus-rpm/release/el/releasever/basearch
repo_gpgcheck=1
enabled=1
gpgkey=https://packagecloud.io/prometheus-rpm/release/gpgkey
https://raw.githubusercontent.com/lest/prometheus-rpm/master/RPM-GPG-KEY-prometheus-rpm
gpgcheck=1
metadata_expire=300

3.1.3 Ubuntu与Debian

UbuntuDebian可直接使用apt命令安装

3.2 在ubuntu下使用预制包安装

  1. 下载当然最新版本的预制包(OS=linux,Arch=amd64)
    wget https://github.com/prometheus/prometheus/releases/download/v2.24.1/prometheus-2.24.1.linux-amd64.tar.gz
    
  2. 解压缩至所需路径
    tar xvf prometheus-2.24.1.linux-amd64.tar.gz -C /usr/local/
    ln -s prometheus-2.24.1.linux-amd64/ prometheus
    
  3. 直接启动服务端
    ./prometheus
    
  4. 网页访问

    服务端页面:http://IPADDR:9090/

    客户端暴露页面:http://IPADDR:9090/metrics

四、Exporters 介绍

4.1 客户端库

应用程序自己并不会直接生成指标数据,这依赖于开发人员将相关的客户端库添加至应用程序中构建出的测量系统(instrumentation system)来完成。

  • Prometheus为包括Go、Python、Java(或Scala)和Ruby等主流的编程语言提供了各自适用的客户端库,另外还有适用于Bash、C、C++、C#、Node.js、Haskell、Erlang、Perl、PHP和Rust等多种编程语言的第三方库可用;

  • 通常,三两行代码即能将客户端库整合进应用程序中实现直接测量(direct instrumentation)机制;

客户端库主要负责处理所有的细节类问题,例如线程安全和记账,以及生成文本格式的指标以数据响应HTTP请求等;

客户端库通常还会额外提供一些指标,例如CPU使用率和垃圾回收统计信息等,具体的实现则取决于库和相关的运行时环境;

4.2 Exporter 基础

对于那些非由用户可直接控制的应用代码来说,为其添加客户端库以进行直接测量很难实现

  • 操作系统内核就是一个典型的示例,它显然不大可能易于实现添加自定义代码通过HTTP协议输出Prometheus格式的指标

  • 但这一类的程序一般都会通常某种接口输出其内在的指标,只不过这些指标可能有着特殊的格式,例如Linux内核的特有指标格式,或者SNMP指标格式等

  • 这些指标需要对它进行适当的解析和处理以转换为合用的目标格式,Exporter(指标暴露器)是完成此类转换功能的应用程序

Exporter独立运行于要获取其测量指标的应用程序之外,负责接收来自于Prometheus Server的指标获取请求,它通过目标应用程序(真正的目标)内置的指标接获取指标数据,并将这些指标数据转换为合用的目标格式后响应给Prometheus

  • Exporter更像是“一对一”的代理,它作为Prometheus Server的target存在,工作于应用程序的指标接口和Prometheus的文本指标格式之间转换数据格式

  • 但Exporter不存储也不缓存任何数据

4.3 部署 Node Export 监控系统级指标

下载相应的程度包文件(amd64)

4.4 Exporter Unit文件示例

首先添加Prometheus用户

其次,创建node_exporter.service这一Unitfile,文件内容类似如下

# sudo vim /lib/systemd/system/node_exporter.service

[Unit]
Description=node_exporter
Documentation=https://prometheus.io/
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/node_exporter \
    --collector.ntp \
    --collector.mountstats \
    --collector.systemd \
    --collector.tcpstat
ExecReload=/bin/kill -HUP $MAINPID
TimeoutStopSec=20s
Restart=always

[Install]
WantedBy=multi-user.target

4.5 Node Exporter 的指标

node-export如何启用内置的指标

  • Collectors are enabled by providing a –collector. flag.

  • Collectors that are enabled by default can be disabled by providing a –no-collector. flag.

常用的各指标

  • node_cpu_seconds_total
  • node_memory_MemTotal_bytes
  • node_filesystem_size_bytes{mount_point=PATH}
  • node_system_unit_state{name=}
  • node_vmstat_pswpin:系统每秒从磁盘读到内存的字节数;
  • node_vmstat_pswpout:系统每秒钟从内存写到磁盘的字节数;

更多指标介绍: https://github.com/prometheus/node_exporter

4.6 适用于主机监控的 USE 方法

USE 是使用率(Utilization)、饱和度(Saturation)和错误(Error)的缩写,由Netflix的内核和性能工程师Brendan Gregg开发;

USE方法可以概括为:针对每个资源,检查使用率、饱和度和错误;

  • 资源:系统的一个组件,在USE中,它指的是一个传统意义上的物理服务器组件,如CPU、内存和磁盘等;
  • 使用率:资源忙于工作的平均时间,它通常用随时间变化的百分比进行表示;
  • 饱和度:资源排队工作的指标,无法再处理额外的工作;通常用队列长度表示;
  • 错误:资源错误事件的计数;

CPU来说,USE通常意味着如下概念

  • CPU使用率随时间的百分比;
  • CPU饱和度,等待CPU的进程数;
  • 错误,通常对CPU不太有影响;

内存来说,USE的意义相似

  • 内存使用率随时间的百分比;
  • 内存饱和度,可通过监控swap进行测量;
  • 错误,通常不太关键;

4.7 CPU 使用率

每台主机CPU在5分钟内的平均使用率

(1-avg(irate(node_cpu_seconds_total{mode="idle"}[5m]))by(instance))*100

4.8 CPU 饱和度

跟踪 CPU 的平均负载就能获取到相关主机的CPU饱和度,实际上,它是将主机上的CPU数量考虑在内的一段时间内的平均运行队列长度

  • 平均负载少于CPU的数量是正常状况,而长时间内超过CPU数量则表示CPU已然饱和;

  • node_load1 > on (instance) 2 * count (node_cpu_seconds_total{mode=”idle”}) by (instance)
    查询1分钟平均负载超过主机CPU数量两倍的时间序列

4.9 内存使用率

node_exporter暴露了多个以 node_memory 为前缀的指标,我们重点关注如下几个

  • node_memory_MemTotal_bytes 总内存空间
  • node_memory_MemFree_bytes 空闲内存空间(total-used-buffer-cache)
  • node_memory_Buffers_bytes
  • node_memory_Cached_bytes

计算使用率

  • 可用空间:上面后三个指标之和;
  • 已用空间:总空间减去可用空间;
  • 使用率:已用空间除以总空间;

4.10 MySQL exporter

Exporter Unit File 示例

vim /usr/lib/systemd/system/mysqld_exporter.service

[Unit]
Description=mysql_exporter
Documentation=https://prometheus.io/
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/mysqld_exporter/mysqld_exporter --config.my-cnf=my.cnf
Restart=on-failure

[Install]
WantedBy=multi-user.target

my.cnf 文件示例

[client]
host=127.0.0.1
user=exporter
password=password

授权exporter用户

mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';

五、PromQL 基础

5.1 Prometheus 时间序列

时间序列数据:按照时间顺序记录系统、设备状态变化的数据,每个数据称为一个样本;

数据采集以特定的时间周期进行,因而,随着时间流逝,将这些样本数据记录下来,将生成一个离散的样本数据序列;

该序列也称为向量(Vector);而将多个序列放在同一个坐标系内(以时间为横轴,以序列为纵轴),将形成一个由数据点组成的矩阵

5.1.1 PromQL 简介

Prometheus 基于指标名称(metrics name)以及附属的标签集(labelset)唯一定义一条时间序列

  • 指标名称代表着监控目标上某类可测量属性的基本特征标识

  • 标签则是这个基本特征上再次细分的多个可测量维度

基于 PromQL 表达式,用户可以针对指定的特征及其细分的纬度进行过滤、聚合、统计等运算从而产生期望的计算结果

PromQL (Prometheus Query Language)是 Prometheus Server 内置数据查询语言

  • PromQL使用表达式(expression)来表述查询需求

  • 根据其使用的指标和标签,以及时间范围,表达式的查询请求可灵活地覆盖在一个或多个时间序列的一定范围内的样本之上,甚至是只包含单个时间序列的单个样本

5.1.2 Prometheus 数据模型

Prometheus中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识,格式为“<metric name>{<label name>=<label value>, …}”;

  • 指标名称:通常用于描述系统上要测定的某个特征;
    • 例如,http_requests_total表示接收到的HTTP请求总数;

    • 支持使用字母、数字、下划线和冒号,且必须能匹配RE2规范的正则表达式;

  • 标签:键值型数据,附加在指标名称之上,从而让指标能够支持多纬度特征;可选项;

  • 例如,http_requests_total{method=GET}http_requests_total{method=POST}代表着两个不同的时 间序列;

    • 标签名称可使用字母、数字和下划线,且必须能匹配RE2规范的正则表达式;

    • 以“_ _”为前缀的名称为Prometheus系统预留使用;

Metric Name的表示方式有两种,后一种通常用于Prometheus内部。

5.1.3 样本数据格式

Prometheus的每个数据样本由两部分组成

  • loat64格式的数据

  • 毫秒精度的时间戳

5.1.4 指标名称及标签使用注意事项

指标名称和标签的特定组合代表着一个时间序列;

  • 指标名称相同,但标签不同的组合分别代表着不同的时间序列;

  • 不同的指标名称自然更是代表着不同的时间序列;

PromQL支持基于定义的指标维度进行过滤和聚合

  • 更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列

  • 应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个动态的数据环境,并使得监控的数据源难以跟踪,从而导致建立在该指标之上的图形、告警及记录规则变得无效

5.1.5 PromQL 的数据类型

PromQL的表达式中支持4种数据类型

  • 即时向量(Instant Vector):特定或全部的时间序列集合上,具有相同时间戳的一组样本值称为即时向量;

  • 范围向量(Range Vector):特定或全部的时间序列集合上,在指定的同一时间范围内的所有样本值;

  • 标量(Scalar):一个浮点型的数据值;

  • 字符串(String):支持使用单引号、双引号或反引号进行引用,但反引号中不会对转义字符进行转义;

5.2 时间序列选择器(Time series Selectors)

PromQL的查询操需要针对有限个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式时最为关键的一步

用户可使用向量选择器表达式来挑选出给定指标名称下的所有时间序列或部分时间序列的即时(当前)样本值或至过去某个时间范围内的样本值,前者称为即时向量选择器,后者称为范围向量选择器

  • 即时向量选择器(Instant Vector Selectors):返回0个、1个或多个时间序列上在给定时间戳(instant)上的各自的一个样本,该样本也可称为即时样本;

  • 范围向量选择器(Range Vector Selectors) :返回0个、1个或多个时间序列上在给定时间范围内的各自的一组样本;

5.2.1 向量表达式使用要点

表达式的返回值类型亦是即时向量、范围向量、标量或字符串4种数据类型其中之一,但是,有些使用场景要求表达式返回值必须满足特定的条件,例如

  • 需要将返回值绘制成图形时,仅支持即时向量类型的数据;

  • 对于诸如rate一类的速率函数来说,其要求使用的却又必须是范围向量型的数据;

由于范围向量选择器的返回的是范围向量型数据,它不能用于表达式浏览器中图形绘制功能,否则,表达式浏览器会返回“Error executing query: invalid expression type “range vector” for range query, must be Scalar or instant Vector”一类的错误

  • 事实上,范围向量选择几乎总是结合速率类的函数rate一同使用

5.2.2 即时向量选择器

即时向量选择器由两部分组成;

  • 指标名称:用于限定特定指标下的时间序列,即负责过滤指标;可选;

  • 匹配器(Matcher):或称为标签选择器,用于过滤时间序列上的标签;定义在{}之中;可选;

显然,定义即时向量选择器时,以上两个部分应该至少给出一个;于是,这将存在以下三种组合;

  • 仅给定指标名称,或在标签名称上使用了空值的匹配器:返回给定的指标下的所有时间序列各自的即时样本;

    例如:http_requests_total和http_requests_total{}的功能相同,都是用于返回http_requests_total指标下各时间序列的即时样本;

  • 仅给定匹配器:返回所有符合给定的匹配器的所有时间序列上的即时样本;

    注意:这些时间序列可能会有着不同的指标名称;

    例如:{job=”.*”, method=”get”}

  • 指标名称和匹配器的组合:返回给定的指定下的,且符合给定的标签过滤器的所有时间序列上的即时样本;

    例如:http_requests_total{method=”get”}

5.2.3 匹配器(Matcher)

匹配器用于定义标签过滤条件,目前支持如下4种匹配操作符;

  • =: Select labels that are exactly equal to the provided string.

  • !=: Select labels that are not equal to the provided string.

  • =~: Select labels that regex-match the provided string.

  • !~: Select labels that do not regex-match the provided string.

注意事项

  • 匹配到空标签值的匹配器时,所有未定义该标签的时间序列同样符合条件;

    例如:http_requests_total{env= “”},则该指标名称上所有未使用该标签(env)的时间序列也符合

    条件,比如时间序列http_requests_total{method =”get”} ;

  • 正则表达式将执行完全锚定机制,它需要匹配指定的标签的整个值;

  • 向量选择器至少要包含一个指标名称,或者至少有一个不会匹配到空字符串的匹配器;

    例如:{job=””}为非法的选择器;

  • 使用“__name__”做为标签名称,还能够对指标名称进行过滤;

    例如:{__name__=~"http_requests_.*“}能够匹配所有以“http_requests_”为前缀的所有指标;

5.2.4 范围向量选择器

同即时向量选择器的唯一不同之处在于,范围向量选择器需要在表达式后紧跟一个方括号[ ]来表达需在时间时序上返回的样本所处的时间范围;

  • 时间范围:以当前时间为基准时间点,指向过去一个特定的时间长度;例如[5m]便是指过去5分钟之内;

时间格式:一个整数后紧跟一个时间单位,例如“5m”中的“m”即是时间单位;

  • 可用的时间单位有ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周)和y(年);

  • 必须使用整数时间,且能够将多个不同级别的单位进行串联组合,以时间单位由大到小为顺序,例如1h30m,但不能使用1.5h;

需要注意的是,范围向量选择器返回的是一定时间范围内的数据样本,虽然不同时间序列的数据抓取时间点相同,但它们的时间戳并不会严格对齐;

  • 多个Target上的数据抓取需要分散在抓取时间点前后一定的时间范围内,以均衡Prometheus Server的负载;

  • 因而,Prometheus在趋势上准确,但并非绝对精准;

5.2.5 偏移量修改器

默认情况下,即时向量选择器和范围向量选择器都以当前时间为基准时间点,而偏移量修改器能够修改该基准;

偏移量修改器的使用方法是紧跟在选择器表达式之后使用“offset”关键字指定

  • http_requests_total offset 5m”,表示获取以http_requests_total为指标名称的所有时间序列在过去5分钟之时的即时样本;

  • http_requests_total[5m] offset 1d”,表示获取距此刻1天时间之前的5分钟之内的所有样本;

5.3 PromQL 的指标类型

PromQL有四个指标类型,它们主要由Prometheus的客户端库使用

  • Counter:计数器,单调递增,除非重置(例如服务器或进程重启);

  • Gauge:仪表盘,可增可减的数据;

  • Histogram:直方图,将时间范围内的数据划分成不同的时间段,并各自评估其样本个数及样本值之和,因而可计算出分位数;

    • 可用于分析因异常值而引起的平均值过大的问题;

    • 分位数计算要使用专用的histogram_quantile函数;

  • Summary:类似于Histogram,但客户端会直接计算并上报分位数;\

Prometheus Server并不使用类型信息,而是将所有数据展平为时间序列

5.3.1 Counter

通常,Counter的总数并没有直接作用,而是需要借助于rate(速率)、topk(排序后N个)、increase(步长)和irate(更精确的速率)等函数来生成样本数据的变化状况(增长率);

  • rate(http_requests_total[2h]),获取2小内,该指标下各时间序列上的http总请求数的增长速率;

  • topk(3, http_requests_total),获取该指标下http请求总数排名前3的时间序列;

  • irate(http_requests_total[2h]),高灵敏度函数,用于计算指标的瞬时速率;

    • 基于样本范围内的最后两个样本进行计算,相较于rate函数来说,irate更适用于短期时间范围内的变化速率分析;

5.3.2 Gauge

Gauge用于存储其值可增可减的指标的样本数据,常用于进行求和、取平均值、最小值、最大值等聚合计算;也会经常结合PromQL的predict_linear和delta函数使用;

  • predict_linear(v range-vector, t, scalar)函数可以预测时间序列v在t秒后的值,它通过线性回归的方式来预测样本数据的Gauge变化趋势;

  • delta(v range-vector)函数计算范围向量中每个时间序列元素的第一个值与最后一个值之差,从而展示不同时间点上的样本值的差值;

    • delta(cpu_temp_celsius{host=”web01.magedu.com”}[2h]),返回该服务器上的CPU温度与2小时之前的差异;

5.3.3 Histogram

Histogram是一种对数据分布情况的图形表示,由一系列高度不等的长条图(bar)或线段表示,用于展示单个测度的值的分布

  • 它一般用横轴表示某个指标维度的数据取值区间,用纵轴表示样本统计的频率或频数,从而能够以二维图的形式展现数值的分布状况

  • 为了构建Histogram,首先需要将值的范围进行分段,即将所有值的整个可用范围分成一系列连续、相邻(相邻处可以是等同值)但不重叠的间隔,而后统计每个间隔中有多少值

  • 从统计学的角度看,分位数不能被聚合,也不能进行算术运算;

对于Prometheus来说,Histogram会在一段时间范围内对数据进行采样(通常是请求持续时长或响应大小等),并将其计入可配置的bucket(存储桶)中

  • Histogram事先将特定测度可能的取值范围分隔为多个样本空间,并通过对落入bucket内的观测值进行计数以及求和操作

  • 与常规方式略有不同的是,Prometheus 取值间隔的划分采用的是累积(Cumulative)区间间隔机制,即每个bucket中的样本均包含了其前面所有bucket中的样本,因而也称为累积直方图

    • 可降低Histogram的维护成本

    • 支持粗略计算样本值的分位数

    • 单独提供了_sum和_count指标,从而支持计算平均值

Histogram类型的每个指标有一个基础指标名称,它会提供多个时间序列:

  • _bucket{le=”“}:观测桶的上边界(upper inclusive bound),即样本统计区间,最大区间(包含所有样本)的名称为 _bucket{le=”+Inf”};

  • _sum:所有样本观测值的总和;

  • _count :总的观测次数,它自身本质上是一个Counter类型的指标;

累积间隔机制生成的样本数据需要额外使用内置的histogram_quantile()函数即可根据Histogram指标来计算相应的分位数(quantile),即某个bucket的样本数在所有样本数中占据的比例

  • histogram_quantile()函数在计算分位数时会假定每个区间内的样本满足线性分布状态,因而它的结果仅是一个预估值,并不完全准确;

  • 预估的准确度取决于bucket区间划分的粒度;粒度越大,准确度越低;

5.3.4 Summary

指标类型是客户端库的特性,而 Histogram 在客户端仅是简单的桶划分和分桶计数,分位数计算由Prometheus Server基于样本数据进行估算,因而其结果未必准确,甚至不合理的bucket划分会导致较大的误差;

Summary 是一种类似于 Histogram 的指标类型,但它在客户端于一段时间内(默认为10分钟)的每个采样点进行统计,计算并存储了分位数数值,Server端直接抓取相应值即可;

但Summary不支持sum或avg一类的聚合运算,而且其分位数由客户端计算并生成,Server端无法获取客户端未定义的分位数,而Histogram可通过PromQL任意定义,有着较好的灵活性;

对于每个指标,Summary以指标名称为前缀,生成如下几个个指标序列

  • {quantile=”<φ>”},其中φ是分位点,其取值范围是(0 ≤φ≤ 1);计数器类型指标;如下是几种典型的常用分位点;
    • 0、0.25、0.5、0.75和1几个分位点;

    • 0.5、0.9和0.99几个分位点;

    • 0.01、0.05、0.5、0.9和0.99几个分位点;

  • _sum,抓取到的所有样本值之和;

  • _count,抓取到的所有样本总数;

六、PromQL 进阶

6.1. Prometheus的聚合函数

一般说来,单个指标的价值不大,监控场景中往往需要联合并可视化一组指标,这种联合机制即是指“聚合”操作,例如,将计数、求和、平均值、分位数、标准差及方差等统计函数应用于时间序列的样本之上生成具有统计学意义的结果等;

对查询结果事先按照某种分类机制进行分组(groupby)并将查询结果按组进行聚合计算也是较为常见的需求,例如分组统计、分组求平均值、分组求和等;

聚合操作由聚合函数针对一组值进行计算并返回单个值或少量几值作为结果

  • Prometheus内置提供的11个聚合函数也称为聚合运算符

  • 这些运算符仅支持应用于单个即时向量的元素,其返回值也是具有少量元素的新向量或标量

  • 这些聚合运行符既可以基于向量表达式返回结果中的时间序列的所有标签维度进行分组聚合,也可以仅基于指定的标签维度分组后再进行分组聚合

6.2 聚合表达式

PromQL中的聚合操作语法格式可采用如下面两种格式之一

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
<aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)

分组聚合:先分组、后聚合

  • without:从结果向量中删除由without子句指定的标签,未指定的那部分标签则用作分组标准;

  • by:功能与without刚好相反,它仅使用by子句中指定的标签进行聚合,结果向量中出现但未被by子句指定的标签则会被忽略;

    • 为了保留上下文信息,使用by子句时需要显式指定其结果中原本出现的job、instance等一类的标签

事实上,各函数工作机制的不同之处也仅在于计算操作本身,PromQL对于它们的执行逻辑相似;

6.3 11个聚合函数

sum( ):对样本值求和;

avg ( ) :对样本值求平均值,这是进行指标数据分析的标准方法;

count ( ) :对分组内的时间序列进行数量统计;

stddev ( ) :对样本值求标准差,以帮助用户了解数据的波动大小(或称之为波动程度);

stdvar ( ) :对样本值求方差,它是求取标准差过程中的中间状态;

min ( ) :求取样本值中的最小者;

max ( ) :求取样本值中的最大者;

topk ( ) :逆序返回分组内的样本值最大的前k个时间序列及其值;

bottomk ( ) :顺序返回分组内的样本值最小的前k个时间序列及其值;

quantile ( ) :分位数用于评估数据的分布状态,该函数会返回分组内指定的分位数的值,即数值落在小于等于指定的分位区间的比例;

count_values ( ) :对分组内的时间序列的样本值进行数量统计;

6.4 二元运算符(Binary Operators)

PromQL 支持基本的算术运算和逻辑运算,这类运算支持使用操作符连接两个操作数,因而也称为二元运算符或二元操作符;

  • 支持的运算
    • 两个标量间运算;

    • 即时向量和标量间的运算:将运算符应用于向量上的每个样本;

    • 两个即时向量间的运算:遵循向量匹配机制;

  • 将运算符用于两个即时向量间的运算时,可基于向量匹配模式(Vector Matching)定义其运算机制;

算术运算
– 支持的运算符:+(加)、-(减)、*(乘)、/(除)、%(取模)和^(幂运算);

比较运算
– 支持的运算符:(等值比较)、!=(不等)、>、<、>=和<=(小于等于);

逻辑/集合运算

  • 支持的运算符:and(并且)、or(或者)和unless(除了);

  • 目前,该运算仅允许在两个即时向量间进行,尚不支持标量参与运算;

6.5 二元运算符优先级

Prometheus 的复杂运算中,二元运算符存在如下给定次序中所示的由高到低的优先级

  • ^

  • *, /, %

  • +, –

  • , !=, <=, <, >=, >

  • and, unless

  • or

具有相同优先级的运算符满足结合律(左结合),但幂运算除外,因为它是右结合机制;

可以使用括号( )改变运算次序;

6.6 向量匹配

即时向量间的运算是PromQL的特色之一;运算时,PromQL为会左侧向量中的每个元素找到匹配的元素,其匹配行为有两种基本类型

一对一 (One-to-One)

一对多或多对一 (Many-to-One, One-to-Many)

6.6.1 向量一对一匹配

即时向量的一对一匹配

  • 从运算符的两边表达式所获取的即时向量间依次比较,并找到唯一匹配(标签完全一致)的样本值;

  • 找不到匹配项的值则不会出现在结果中;

匹配表达式语法

<vector expr> <bin-op> ignoring(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) <vector expr>

ignore:定义匹配检测时要忽略的标签;
on:定义匹配检测时只使用的标签;

例如

rate(http_requests_total{status_code=~"5.*"}[5m]) > .1 * rate(http_requests_total[5m])

左侧会生成一个即时向量,它计算出5xx响应码的各类请求的增长速率;

  • 除了status_code标签外,该指标通常还有其它标签;于是,status_code的值为500的标签同其它标签的每个组合将代表一个时间序列,其相应的即时样本即为结果向量的一个元素;

右侧会生成一个即时向量,它计算出所有标签组合所代表的各类请求的增长速率;

计算时,PromQL会在操作符左右两侧的结果元素中找到标签完全一致的元素进行比较;

其意义为,计算出每类请求中的500响应码在该类请求中所占的比例;

示例

Example input

method_code:http_errors:rate5m{method="get", code="500"} 24
method_code:http_errors:rate5m{method="get", code="404"} 30
method_code:http_errors:rate5m{method="put", code="501"} 3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"} 600
method:http_requests:rate5m{method="del"} 34
method:http_requests:rate5m{method="post"} 120

Example query

method_code:http_errors:rate5m{method="get", code="500"} / ignoring(code) method:http_requests:rate5m

This returns a result vector containing the fraction of HTTP requests with status code of 500 for each method, as measured over the last 5 minutes Without ignoring(code)there would have been no match as the metrics donot share the same set of labels. The entries with methods put and del have no match and will not show up inthe result:

{method="get"}  0.04          // 24 / 600
{method="post"} 0.05          //  6 / 120

6.7 向量一对多/多对一匹配

一对多/多对一匹配

  • “一”侧的每个元素,可与“多”侧的多个元素进行匹配;

  • 必须使用group_left或group_right明确指定哪侧为“多”侧;

匹配表达式语法

<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>

示例

Example query

method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m

In this case the left vector contains more than one entry per method label value . Thus , we indicate this usinggroup _ left . The elements from the right side are now matched with multiple elements with the same methodlabel on the left :

{method="get", code="500"}  0.04          // 24 / 600
{method="get", code="404"}  0.05          // 30 / 600
{method="post", code="500"} 0.05          //  6 / 120
{method="post", code="404"} 0.175         // 21 / 120

Many-to-one and one-to-many matching are advanced use cases that should be carefully considered . Often aproper use of ignoring ( < labels ) provides the desired outcome

七、服务发现

7.1 Agenda

Prometheus指标抓取的生命周期

  • 发现 -> 配置 -> relabel -> 指标数据抓取 -> metrics relabel

Prometheus的服务发现

  • 基于文件的服务发现;

  • 基于DNS的服务发现;

  • 基于API的服务发现:Kubernetes、Consul、Azure、……

重新标记

  • target重新打标

  • metric重新打标

7.2 Prometheus 为何要进行服务发现?

Prometheus Server的数据抓取工作于Pull模型,因而,它必需要事先知道各Target的位置,然后才能从相应的Exporter或Instrumentation中抓取数据

  • 对于小型的系统环境来说,通过static_configs指定各Target便能解决问题,这也是最简单的配置方法;
    • 每个Targets用一个网络端点(ip:port)进行标识;
  • 对于中大型的系统环境或具有较强动态性的云计算环境来说,静态配置显然难以适用;

  • 因此,Prometheus为此专门设计了一组服务发现机制,以便于能够基于服务注册中心(服务总线)自动发现、检测、分类可被监控的各Target,以及更新发生了变动的Target;

7.3 指标抓取的生命周期

下图展示了Prometheus上进行指标抓取的简单生命周期

  • 在每个scrape_interval期间,Prometheus都会检查执行的作业(Job);

  • 这些作业首先会根据Job上指定的发现配置生成target列表,此即服务发现过程;

    • 服务发现会返回一个Target列表,其中包含一组称为元数据的标签,这些标签都以“__meta_”为前缀;

    • 服务发现还会根据目标配置来设置其它标签,这些标签带有__前缀和后缀,包括__scheme____address__和__metrics_path__,分别保存有target支持使用协议(http或https,默认为http)、target的地址及指标的URI路径(默认为/metrics);

    • 若URI路径中存在任何参数,则它们的前缀会设置为__param__

    • 这些目标列表和标签会返回给Prometheus,其中的一些标签也可以配置中被覆盖;

配置标签会在抓取的生命周期中被重复利用以生成其他标签,例如,指标上的instance标签的默认值就来自于__address__标签的值;

对于发现的各目标,Prometheus提供了可以重新标记(relabel) 目标的机会

  • 它定义在job配置段的relabel_config配置中,常用于实现如下功能
    • 将来自服务发现的元数据标签中的信息附加到指标的标签上;

    • 过滤目标;

这之后,便是数据抓取、以及指标返回的过程;

抓取而来的指标在保存之前,还允许用户对指标重新打标并过滤的方式;

  • 它定义在job配置段的metric_relabel_configs配置中,常用于实现如下功能
    • 删除不必要的指标;

    • 从指标中删除敏感或不需要的标签;

    • 添加、编辑或修改指标的标签值或标签格式;

未完待续 …

查询持久化及可视化

Alertmanager与告警规则

Prometheus Server高可用

Alertmanager高可用

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇