2024-10-24
技术分享
00

目录

prometheus概述
安装Prometheus
直接安装
docker安装
使用grafana展示
Prometheus相关概念
样本
指标(Metric)
Counter: 只增不减的计数器
Gauge: 可增可减的仪表盘
使用HIstogram(直方图)和Summary(摘要)分析数据分布情况
job(任务)和instances(实例)
什么是Exporter
Exporter的来源,主要分为两类
Exporter类型,通常可以分为两类
Exporter规范
监控Linux服务器
监控nginx
监控Redis
监控rabbitmq
监控mongodb
监控docker
监控mysql
监控springboot
系统进程监控
黑盒监控
域名监控
监控总结
pushgateway
基于文件的服务发现
基于Consul的服务发现
Relabeling机制
PromQL基础使用
时间序列过滤器
PromQL二元运算符
算术二元运算符
集合运算符
基于时间聚合
向量匹配
PromQL内置函数
prometheus告警
Alertmanager配置
163邮箱告警

prometheus概述

一、prometheus介绍

Prometheus是一个开源系统监控和警报工具包,受启发于Google的Brogmon监控系统(相似的Kubernetes是从Google的Brog系统演变而来),从2012年开始由前Google工程师在Soundcloud以开源软件的形式进行研发,并且于2015年早期对外发布早期版本。2016年5月继Kubernetes之后成为第二个正式加入CNCF基金会的项目,同年6月正式发布1.0版本。2017年底发布了基于全新存储层的2.0版本。能更好地与容器平台、云平台配合

二、prometheus特点:

  • 支持多维数据横型由指标名称和键值对标识的时间序列数据
  • 内置时间序列库TSDB(Time Series Database)
  • 支持PromQL(Promethues Query Language),对数据的查询和分析、图形展示和监控告告警
  • 不依赖分布式存储;单个服务器节点是自治的
  • 支持HTTP的拉取(pull)方式收集时间序列数据
  • 通过中间网关Pushgateway推送时间序列
  • 通过服务发现或静态配置2种方式发现目标
  • 支持多种可视化和仪表盘,如:grafana

三、核心组件

  • Prometheus Server: 主要用于抓取数据和存储时序数据,另外还提供查询和AlertRule配置管理。
  • client libraries: 用于检测应用程序代码的客户端库。
  • push gateway: 用于批量,短期的监控数据的汇总节点,主要用于业务数据汇报等。
  • exporters: 收集监控样本数据,并以标准格式向Prometheus提供。例如:收集服务器系统数据的 node_exporter,收集MySQL监控样本数据的是 MySQL exporter 等等。
  • alertmanager: 用于告警通知管理的。

四、基础架构

image-20240808170538168

从这个架构图,也可以看出Prometheus的主要模块包含,Server,Exporters,Pushgateway,PromQL,Alertmanager,WebUl等。 它大致使用逻辑是这样:

  1. Prometheus server 定期从静态配置的 targets 或者服务发现的 targets 拉取数据(Targets是 Prometheus 采集 Agent 需要抓取的采集目标)。
  2. 当新拉取的数据大于配置内存缓存区的时候,Prometheus 会将数据持久化到磁盘(如果使用 remote storage 将持久化到云端)。
  3. Prometheus 可以配置 rules,然后定时查询数据,当条件触发的时候,会将 alerts 推送到配置的 Alertmanager。
  4. Alertmanager 收到警告的时候,可以根据配置(163,钉钉等),聚合,去重,降噪,最后发送警告。
  5. 可以使用API,Prometheus Console 或者 Grafana 查询和聚合数据。

五、Prometheus 与 Zabbix 的对比

ZabbixPrometheus
后端用C开发,界面用PHP开发,定制化难度很高后端用 golang 开发,前端是 Grafana,JSON 编辑即可解决定制化难度较低
6.0支持单个Zabbix实例监控超过10万个业务服务支持更大的集群规模,速度也更快
更适合监控物理机环境(物理主机,交换机,网络等监控)更适合云环境的监控,对 OpenStack, Kubernetes 有更好的集成
监控数据存储在关系型数据库内,如 MySQL,很难从现有数据中扩展维度监控数据存储在基于时间序列的数据库内,便于对已有数据进行新的聚合。十万级监控数据,Prometheus 数据查询速率比 Zabbix 更快
安装简单,zabbix-server 一个软件包中包含了所有的服务端功能安装相对复杂,监控、告警和界面都分属于不同的组件
图形化界面比较成熟,界面上基本能完成全部的配置操作界面相对较弱,很多配置需要修改配置文件
发展时间更长,对于很多监控场景,都有线程的解决方案2015年后开始快速发展,发展时间短,但现在也非常的成熟

安装Prometheus

直接安装

安装Prometheus

官网下载地址

bash
# 下载二进制包 wget https://github.com/prometheus/prometheus/releases/download/v2.53.1/prometheus-2.53.1.linux-amd64.tar.gz # 解压解锁包 tar -xf prometheus-2.53.1.linux-amd64.tar.gz # 移动解压后的文件到 /data/prometheus/ 目录,并改名 prometheus mv prometheus-2.53.1.linux-amd64 /data/prometheus/prometheus

创建一个 prometheus 用户:

bash
useradd -M -s /usr/sbin/nologin prometheus

更改 prometheus 用户的文件夹权限:

bash
chown prometheus:prometheus -R /data/prometheus/prometheus

创建 systemd 服务:

bash
cat > /etc/systemd/system/prometheus.service << "EOF" [Unit] Description=Prometheus Server Documentation=https://prometheus.io/docs/introduction/overview/ After=network.target [Service] Type=simple User=prometheus Group=prometheus Restart=on-failure ExecStart=/data/prometheus/prometheus/prometheus \\ --config.file=/data/prometheus/prometheus/prometheus.yml \\ --storage.tsdb.path=/data/prometheus/prometheus/data \\ --storage.tsdb.retention.time=60d \\ --web.enable-lifecycle [Install] WantedBy=multi-user.target EOF

启动prometheus

bash
systemctl start prometheus

查看状态

bash
systemctl status prometheus

访问地址

应用访问地址备注
Prometheushttp://192.168.1.199:9090/无用户名密码
监控指标http://192.168.1.199:9090/metrics

安装alertmanager

bash
# 下载alertmanager wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz # 解压解锁包 tar -xf alertmanager-0.27.0.linux-amd64.tar.gz # 移动解压后的文件到 /data/prometheus/ 目录,并改名 alertmanager mv alertmanager-0.27.0.linux-amd64 /data/prometheus/alertmanager # 更改权限 chown prometheus:prometheus -R /data/prometheus/alertmanager/

创建systemd服务:

bash
cat > /etc/systemd/system/alertmanager.service << "EOF" [Unit] Description=Alert Manager Wants=network.target After=network.target [Service] Type=simple User=prometheus Group=prometheus Restart=always ExecStart=/data/prometheus/alertmanager/alertmanager \\ --config.file=/data/prometheus/alertmanager/alertmanager.yml \\ --storage.path=/data/prometheus/alertmanager/data [Install] WantedBy=multi-user.target EOF

启动alertmanager

bash
systemctl start alertmanager

查看状态

bash
systemctl status alertmanager

访问地址:

应用访问地址
alertmanagerhttp://192.168.1.199:9093/

修改Prometheus配置

加入alertmanager

yaml
vim /data/prometheus/prometheus/prometheus.yml alerting: alertmanagers: - static_configs: - targets: - localhost:9093 rule_files: - "alert.yml"

增加触发器配置文件

yaml
cat > /data/prometheus/prometheus/alert.yml << "EOF" groups: - name: Prometheus alert rules: # 对任何实例超过30s无法联系的情况发出警报 - alert: 服务告警 expr: up == 0 for: 30s labels: severity: critical annotations: instance: "{{ $labels.instance }}" description: "{{ $labels.job }} 服务已关闭" EOF

检查配置

bash
cd /data/prometheus/prometheus/ ./promtool check config prometheus.yml

重启Prometheus或重新加载配置(二选一)

bash
# 重启 systemctl restart prometheus # 重载配置,需要 --web.enable-lifecycle 配置 curl -X POST http://localhost:9090/-/reload

安装grafana

官网下载地址

二进制安装:

bash
# 下载 wget https://dl.grafana.com/enterprise/release/grafana-enterprise-11.1.3.linux-amd64.tar.gz # 解压 tar -zxvf grafana-enterprise-11.1.3.linux-amd64.tar.gz # 移动解压后的文件到 /data/prometheus/ 目录,并改名 grafana mv grafana-v11.1.3/ /data/prometheus/grafana # 更改权限 chown prometheus:prometheus -R /data/prometheus/grafana

创建systemd服务:

bash
cat > /etc/systemd/system/grafana.service << "EOF" [Unit] Description=Grafana server Documentation=http://grafana.com/docs/ [Service] Type=simple User=prometheus Group=prometheus Restart=on-failure ExecStart=/data/prometheus/grafana/bin/grafana-server \\ --config=/data/prometheus/grafana/conf/defaults.ini \\ --homepath=/data/prometheus/grafana [Install] WantedBy=multi-user.target EOF

启动grafana

bash
systemctl start grafana

查看状态

bash
systemctl status grafana

访问地址:

应用访问地址账号密码
grafanahttp://192.168.1.199:3000/adminadmin

安装node_exporter

官网下载地址

bash
# 下载 wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz # 解压 tar -xf node_exporter-1.8.2.linux-amd64.tar.gz # 移动到 /data/prometheus/ 目录 mv node_exporter-1.8.2.linux-amd64 /data/prometheus/node_exporter # 更改权限 chown prometheus:prometheus -R /data/prometheus/node_exporter

创建systemd服务:

bash
cat > /etc/systemd/system/node_exporter.service << "EOF" [Unit] Description=node_exporter Documentation=https://prometheus.io/ After=network.target [Service] User=prometheus Group=prometheus Restart=on-failure ExecStart=/data/prometheus/node_exporter/node_exporter [Install] WantedBy=multi-user.target EOF

启动服务

bash
systemctl start node_exporter

查看服务状态

bash
systemctl status node_exporter

访问地址:

应用访问地址
node_exporterhttp://192.168.1.199:9100/metrics

修改配置

yaml
cat >> /data/prometheus/prometheus/prometheus.yml << "EOF" # 在prometheus.yml配置文件追加如下配置: # node_exporter配置 - job_name: 'node_exporter' scrape_interval: 15s static_configs: - targets: ['localhost:9100'] labels: instance: Prometheus服务器 EOF

重载配置

bash
curl -X POST http://localhost:9090/-/reload

docker安装

创建prometheus监控文件夹

bash
mkdir -p /data/docker/docker-prometheus/{grafana,prometheus,alertmanager} cd /data/docker/docker-prometheus/

创建 alertmanager配置文件

yaml
cat > alertmanager/config.yml << "EOF" global: #163服务器 smtp_smarthost: 'smtp.163.com:465' #发邮件的邮箱 smtp_from: '[email protected]' #发邮件的邮箱用户名,也就是你的邮箱      smtp_auth_username: '[email protected]' #发邮件的邮箱密码 smtp_auth_password: 'your-password' #进行tls验证 smtp_require_tls: false route: group_by: ['alertname'] # 当收到告警的时候,等待group_wait配置的时间,看是否还有告警,如果有就一起发出去 group_wait: 10s # 如果上次告警信息发送成功,此时又来了一个新的告警数据,则需要等待group_interval配置的时间才可以发送出去 group_interval: 10s # 如果上次告警信息发送成功,且问题没有解决,则等待 repeat_interval配置的时间再次发送告警数据 repeat_interval: 10m # 全局报警组,这个参数是必选的 receiver: email receivers: - name: 'email' #收邮件的邮箱 email_configs: - to: '[email protected]' inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance'] EOF

创建grafana配置配置文件,GF_SECURITY_ADMIN_PASSWORD为grafana超级管理员的密码

bash
cat > grafana/config.monitoring << EOF GF_SECURITY_ADMIN_PASSWORD=admin GF_USERS_ALLOW_SIGN_UP=false EOF

创建prometheus配置文件

yaml
cat > prometheus/prometheus.yml << "EOF" # 全局配置 global: scrape_interval: 15s # 将搜刮间隔设置为每15秒一次。默认是每1分钟一次。 evaluation_interval: 15s # 每15秒评估一次规则。默认是每1分钟一次。 # Alertmanager 配置 alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] # 报警(触发器)配置 rule_files: - "alert.yml" # 搜刮配置 scrape_configs: - job_name: 'prometheus' # 覆盖全局默认值,每15秒从该作业中刮取一次目标 scrape_interval: 15s static_configs: - targets: ['localhost:9090'] - job_name: 'alertmanager' scrape_interval: 15s static_configs: - targets: ['alertmanager:9093'] - job_name: 'cadvisor' scrape_interval: 15s static_configs: - targets: ['cadvisor:8080'] labels: instance: Prometheus服务器 - job_name: 'node-exporter' scrape_interval: 15s static_configs: - targets: ['node_exporter:9100'] labels: instance: Prometheus服务器 EOF

创建alert报警文件

yaml
cat > prometheus/alert.yml << "EOF" groups: - name: Prometheus alert rules: # 对任何实例超过30秒无法联系的情况发出警报 - alert: 服务告警 expr: up == 0 for: 30s labels: severity: critical annotations: summary: "服务异常,实例:{{ $labels.instance }}" description: "{{ $labels.job }} 服务已关闭" EOF

新建 docker-compose.yml文件

yaml
# 通过cat创建docker-compose.yml cat > docker-compose.yml << "EOF" version: '3.3' volumes: prometheus_data: {} grafana_data: {} networks: monitoring: driver: bridge services: prometheus: image: prom/prometheus:v2.37.6 container_name: prometheus restart: always volumes: - /etc/localtime:/etc/localtime:ro - ./prometheus/:/etc/prometheus/ - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/usr/share/prometheus/console_libraries' - '--web.console.templates=/usr/share/prometheus/consoles' #热加载配置 - '--web.enable-lifecycle' #api配置 #- '--web.enable-admin-api' #历史数据最大保留时间,默认15天 - '--storage.tsdb.retention.time=30d' networks: - monitoring links: - alertmanager - cadvisor - node_exporter expose: - '9090' ports: - 9090:9090 depends_on: - cadvisor alertmanager: image: prom/alertmanager:v0.25.0 container_name: alertmanager restart: always volumes: - /etc/localtime:/etc/localtime:ro - ./alertmanager/:/etc/alertmanager/ command: - '--config.file=/etc/alertmanager/config.yml' - '--storage.path=/alertmanager' networks: - monitoring expose: - '9093' ports: - 9093:9093 cadvisor: image: google/cadvisor:latest container_name: cadvisor restart: always volumes: - /etc/localtime:/etc/localtime:ro - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro networks: - monitoring expose: - '8080' node_exporter: image: prom/node-exporter:v1.5.0 container_name: node-exporter restart: always volumes: - /etc/localtime:/etc/localtime:ro - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc|rootfs/var/lib/docker)($$|/)' networks: - monitoring ports: - '9100:9100' grafana: image: grafana/grafana:9.4.3 container_name: grafana restart: always volumes: - /etc/localtime:/etc/localtime:ro - grafana_data:/var/lib/grafana - ./grafana/provisioning/:/etc/grafana/provisioning/ env_file: - ./grafana/config.monitoring networks: - monitoring links: - prometheus ports: - 3000:3000 depends_on: - prometheus EOF

web访问地址

应用访问地址用户名/密码
Prometheushttp://192.168.1.199:9090/无用户和密码
granfanahttp://192.168.1.199:3000/admin/admin
alertmanagerhttp://192.168.1.199:9093/无用户和密码
node-exporterhttp://192.168.1.199:9100/metrics无用户和密码

使用grafana展示

登录grafana

应用访问地址用户名密码
grafanahttp://192.168.1.199:3000/adminadmin

创建prometheus数据源

  1. 进入grafana面板后,点击 Connections
  2. 点击 Data sources
  3. 点击 Add new data source
  4. 选择 prometheus 的数据源
  5. 设置 Prometheus 服务器 URL
  6. 单机 Save & test ,就配置好数据源了

创建仪表盘

  1. 点击这里 从 grafana 官网导入仪表盘,搜索 Node Exporter(如果不想导入,也可以手动创建)
  2. 找到合适的面盘,点击进去,拷贝面板id
  3. 在grafana面板 Dashboards 下点击 import ,输入刚才拷贝好的id

Prometheus相关概念

理解时间序列

安装好Prometheus后会暴漏一个 metrics 的HTTP服务(相当于安装了prometheus_exporter),通过配置(默认会加上/metrics),Prometheus就可以采集到这个 metrics 里面所有监控样本数据。

样本

Prometheus 会将所有采集到的监控样本数据以时间序列的方式保存在内存数据库中,并且定时保存到硬盘上。时间序列是按照时间戳和值的序列顺序存放的,我们称之为向量(vector),每条时间序列通过指标名称(metrics name)和一组标签集(label)命名。如下所示,可以将时间序列理解为一个以时间为X轴的数字矩阵:

bash
^ | · · · · · · · · · · · · process_open_fds | · · · · · · · · · · · · node_cpu_seconds_total{cpu="cpu0",mode="system"} | · · · · · · · · · · · · node_load1{} | · · · · · · · · · · · · v <----------------- 时间 ----------------->

在时间序列中的每一个点称为一个样本(sample),样本由以下三部分组成:

  • 指标(metric): 指标名和描述当前样本特征的标签集合
  • 时间戳(timestamp): 一个精确到毫秒的时间戳
  • 样本值(value): 一个 float64 的浮点型数据表示当前样本的值

如下所示:

bash
<-------------------------- metric --------------------------><- timestamp -><-value-> process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 39 process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 33 process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 35 process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 37 process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 36 process_open_fds{instance="localhost:9090", job="prometheus"} @1723454643619 25 <--metric_name--><------------------lable------------------> <--metric_name--><--name--><----value----> <name><--value-->

指标(Metric)

在形式上,所有的指标(Metric)都通过如下格式表示:

bash
<metric name>{<label name>=<label value>, ...}

指标的名称(metric name)可以反映被监控样本的含义(比如,process_open_fds: 表示当前系统打开的文件描述符)。指标名称只能由ASCII字符、数字、下划线以及冒号组成并必须符合正则表达式 [a-zA-Z_:][a-zA-Z0-9_:]*

标签(label)反映了当前样本的特征维度,通过这些维度Prometheus可以对样本数据进行过滤,聚合等。标签的名称只能由ASCII字符、数字以及下划线组成并满足正则表达式 [a-zA-Z_][a-zA-Z0-9_]*

其中以 _ 作为前缀的标签,是系统保留的关键字,只能在系统内部使用。标签的值则可以包含任何Unicode编码的字符。在Prometheus的底层实现中指标名称实际上是以 _name__=<metric name> 的形式保存在数据库中的,因此以下两种方式均表示的同一条time-series:

bash
process_open_fds{instance="localhost:9090", job="prometheus"}

等同于:

bash
{__name__="process_open_fds", instance="localhost:9090", job="prometheus"}

指标(Metric)的4种类型

Prometheus 底层存储上其实并没有对指标做类型的区分,都是以时间序列的形式存储,但是为了方便用户的使用和理解不同监控指标之间的差异,Prometheus 定义了 counter(计数器)、gauge(仪表盘)、histogram(直方图)以及summary(摘要)这四种 Metrics 类型。

Gauge/counter是数值指标,代表数据的变化情况,Histogram/summary是统计类型的指标,表示数据的分布情况

在Exporter返回的样本数据中,其注释中也包含了该样本的类型。例如:

bash
# HELP process_resident_memory_bytes Resident memory size in bytes. # TYPE process_resident_memory_bytes gauge process_resident_memory_bytes 9.2274688e+07

Counter: 只增不减的计数器

Counter类型的指标其工作方式和计数器一样,只增不减(除非系统发生重置)。常见的监控指标,如 http_requests_total,node_cpu 都是Counter类型的监控指标。一般在定义Counter类型指标的名称时推荐使用 _total 作为后缀

通过Counter指标可以统计HTTP请求数量,请求错误数,接口调用次数等单调递增的数据,同时可结合 increaserate 等函数统计变化速率

例如,通过PromQL内置的聚合rate0函数获取HTTP请求量的评价增长率:

bash
rate(prometheus_http_requests_total[5m])

查询当前系统中,访问量前10的HTTP地址:

bash
topk(10, prometheus_http_requests_total)

Gauge: 可增可减的仪表盘

与Counter不同Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如: node_memory_MemFree_bytes (主机当前空闲的物理内存大小)、 node_memory_MemAvailable_bytes (可用内存大小)都是Gauge类型的监控指标。

通过Gauge指标,通过PromQL可以直接查看系统的当前空闲物理内存大小:

bash
node_memory_MemFree_bytes

对于Gauge类型的监控指标,通过PromQL内置函数 delta() 可以获取样本在一段时间内返回的变化情况。例如,计算CPU温度在两个小时内的差异:

bash
delta(cpu_temp_celsius{host="zeus"}[2h])

还可以使用 deriv() 计算样本的线性回归模式,甚至是直接使用 predict_linear() 对数据的变化趋势进行预测。例如,预测系统磁盘空间在4小时之后的剩余情况:

bash
predict_linear(node_filesystem_avail_bytes{}[1h], 4 * 3600)

使用HIstogram(直方图)和Summary(摘要)分析数据分布情况

除了Counter和Gauge类型的监控指标以外,Prometheus还定义了Histogram和Summary的指标类型。Histogram和summary主用用于统计和分析样本的分布情况。

在大多数情况下人们都倾向于使用某些量化指标的平均值,例如CPU的平均使用率、页面的平均响应时间。这种方式的问题很明显,以系统API调用的平均响应时间为例:如果大多数API请求都维持在100ms的响应时间范围内,而个别请求的响应时间需要5s,那么就会导致某些WEB页面的响应时间落到中位数的情况,而这种现象被称为长尾问题。

为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。例如,统计延迟在010ms之间的请求数有多少,而1020ms之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram和Summary都是为了能够解决这样问题的存在,通过Histogram和Summary类型的监控指标,我们可以快速了解监控样本的分布情况。

例如,指标 prometheus_tsdb_wal_fsync_duration_seconds 的指标类型为Summary。它记录了 Prometheus Server 中 wal_fsync 处理的处理时间,通过访问 Prometheus Server 的 /metrics 地址,可以获取到以下监控样本数据:

# HELP prometheus_tsdb_wal_fsync_duration_seconds Duration of WAL fsync. # TYPE prometheus_tsdb_wal_fsync_duration_seconds summary prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458055 prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173 prometheus_tsdb_wal_fsync_duration_seconds_sum 2.859716124000056 prometheus_tsdb_wal_fsync_duration_seconds_count 216

从上面的样本中可以得知当前 Prometheus Server 进行 wal_fsync 操作的总次数为216次,耗时 2.859716124000056s。其中中位数(quantile="0.5")的耗时为0.012352463,9分位数(quantile="0.9")的耗时为0.014458055s。

在 Prometheus Server 自身返回的样本数据中,我们还能找到类型为Histogram的监控指标

bash
# HELP prometheus_tsdb_compaction_chunk_range_seconds Final time range of chunks on their first compaction # TYPE prometheus_tsdb_compaction_chunk_range_seconds histogram prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="100"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="400"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="1600"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="6400"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="25600"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="102400"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="409600"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="1.6384e+06"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="6.5536e+06"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="2.62144e+07"} 0 prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="+Inf"} 0 prometheus_tsdb_compaction_chunk_range_seconds_sum 0 prometheus_tsdb_compaction_chunk_range_seconds_count 0

与Summary类型的指标相似之处在于Histogram类型的样本同样会反应当前指标的记录的总数(以 _count 作为后缀)及其值的总量(以 _sum 作为后缀)。不同在于Histogram指标直接反应了在不同区间内样本的个数,区间通过标签len进行定义。

同时对于Histogram的指标,我们还可以通过 histogram_quantile() 函数计算出其值的分位数。不同在于Histogram通过histogram_quantile函数是在服务器端计算的分位数。而Sumamry的分位数则是直接在客户端计算完成。因此对于分位数的计算而言,Summary在通过PromQL进行查询时有更好的性能表现,而Histogram则会消耗更多的资源。反之对于客户端而言Histogram消耗的资源更少。在选择这两种方式时用户应该按照自己的实际场景进行选择

需要特别注意的是,假设采样数据 metric 叫做 ×(指标名),如果 ×histogramsummary 类型必需满足以下条件:

  • 采样数据的总和应表示为 x_sum
  • 采样数据的总量应表示为 x_count
  • summary 类型的采样数据的 quantile 应表示为 x{quantile="y"}
  • histogram 类型的采样分区统计数据将表示为 x_bucket{le="y"}
  • histogram 类型的采样必须包含 x_bucket{le="+Inf"} ,它的值等于 x_count 的值。
  • summaryhistoramquantilele 必须按从小到大顺序排序。

job(任务)和instances(实例)

概述: 在Prometheus中,任何被采集的目标,即每一个暴露监控样本数据的HTTP服务都称为一个实例(Instance),例如在当前主机上运行的 node_exporter 可以被称为一个实例(Instance)。而具有相同采集目的的实例集合称为任务(Job)。

job(任务)

例如,以下2个复制实例的node作业:

bash
* job: node * instance 2: 192.168.1.199:9100 * instance 4: 192.168.1.200:9100

instances(实例)

通过在 prometheus.yml 配置文件中,添加如下配置。我们让Prometheus可以从 node exporter 暴露的服务中获取监控指标数据。

bash
scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['prometheus:9090'] - job_name: 'alertmanager' static_configs: - targets: ['alertmanager:9090'] - job_name: 'node-exporter' static_configs: - targets: - node-exporter:9090 - 192.168.1.75:9100

当我们需要采集不同的监控指标(例如:主机、MySQL、Nginx)时,我们只需要运行相应的监控采集程序,在 prometheus server 配置这些 Exporter 实例的访问地址。

实例的状态

除了通过使用“up”表达式查询当前所有 Instance 的状态外,还可以通过 Prometheus UI 中的 Targets 页面查看当前所有的监控采集任务,以及各个任务下所有实例的状态。

什么是Exporter

概述:所有可以向 Prometheus 提供监控样本数据的程序都可以被称为一个 Exporter。而 Exporter 的一个实例成为 target,如下所示,Prometheus 通过轮询的方法定期从这些 target 中获取样本数据:

graph LR
A(Prometheus Server) --> B(Target)
A(Prometheus Server) --> C(Target)
A(Prometheus Server) --> D(Target)

注: 安装好Exporter后会暴露一个 http://ip:port/metrics 的HTTP服务,通过Prometheus添加配置 - targets: ['node_exporter:9100'] (默认会加上 /metrics),Prometheus就可以采集到这个 http://ip:port/metrics 里面所有监控样本数据

Exporter的来源,主要分为两类

社区提供的

社区提供的(https://prometheus.io/docs/instrumenting/exporters/)

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 等
监控系统Colled Exporter, Graphite Exporter, InfluxDB Exporter, Nagios Exporter, SNMP Exporter 等
其他Blockbox Exporter, JIRA Exporter, Jenkins Exporter, Confluence Exporter 等
用户自定义除了直接使用社区提供的Exporter程序以外,用户还可以基于Prometheus提供的Client Library创建自己的Exporter程序

用户自定义的

用户自定义的Exporter程序,目前Prometheus社区官方提供了对以下编程语言的支持: Go、Java/Scala、Python、Ruby。同时还有第三方实现的,例如:Bash、C++、Common Lisp、Erlang、Haskeel、Lua、Node.js、PHP、Rust等。

Exporter类型,通常可以分为两类

  • 直接采集型

这类Exporter直接内置了相应的应用程序,用于向Prometheus直接提供Target数据支持。这样设计的好处是,可以更好地监控各自系统的内部运行状态,同时也适合更多自定义监控指标的项目实施。例如cAdvisor、Kubernetes等,它们均内置了用于向Prometheus提供监控数据的端点。

  • 间接采集型

原始监控目标并不直接支持Prometheus,需要我们使用Prometheus提供的 Client Library 编写该监控目标的监控采集程序,用户可以将该程序独立运行,去获取指定的各类监控数据值。例如,由于Linux操作系统自身并不能直接支持Prometheus,用户无法从操作系统层面上直接提供对Prometheus的支持,因此单独安装Node exporter,还有数据库或网站HTTP应用类等Exporter。

Exporter规范

所有的Exporter程序都需要按照Prometheus的规范,返回监控的样本数据。以 Node Exporter 为例,当访问 http://192.168.1.199:9100/metrics 地址时会返回一下内容:

bash
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 3.7661e-05 go_gc_duration_seconds{quantile="0.25"} 7.0226e-05 go_gc_duration_seconds{quantile="0.5"} 7.6714e-05 go_gc_duration_seconds{quantile="0.75"} 0.000111233 go_gc_duration_seconds{quantile="1"} 0.000640195 go_gc_duration_seconds_sum 0.131039589 go_gc_duration_seconds_count 1215 # HELP go_goroutines Number of goroutines that currently exist. # TYPE go_goroutines gauge go_goroutines 8 # HELP go_info Information about the Go environment. # TYPE go_info gauge go_info{version="go1.19.3"} 1

以#开始的行通常都是注释内容,这些样本数据集合说明如下:

  • #HELP 开始的行,表示metric的帮助与说明注释,可以包含当前监控指标名称和对应的说明信息。
  • #TYPE 开始的行,表示定义metric类型,可以包含当前监控指标名称和类型,类型有Counter、Gauge、HIstogram、Summary和Untyped。
  • 非#开头的行,就是监控样本数据
bash
# HELP <监控指标名称> <监控指标描述> # TYPE <监控指标名称> <监控指标类型> <监控指标名称>{ <标签名称>=<标签值>,<标签名称>=<标签值>...} <样本值1> <时间戳> <监控指标名称>{ <标签名称>=<标签值>,<标签名称>=<标签值>...} <样本值2> <时间戳>

监控样本数据规范

bash
metric_name [ "{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `=` } [","] "}" ] value [ timestamp ]

其中 metric_name 和 label_name 必须遵循 PromQL 的格式规范要求。value是一个float格式的数据,timestamp的类型为int64(从1970-01-0100:00:00以来的毫秒数),timestamp为可选默认为当前时间。具有相同 metric_name 的样本必须按照一个组的形式排列,并且每一行必须是唯一的指标名称和标签键值对组合。

监控Linux服务器

环境介绍

主机名IP地址系统说明
localhost192.168.1.199CentOS Linux release 7.9.2009docker方式安装prometheus
test192.168.1.200CentOS Linux release 7.9.2009docker方式安装node_exporter对服务器监控

环境准备

更换 192.168.1.200 的主机名

bash
hostnamectl set-hostname test

安装docker

bash
# yum-utils 提供了 yum-config-manager yum install -y yum-utils # 配置yum源 yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # 安装docker yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin # 安装docker-compose curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose # 添加执行权限 chmod +x /usr/local/bin/docker-compose

使用docker方式安装 node_exporter

yaml
#创建node_exporter目录 mkdir /data/docker/node_exporter -p # 进入目录 cd /data/docker/node_exporter/ # 以cat方式创建docker-compose.yml文件 cat > docker-compose.yml << "EOF" version: '3.3' services: node_exporter: image: prom/node-exporter:v1.5.0 container_name: node-exporter restart: always volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc|rootfs/var/lib/docker)($$|/)' ports: - '9100:9100' EOF

检查文件

bash
cat docker-compose.yml

运行node_exporter

bash
docker-compose up -d # 检查运行状态 docker ps

二进制安装(二选一)

官网下载地址:https://prometheus.io/download/

bash
# 下载node_exporter wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz # 解压 tar xvf node_exporter-1.5.0.linux-amd64.tar.gz # 移动 mv node_exporter-1.5.0.linux-amd64/node_exporter /usr/local/bin/node_exporter

创建用户

bash
useradd -M -s /usr/sbin/nologin prometheus

创建 systemd 服务

cat > /etc/systemd/system/node_exporter.service << "EOF" [Unit] Description=node_exporter After=network.target [Service] User=prometheus Group=prometheus ExecStart=/usr/local/bin/node_exporter Restart=on-failure [Install] WantedBy=multi-user.target EOF

启动 node_exporter

bash
systemctl daemon-reload systemctl start node_exporter.service # 添加开机自启 systemctl enable node_exporter.service

编辑prometheus配置文件

bash
# 编辑prometheus配置文件 vim /data/docker/docker-prometheus/prometheus/prometheus.yml # 在 - job_name: 'node-exporter' 下添加这台服务器 - targets: ['192.168.1.200:9100'] labels: instance: test服务器 # 修改完配置重载配置 curl -X POST http://localhost:9090/-/reload

web访问地址

应用访问地址
node-exporterhttp://192.168.1.200:9100/metrics

常用的监控指标

cpu采集

bash
node_cpu_seconds_total
名称含义
node_load11分钟内cpu负载
node_load55分钟内cpu负载
node_load1515分钟内cpu负载

内存采集

/proc/meminfo 文件

bash
node_memory_
名称含义备注
node_memory_MemTotal_bytes内存总大小单位字节,/1024/1024=MB,/1024/1024/1024=GB
node_memory_MemAvailable_bytes空闲可使用的内存大小(=free + buffer + cache)
node_memory_MemFree_bytes空闲物理内存大小
node_memory_SwapFree_bytesswap内存空闲大小
node_memory_SwapTotal_bytesswap内存总大小

磁盘采集

bash
node_disk_

文件系统采集

bash
node_filesystem_
名称含义
node_filesystem_avail_bytes空闲磁盘大小,单位字节/1024/1024=MB,/1024/1024/1024=GB
node_filesystem_size_bytes磁盘总大小
node_filesystem_files_free空闲inode大小,单位个
node_filesystem_filesinode总大小,单位个

网络采集

bash
node_network_
名称含义
node_network_transmit_bytes_total网络流出流量,单位字节(Byte)/1024/1024=Mb/s
node_network_receive_bytes_total网络流入流量

触发器设置

yaml
cd /data/docker/docker-prometheus/ cat >> prometheus/alert.yml << "EOF" - name: node-exporter rules: - alert: HostOutOfMemory expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10 for: 2m labels: severity: warning annotations: summary: "主机内存不足,实例:{{ $labels.instance }}" description: "内存可用率<10%,当前值:{{ $value }}" - alert: HostMemoryUnderMemoryPressure expr: rate(node_vmstat_pgmajfault[1m]) > 1000 for: 2m labels: severity: warning annotations: summary: "内存压力不足,实例:{{ $labels.instance }}" description: "节点内存压力大。 重大页面错误率高,当前值为:{{ $value }}" - alert: HostUnusualNetworkThroughputIn expr: sum by (instance) (rate(node_network_receive_bytes_total[2m])) / 1024 / 1024 > 100 for: 5m labels: severity: warning annotations: summary: "异常流入网络吞吐量,实例:{{ $labels.instance }}" description: "网络流入流量 > 100 MB/s,当前值:{{ $value }}" - alert: HostUnusualNetworkThroughputOut expr: sum by (instance) (rate(node_network_transmit_bytes_total[2m])) / 1024 / 1024 > 100 for: 5m labels: severity: warning annotations: summary: "异常流出网络吞吐量,实例:{{ $labels.instance }}" description: "网络流出流量 > 100 MB/s,当前值为:{{ $value }}" - alert: HostUnusualDiskReadRate expr: sum by (instance) (rate(node_disk_read_bytes_total[2m])) / 1024 / 1024 > 50 for: 5m labels: severity: warning annotations: summary: "异常磁盘读取,实例:{{ $labels.instance }}" description: "磁盘读取> 50 MB/s,当前值:{{ $value }}" - alert: HostUnusualDiskWriteRate expr: sum by (instance) (rate(node_disk_written_bytes_total[2m])) / 1024 / 1024 > 50 for: 2m labels: severity: warning annotations: summary: "异常磁盘写入,实例:{{ $labels.instance }}" description: "磁盘写入> 50 MB/s,当前值:{{ $value }}" - alert: HostOutOfDiskSpace expr: (node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes < 10 and ON (instance, device, mountpoint) node_filesystem_readonly == 0 for: 2m labels: severity: warning annotations: summary: "磁盘空间不足告警,实例:{{ $labels.instance }}" description: "剩余磁盘空间< 10% ,当前值:{{ $value }}" - alert: HostDiskWillFillIn24Hours expr: (node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes < 10 and ON (instance, device, mountpoint) predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs"}[1h], 24 * 3600) < 0 and ON (instance, device, mountpoint) node_filesystem_readonly == 0 for: 2m labels: severity: warning annotations: summary: "磁盘空间将在24小时内耗尽,实例:{{ $labels.instance }}" description: "以当前写入速率预计磁盘空间将在 24 小时内耗尽,当前值:{{ $value }}" - alert: HostOutOfInodes expr: node_filesystem_files_free{mountpoint ="/"} / node_filesystem_files{mountpoint="/"} * 100 < 10 and ON (instance, device, mountpoint) node_filesystem_readonly{mountpoint="/"} == 0 for: 2m labels: severity: warning annotations: summary: "磁盘Inodes不足,实例:{{ $labels.instance }}" description: "剩余磁盘 inodes < 10%,当前值: {{ $value }}" - alert: HostUnusualDiskReadLatency expr: rate(node_disk_read_time_seconds_total[1m]) / rate(node_disk_reads_completed_total[1m]) > 0.1 and rate(node_disk_reads_completed_total[1m]) > 0 for: 2m labels: severity: warning annotations: summary: "异常磁盘读取延迟,实例:{{ $labels.instance }}" description: "磁盘读取延迟 > 100ms,当前值:{{ $value }}" - alert: HostUnusualDiskWriteLatency expr: rate(node_disk_write_time_seconds_total[1m]) / rate(node_disk_writes_completed_total[1m]) > 0.1 and rate(node_disk_writes_completed_total[1m]) > 0 for: 2m labels: severity: warning annotations: summary: "异常磁盘写入延迟,实例:{{ $labels.instance }}" description: "磁盘写入延迟 > 100ms,当前值:{{ $value }}" - alert: high_load expr: node_load1 > 4 for: 2m labels: severity: page annotations: summary: "CPU1分钟负载过高,实例:{{ $labels.instance }}" description: "CPU1分钟负载>4,已经持续2分钟。当前值为:{{ $value }}" - alert: HostCpuIsUnderUtilized expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100) > 80 for: 1m labels: severity: warning annotations: summary: "cpu负载高,实例:{{ $labels.instance }}" description: "cpu负载> 80%,当前值:{{ $value }}" - alert: HostCpuStealNoisyNeighbor expr: avg by(instance) (rate(node_cpu_seconds_total{mode="steal"}[5m])) * 100 > 10 for: 0m labels: severity: warning annotations: summary: "CPU窃取率异常,实例:{{ $labels.instance }}" description: "CPU 窃取率 > 10%。 嘈杂的邻居正在扼杀 VM 性能,或者 Spot 实例可能失去信用,当前值:{{ $value }}" - alert: HostSwapIsFillingUp expr: (1 - (node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes)) * 100 > 80 for: 2m labels: severity: warning annotations: summary: "磁盘swap空间使用率异常,实例:{{ $labels.instance }}" description: "磁盘swap空间使用率>80%" - alert: HostNetworkReceiveErrors expr: rate(node_network_receive_errs_total[2m]) / rate(node_network_receive_packets_total[2m]) > 0.01 for: 2m labels: severity: warning annotations: summary: "异常网络接收错误,实例:{{ $labels.instance }}" description: "网卡{{ $labels.device }}在过去2分钟接收{{ $value }}个错误" - alert: HostNetworkTransmitErrors expr: rate(node_network_transmit_errs_total[2m]) / rate(node_network_transmit_packets_total[2m]) > 0.01 for: 2m labels: severity: warning annotations: summary: "异常网络传输错误,实例:{{ $labels.instance }}" description: "网卡{{ $labels.device }}在过去2分钟传输{{ $value }}个错误" - alert: HostNetworkInterfaceSaturated expr: (rate(node_network_receive_bytes_total{device!~"^tap.*"}[1m]) + rate(node_network_transmit_bytes_total{device!~"^tap.*"}[1m])) / node_network_speed_bytes{device!~"^tap.*"} > 0.8 < 10000 for: 1m labels: severity: warning annotations: summary: "异常网络接口饱和,实例:{{ $labels.instance }}" description: "网卡{{ $labels.device }}正在超载,当前值{{ $value }}" - alert: HostConntrackLimit expr: node_nf_conntrack_entries / node_nf_conntrack_entries_limit > 0.8 for: 5m labels: severity: warning annotations: summary: "异常连接数,实例:{{ $labels.instance }}" description: "连接数过大,当前连接数:{{ $value }}" - alert: HostClockSkew expr: (node_timex_offset_seconds > 0.05 and deriv(node_timex_offset_seconds[5m]) >= 0) or (node_timex_offset_seconds < -0.05 and deriv(node_timex_offset_seconds[5m]) <= 0) for: 2m labels: severity: warning annotations: summary: "异常时钟偏差,实例:{{ $labels.instance }}" description: "检测到时钟偏差,时钟不同步。值为:{{ $value }}" - alert: HostClockNotSynchronising expr: min_over_time(node_timex_sync_status[1m]) == 0 and node_timex_maxerror_seconds >= 16 for: 2m labels: severity: warning annotations: summary: "时钟不同步,实例:{{ $labels.instance }}" description: "时钟不同步" - alert: NodeFileDescriptorLimit expr: node_filefd_allocated / node_filefd_maximum * 100 > 80 for: 1m labels: severity: warning annotations: summary: "预计内核将很快耗尽文件描述符限制" description: "{{ $labels.instance }}}已分配的文件描述符数超过了限制的80%,当前值为:{{ $value }}" EOF

检查

bahs
cat prometheus/alert.yml

检查配置:

bash
docker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml

重新加载配置:

bash
curl -X POST http://localhost:9090/-/reload

检查

bash
http://192.168.1.199:9090/alerts

之后就可以在 http://192.168.1.199:3000/ grafana面板查看监控信息了

监控nginx

环境搭建

创建nginx目录

bash
mkdir /data/docker/nginx/conf.d -p cd /data/docker/nginx/conf.d

/data/docker/nginx/conf.d 目录里新增加nginx的配置文件

bash
cat >> server.conf << "EOF" server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } EOF

检查

bash
cat server.conf

docker-compose安装rabbitmq、nginx、mongo、redis

bash
mkdir /data/docker/docker-compose -p cd /data/docker/docker-compose/

通过cat创建docker-compose.yml文件

yaml
cat > docker-compose.yml << "EOF" version: '3' services: redis: image: redis:5 container_name: redis command: redis-server --requirepass 123456 --maxmemory 512mb restart: always volumes: - /data/docker/redis/data:/data ports: - 6379:6379 nginx: image: nginx:1.21.6 container_name: nginx restart: always volumes: - /data/docker/nginx/conf.d:/etc/nginx/conf.d - /data/docker/nginx/html:/usr/share/nginx/html - /data/docker/nginx/log:/var/log/nginx ports: - 80:80 rabbitmq: image: rabbitmq:3.7.15-management container_name: rabbitmq restart: always volumes: - /data/docker/rabbitmq/data:/var/lib/rabbitmq - /data/docker/rabbitmq/log:/var/log/rabbitmq ports: - 5672:5672 - 15672:15672 mongo: image: mongo:4.2.5 container_name: mongo restart: always volumes: - /data/docker/mongo/db:/data/db ports: - 27017:27017 command: [--auth] environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: 123456 EOF

运行

bash
docker-compose up -d

检查

bash
docker ps

监控nginx

nginx开启 stub_status

  • 注: 监控nginx需要with-http_stub_status_module

检查是否安装有with-http_stub_status_module模块

bash
docker exec -it nginx nginx -V 2>&1 | grep -o with-http_stub_status_module with-http_stub_status_module

nginx开启stub_status配置

bash
cd /data/docker/nginx/conf.d vim server.conf
bash
server { .... location /stub_status { stub_status on; access_log off; #allow nginx_export的ip; allow 0.0.0.0/0; deny all; } .... }

检查配置

bash
docker exec -it nginx nginx -t

重新加载配置文件

bash
docker exec -it nginx nginx -s reload

检查

bash
[root@test conf.d]# curl http://192.168.1.200/stub_status Active connections: 1 server accepts handled requests 1 1 1 Reading: 0 Writing: 1 Waiting: 0

参数解释:

  • Active connections: 活动连接数
  • accepts:接收请求数
  • handled: 总请求数
  • reding: 正在进行读操作的请求数
  • writing: 正在进行写操作的请求数
  • waiting: 正在等待的请求数

docker安装nginx_exporter

通过cat创建docker-compose.yml文件

bash
cd /data/docker/nginx/
yaml
cat > docker-compose.yaml << "EOF" version: '3.3' services: nginx_exporter: image: nginx/nginx-prometheus-exporter:0.11 container_name: nginx_exporter hostname: nginx_exporter command: - '-nginx.scrape-uri=http://192.168.1.200/stub_status' restart: always ports: - "9113:9113" EOF

启动

bash
docker-compose up -d

检查

bash
docker ps

参数解释

Environment variable命令行参数description
-nginx.scrape-uringinx stub_status 复制

metrics地址

安装好Exporter后会暴露一个 http://ip:port/metrics 的HTTP服务

名称地址
nginx_exporterhttp://192.168.1.200:9113/metrics

修改prometheus配置

配置prometheus去采集(拉取)nginx_exporter的监控样本数据

yaml
cd /data/docker/docker-prometheus # 在scrape_configs(搜刮配置):下面增加如下配置: cat >> prometheus/prometheus.yml << "EOF" - job_name: 'nginx_exporter' static_configs: - targets: ['192.168.1.200:9113'] labels: instance: test服务器 EOF

重新加载配置

bash
curl -X POST http://localhost:9090/-/reload

常用的监控指标

bash
nginx_connections_accepted 接收请求数 nginx_connections_active 活动连接数 nginx_connections_handled 成功处理请求数 nginx_connections_reding 正在进行读操作的请求数 nginx_connections_waiting 正在等待的请求数 nginx_connections_writing 正在进行写操作的请求数 nginx_connections_requests 总请求数

添加触发器

bash
cd /data/docker/docker-prometheus
yaml
cat >> prometheus/alert.yml << "EOF" - name: nginx rules: # 对任何实例超过30秒无法联系的情况发出警报 - alert: NginxDown expr: nginx_up == 0 for: 30s labels: severity: critical annotations: summary: "nginx异常,实例:{{ $labels.instance }}" description: "{{ $labels.job }} nginx已关闭" EOF

检查配置

bash
docker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml

重新加载配置

bash
curl -X POST http://localhost:9090/-/reload

grafana展示prometheus从nginx_exporter收集到的的数据

https://grafana.com/grafana/dashboards/ 在官网找到合适的nginx仪表盘,点进去拷贝id,在grafana上导入就可以了

监控Redis

docker安装redis_exporter

docker直接运行

bash
docker run -d --restart=always --name redis_exporter -p 9121:9121 oliver006/redis_exporter --redis.addr redis://192.168.1.200:6379 --redis.password '123456'

docker-compose方式

bash
cd /data/docker/redis/redis_exporter
yaml
cat > docker-compose.yaml << EOF version: '3.3' services: redis_exporter: image: oliver006/redis_exporter container_name: redis_exporter restart: always environment: REDIS_ADDR: "192.168.1.200:6379" REDIS_PASSWORD: 123456 ports: - "9121:9121" EOF

启动

bash
docker-compose up -d

检查

bash
docker ps

参数解释

Environment variabledescription
REDIS_ADDR192.168.1.200:6379redis服务器地址,如:ip:6379
REDIS_PASSWORD123456redis服务器管理密码

metrics地址

名称地址备注
redis_exporterhttp://192.168.1.200:9121/metrics

配置prometheus

bash
cd /data/docker/docker-prometheus cat >> prometheus/prometheus.yml << "EOF" - job_name: 'redis_exporter' static_configs: - targets: ['192.168.1.200:9121'] labels: instance: test服务器 EOF

重新加载配置

bash
curl -X POST http://localhost:9090/-/reload

常用的监控指标

bash
redis_up # 服务器是否在线 redis_uptime_in_seconds # 运行时长,单位 s rate(redis_cpu_sys_seconds_total[1m]) + rate(redis_cpu_user_seconds_total[1m]) # 占用 CPU 核数 redis_memory_used_bytes # 占用内存量 redis_memory_max_bytes # 限制的最大内存,如果没限制则为 0 delta(redis_net_input_bytes_total[1m]) # 网络接收的 bytes delta(redis_net_output_bytes_total[1m]) # 网络发送的 bytes redis_connected_clients # 客户端连接数 redis_connected_clients / redis_config_maxclients # 连接数使用率 redis_rejected_connections_total # 拒绝的客户端连接数 redis_connected_slaves # slave 连接数

配置触发器

Prometheus配置

bash
# 报警(触发器)配置 rule_files: - "alert.yml" - "rules/*.yml"

redis触发器(告警规则)

因为是单机,所以未配置集群的触发器

yaml
cat >> prometheus/rules/redis.yml << "EOF" groups: - name: redis rules: - alert: RedisDown expr: redis_up == 0 for: 0m labels: severity: critical annotations: summary: 'Redis Down,实例:{{ $labels.instance }}' description: "Redis实例 is down" - alert: RedisMissingBackup expr: time() - redis_rdb_last_save_timestamp_seconds > 60 * 60 * 24 for: 0m labels: severity: critical annotations: summary: "Redis备份丢失,实例:{{ $labels.instance }}" description: "Redis 24小时未备份" - alert: RedisOutOfConfiguredMaxmemory expr: redis_memory_used_bytes / redis_memory_max_bytes * 100 > 90 for: 2m labels: severity: warning annotations: summary: "Redis超出配置的最大内存,实例:{{ $labels.instance }}" description: "Redis内存使用超过配置最大内存的90%" - alert: RedisTooManyConnections expr: redis_connected_clients > 100 for: 2m labels: severity: warning annotations: summary: "Redis连接数过多,实例:{{ $labels.instance }}" description: "Redis当前连接数为: {{ $value }}" - alert: RedisNotEnoughConnections expr: redis_connected_clients < 1 for: 2m labels: severity: warning annotations: summary: "Redis没有足够的连接,实例:{{ $labels.instance }}" description: "Redis当前连接数为: {{ $value }}" - alert: RedisRejectedConnections expr: increase(redis_rejected_connections_total[1m]) > 0 for: 0m labels: severity: critical annotations: summary: "Redis有拒绝连接,实例:{{ $labels.instance }}" description: "与Redis 的某些连接被拒绝{{ $value }}" EOF

检查配置:

bash
docker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml

重载配置

bash
curl -X POST http://localhost:9090/-/reload

grafana展示prometheus从redis_exporter收集到的的数据

在官网找到合适的模板id,在grafana导入就可以了

监控rabbitmq

docker安装

docker直接安装

bash
docker run -d --restart=always -p 9419:9419 --name rabbitmq_exporter -e RABBIT_URL=http://192.168.1.200:15672 -e RABBIT_USER=guest -e RABBIT_PASSWORD=guest kbudde/rabbitmq-exporter

docker-compose方式

bash
cat > docker-compose.yaml << "EOF" version: '3.3' services: rabbitmq_exporter: image: kbudde/rabbitmq-exporter container_name: rabbitmq_exporter restart: always environment: RABBIT_URL: "http://192.168.1.200:15672" RABBIT_USER: "guest" RABBIT_PASSWORD: "guest" PUBLISH_PORT: "9419" OUTPUT_FORMAT: "JSON" ports: - "9419:9419" EOF

启动

bash
docker-compose up -d

参数解释

Environment variabledefaultdescription
RABBIT_URLhttp://127.0.0.1:15672rabbitMQ管理插件的url(必须以http(s)://开头)
RABBIT_USERguestrabbitMQ 管理插件的用户名。
RABBIT_PASSWORDguestrabbitMQ 管理插件的密码。
OUTPUT_FORMATJSON输出格式
PUBLISH_PORT9419运行端口(监听端口)

metrics地址

名称地址备注
rabbitmq_exporterhttp://192.168.1.200:9419/metrics

Prometheus配置

配置prometheus去采集(拉取)rabbitmq_exporter的监控样本数据

bash
cd /data/docker/docker-prometheus #在scrape_configs(搜刮配置):下面增加如下配置: cat >> prometheus/prometheus.yml << "EOF" - job_name: 'rabbitmq_exporter' static_configs: - targets: ['192.168.1.200:9419'] labels: instance: test服务器 EOF

常用的监控指标

bash
rabbitmq_queue_messages_unacknowledged_global 队列中有未确认的消息总数(未被消费的消息) rabbitmq_node_disk_free_limit 使用磁盘大小 rabbitmq_node_disk_free 磁盘总大小 rabbitmq_node_mem_used 使用内存大小 rabbitmq_node_mem_limit 内存总大小 rabbitmq_sockets_used 使用sockets的数量 rabbitmq_sockets_available 可用的sockets总数 rabbitmq_fd_used 使用文件描述符的数量 rabbitmq_fd_available 可用的文件描述符总数

触发器配置(告警规则)

也是单节点,未配置集群触发器

yaml
cat > prometheus/rules/rabbitmq.yml << "EOF" groups: - name: Rabbitmq rules: - alert: RabbitMQDown expr: rabbitmq_up != 1 labels: severity: High annotations: summary: "Rabbitmq Down,实例:{{ $labels.instance }}" description: "Rabbitmq_exporter连不上RabbitMQ! ! !" - alert: RabbitMQ有未确认消息 expr: rabbitmq_queue_messages_unacknowledged_global > 0 for: 1m labels: severity: critical annotations: summary: "RabbitMQ有未确认消息,实例:{{ $labels.instance }}" description: 'RabbitMQ未确认消息>0,当前值为:{{ $value }}' - alert: RabbitMQ可用磁盘空间不足告警 expr: rabbitmq_node_disk_free_alarm != 0 #expr: rabbitmq_node_disk_free_limit / rabbitmq_node_disk_free *100 > 90 for: 0m labels: severity: critical annotations: summary: "RabbitMQ可用磁盘空间不足,实例:{{ $labels.instance }}" description: "RabbitMQ可用磁盘空间不足,请检查" - alert: RabbitMQ可用内存不足告警 expr: rabbitmq_node_mem_alarm != 0 #expr: rabbitmq_node_mem_used / rabbitmq_node_mem_limit * 100 > 90 for: 0m labels: severity: critical annotations: summary: "RabbitMQ可用内存不足,实例:{{ $labels.instance }}" description: "RabbitMQ可用内存不足,请检查" - alert: RabbitMQ_socket连接数使用过高告警 expr: rabbitmq_sockets_used / rabbitmq_sockets_available * 100 > 60 for: 0m labels: severity: critical annotations: summary: "RabbitMQ_socket连接数使用过高,实例:{{ $labels.instance }}" description: 'RabbitMQ_sockets使用>60%,当前值为:{{ $value }}' - alert: RabbitMQ文件描述符使用过高告警 expr: rabbitmq_fd_used / rabbitmq_fd_available * 100 > 60 for: 0m labels: severity: critical annotations: summary: "RabbitMQ文件描述符使用过高,实例:{{ $labels.instance }}" description: 'RabbitMQ文件描述符使用>60%,当前值为:{{ $value }}' EOF

grafana展示prometheus从rabbitmq_exporter收集到的的数据

在grafana面板导入id就可以了,id: 4279

监控mongodb

创建监控用户

登陆mongodb创建监控用户,权限为“readAnyDatabase”,如果是cluster环境,需要有权限“clusterMonitor”

登录mongodb(docker安装的mongo)

bash
docker exec -it mongo mongo admin

创建监控用户

bash
> db.auth('root','123456') 1 > db.createUser({ user:'exporter',pwd:'password',roles:[ { role:'readAnyDatabase', db: 'admin'},{ role: "clusterMonitor", db: "admin" }]}); #测试 使用上面创建的用户信息进行连接。 > db.auth('exporter', 'password') 1 #表示成功 > exit

docker安装

直接运行

bash
docker run -d --restart=always -p 9216:9216 -p 17001:17001 --restart=always --name=mongodb-exporter bitnami/mongodb-exporter:latest --collect-all --compatible-mode --mongodb.uri=mongodb://exporter:[email protected]:27017/admin?ssl=false

docker-compose方式运行

yaml
cat > docker-compose.yaml << "EOF" version: '3.3' services: mongodb_exporter: image: bitnami/mongodb-exporter:latest container_name: mongodb_exporter restart: always environment: MONGODB_URI: "mongodb://exporter:[email protected]:27017/admin?ssl=false" command: - '--collect-all' - '--compatible-mode' ports: - "9216:9216" EOF

参数解释

Flag含义案例
-h, --help显示上下文相关的帮助
--[no-]compatible-mode启用旧的 mongodb-exporter 兼容指标
--[no-]discovering-mode启用自动发现集合
--mongodb.collstats-colls逗号分隔的 databases.collections 列表以获取 $collStats--mongodb.collstats-colls=db1,db2.col2
--mongodb.indexstats-colls逗号分隔的 databases.collections 列表以获取 $indexStats--mongodb.indexstats-colls=db1.col1,db2.col2
--[no-]mongodb.direct-connect是否应该进行直接连接。如果指定了多个主机或使用了 SRV URI,则直接连接无效
--[no-]mongodb.global-conn-pool使用全局连接池而不是为每个 http 请求创建新池
--mongodb.uriMongoDB 连接 URI ($MONGODB_URI)--mongodb.uri=mongodb://user
@127.0.0.1:27017/admin?ssl=true
--web.listen-address用于侦听 Web 界面和遥测的地址--web.listen-address=":9216"
--web.telemetry-path指标公开路径--web.telemetry-path="/metrics"
--web.config具有用于基本身份验证的 Prometheus TLS 配置的文件的路径--web.config=STRING
--log.level仅记录具有给定严重性或更高严重性的消息。有效级别:[调试、信息、警告、错误、致命]--log.level="error"
--collector.diagnosticdata启用从 getDiagnosticData 收集指标
--collector.replicasetstatus启用从 replSetGetStatus 收集指标
--collector.dbstats启用从 dbStats 收集指标
--collector.topmetrics启用从 top admin command 收集指标
--collector.indexstats启用从 $indexStats 收集指标
--collector.collstats启用从 $collStats 收集指标
--collect-all启用所有收集器。与指定所有 --collector. 相同
--collector.collstats-limit=0如果有超过 个集合,请禁用 collstats、dbstats、topmetrics 和 indexstats 收集器。0=无限制
--metrics.overridedescendingindex启用降序索引名称覆盖以将 -1 替换为 _DESC
--version显示版本并退出

metrics地址

名称地址备注
mongodb_exporterhttp://192.168.1.200:9216/metrics

Prometheus配置

yaml
cd /data/docker/docker-prometheus #在scrape_configs(搜刮配置):下面增加如下配置: cat >> prometheus/prometheus.yml << "EOF" - job_name: 'mongodb_exporter' static_configs: - targets: ['192.168.1.200:9216'] labels: instance: test服务器 EOF

常用的监控指标

bash
mongodb_ss_connections{conn_type="available"} 可用的连接总数 mongodb_ss_mem_virtual mongodb_ss_mem_resident # 关于 server status mongodb_up # 服务器是否在线 mongodb_ss_ok{cl_id="", cl_role="mongod", rs_state="0"} # 服务器是否正常运行,取值为 1、0 。标签中记录了 Cluster、ReplicaSet 的信息 mongodb_ss_uptime # 服务器的运行时长,单位为秒 mongodb_ss_connections{conn_type="current"} # 客户端连接数 # 关于主机 mongodb_sys_cpu_num_cpus # 主机的 CPU 核数 # 关于 collection mongodb_collstats_storageStats_count{database="xx", collection="xx"} # collection 全部文档的数量 mongodb_collstats_storageStats_size # collection 全部文档的体积,单位 bytes mongodb_collstats_storageStats_storageSize # collection 全部文档占用的磁盘空间,默认会压缩 delta(mongodb_collstats_latencyStats_reads_ops[1m]) # collection 读操作的数量(每分钟) delta(mongodb_collstats_latencyStats_reads_latency[1m]) # collection 读操作的延迟(每分钟),单位为微秒 mongodb_collstats_latencyStats_write_ops mongodb_collstats_latencyStats_write_latency # 关于 index mongodb_collstats_storageStats_nindexes # collection 的 index 数量 mongodb_collstats_storageStats_totalIndexSize # collection 的 index 占用的磁盘空间 delta(mongodb_indexstats_accesses_ops[1m]) # index 被访问次数 # 关于操作 delta(mongodb_ss_opcounters[1m]) # 执行各种操作的数量 delta(mongodb_ss_opLatencies_latency[1m]) # 执行各种操作的延迟,单位为微秒 delta(mongodb_ss_metrics_document[1m]) # 各种文档的变化数量 # 关于锁 delta(mongodb_ss_locks_acquireCount{lock_mode="w"}[1m]) # 新加锁的数量。R 表示共享锁,W 表示独占锁,r 表示意向共享锁,w 表示意向独占锁 mongodb_ss_globalLock_currentQueue{count_type="total"} # 被锁阻塞的操作数

mongodb触发器(告警规则)

因mongo单点,所以未配置复制触发器

yaml
cat >> prometheus/rules/mongodb.yml << "EOF" groups: - name: PerconaMongodbExporter rules: - alert: MongodbDown expr: 'mongodb_up == 0' for: 0m labels: severity: critical annotations: summary: "MongoDB Down 容器: $labels.instance" description: "MongoDB 容器 is down, 当前值:{{ $value }}" - alert: MongodbNumberCursorsOpen expr: 'mongodb_ss_metrics_cursor_open{csr_type="total"} > 10 * 1000' for: 2m labels: severity: warning annotations: summary: "MongoDB 数字有标打开告警 容器: $labels.instance" description: "MongoDB 为客户端打开的游标过多 > 10k, 当前值:{{ $value }}" - alert: MongodbCursorsTimeouts expr: 'increase(mongodb_ss_metrics_cursor_timedOut[1m]) > 100' for: 2m labels: severity: warning annotations: summary: "MongoDB 游标超时 容器: $labels.instance" description: "太多游标超时, 当前值:{{ $value }}" - alert: MongodbTooManyConnections expr: 'avg by(instance) (rate(mongodb_ss_connections{conn_type="current"}[1m])) / avg by(instance) (sum (mongodb_ss_connections) by (instance)) * 100 > 80' for: 2m labels: severity: warning annotations: summary: "MongoDB 太多连接 容器: $labels.instance" description: "MongoDB 连接数 > 80%, 当前值:{{ $value }}" - alert: MongodbVirtualMemoryUsage expr: '(sum(mongodb_ss_mem_virtual) BY (instance) / sum(mongodb_ss_mem_resident) BY (instance)) > 3' for: 2m labels: severity: warning annotations: summary: "MongoDB虚拟内存使用告警 容器: $labels.instance" description: "虚拟内存使用过高, 当前值:{{ $value }}" EOF

grafana展示

可以从官网搜索合适的仪表盘,也可以在 https://github.com/percona/grafana-dashboards/tree/main/dashboards/MongoDB ,这里查看合适的仪表,这里选择的是: MongoDB_Instances_Overview.json

监控docker

为了能够获取到Docker容器的运行状态,用户可以通过Docker的stats命令获取到当前主机上运行容器的统计信息,可以查看容器的CPU利用率、内存使用量、网络IO总量以及磁盘IO总量等信息。

bash
docker stats

使用CAdvisor

CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示。

docker命令安装

bash
docker run -d \ --restart=always \ --volume=/:/rootfs:ro \ --volume=/var/run:/var/run:rw \ --volume=/sys:/sys:ro \ --volume=/var/lib/docker/:/var/lib/docker:ro \ --publish=8080:8080 \ --name=cadvisor \ google/cadvisor:latest

Docker-compose安装

yaml
mkdir /data/docker/cadvisor cd /data/docker/cadvisor #通过cat新建docker-compose.yml文件 cat > docker-compose.yml << "EOF" version: '3.3' services: cadvisor: image: google/cadvisor:latest container_name: cadvisor restart: always volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro ports: - 8080:8080 EOF

配置prometheus

yaml
cd /data/docker/docker-prometheus #在scrape_configs(搜刮配置):下面增加如下配置: cat >> prometheus/prometheus.yml << "EOF" - job_name: 'cadvisor' static_configs: - targets: ['192.168.11.62:8080'] labels: instance: test服务器 EOF

常用监控指标

下面表格中列举了一些CAdvisor中获取到的典型监控指标: container_

指标名称类型含义
container_cpu_load_average_10sgauge过去10秒容器CPU的平均负载
container_cpu_usage_seconds_totalcounter容器在每个CPU内核上的累积占用时间 (单位:秒)
container_cpu_system_seconds_totalcounterSystem CPU累积占用时间(单位:秒)
container_cpu_user_seconds_totalcounterUser CPU累积占用时间(单位:秒)
container_fs_usage_bytesgauge容器中文件系统的使用量(单位:字节)
container_fs_limit_bytesgauge容器可以使用的文件系统总量(单位:字节)
container_fs_reads_bytes_totalcounter容器累积读取数据的总量(单位:字节)
container_fs_writes_bytes_totalcounter容器累积写入数据的总量(单位:字节)
container_memory_max_usage_bytesgauge容器的最大内存使用量(单位:字节)
container_memory_usage_bytesgauge容器当前的内存使用量(单位:字节
container_spec_memory_limit_bytesgauge容器的内存使用量限制
machine_memory_bytesgauge当前主机的内存总量
container_network_receive_bytes_totalcounter容器网络累积接收数据总量(单位:字节)
container_network_transmit_bytes_totalcounter容器网络累积传输数据总量(单位:字节)

触发器配置

添加docker触发器(告警规则)

yaml
cat >> prometheus/rules/docker.yml << "EOF" groups: - name: DockerContainers rules: - alert: ContainerKilled expr: time() - container_last_seen > 60 for: 0m labels: severity: warning annotations: isummary: "Docker容器被杀死 容器:{{ $labels.instance }}" description: "{{ $value }}个容器消失了" # This rule can be very noisy in dynamic infra with legitimate container start/stop/deployment. - alert: ContainerAbsent expr: absent(container_last_seen) for: 5m labels: severity: warning annotations: summary: "无容器 容器: {{ $labels.instance }}" description: "5分钟检查容器不存在,值为:{{ $value }}" - alert: ContainerCpuUsage expr: (sum(rate(container_cpu_usage_seconds_total{name!=""}[3m])) BY (instance, name) * 100) > 300 for: 2m labels: severity: warning annotations: summary: "容器cpu使用率告警 容器: {{ $labels.instance }}" description: "容器cpu使用率超过300%,当前值为:{{ $value }}" - alert: ContainerMemoryUsage expr: (sum(container_memory_working_set_bytes{name!=""}) BY (instance, name) / sum(container_spec_memory_limit_bytes > 0) BY (instance, name) * 100) > 80 for: 2m labels: severity: warning annotations: summary: "容器内存使用率告警 容器: {{ $labels.instance }}" description: "容器内存使用率超过80%,当前值为:{{ $value }}" - alert: ContainerVolumeIoUsage expr: (sum(container_fs_io_current{name!=""}) BY (instance, name) * 100) > 80 for: 2m labels: severity: warning annotations: summary: "容器存储io使用率告警 容器: {{ $labels.instance }}" description: "容器存储io使用率超过 80%,当前值为:{{ $value }}" - alert: ContainerHighThrottleRate expr: rate(container_cpu_cfs_throttled_seconds_total[3m]) > 1 for: 2m labels: severity: warning annotations: summary: "容器限制告警 容器:{{ $labels.instance }}" description: "容器被限制,当前值为:{{ $value }}" EOF

grafana展示,id选择: 11600

监控mysql

docker-compose安装

yaml
mkdir /data/docker/mysql cd /data/docker/mysql/

通过cat 创建docker-compose.yml文件

yaml
cat > docker-compose.yaml << "EOF" version: '3.1' services: db: image: mysql:8.0 restart: always container_name: mysql environment: TZ: Asia/Shanghai LANG: en_US.UTF-8 MYSQL_ROOT_PASSWORD: 123456 command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --lower_case_table_names=1 --performance_schema=1 --sql-mode="" --skip-log-bin volumes: #- /data/mysql/conf:/etc/mysql/conf.d #数据文件挂载 - /data/docker/mysql/data:/var/lib/mysql #数据文件挂载 ports: - 3306:3306 EOF

监控mysql

进入容器登录mysql,密码 123456

bash
docker exec -it mysql mysql -uroot -p

创建用户

bash
CREATE USER 'exporter'@'%' IDENTIFIED BY 'password' WITH MAX_USER_CONNECTIONS 3; GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';

docker-compose运行

注:latest版本配置方法改变了,指定v0.14.0版本。如下:

yaml
mkdir /data/docker/mysqld_exporter cd /data/docker/mysqld_exporter cat > docker-compose.yaml << "EOF" version: '3.3' services: mysqld-exporter: image: prom/mysqld-exporter container_name: mysqld-exporter restart: always command: - '--collect.info_schema.processlist' - '--collect.info_schema.innodb_metrics' - '--collect.info_schema.tablestats' - '--collect.info_schema.tables' - '--collect.info_schema.userstats' - '--collect.engine_innodb_status' - '--config.my-cnf=/my.cnf' volumes: - ./my.cnf:/my.cnf ports: - 9104:9104 EOF

创建my.cnf配置文件

bash
cat > my.cnf << "EOF" [client] host=192.168.1.200 user=exporter password=password port=3306 EOF

参数解释

NameMySQL VersionDescription
collect.auto_increment.columns5.1从 information_schema 收集 auto_increment 列和最大值.
collect.binlog_size5.1收集所有注册的binlog文件的当前大小
collect.engine_innodb_status5.1收集SHOW ENGINE INNODB STATUS
collect.engine_tokudb_status5.6收集SHOW ENGINE TOKUDB STATUS .
collect.global_status5.1收集SHOW GLOBAL STATUS(默认启用)
collect.global_variables5.1收集SHOW GLOBAL VARIABLES(默认启用)
collect.info_schema.clientstats5.5如果以 userstat=1 运行,设置为 true 以收集客户端统计信息
collect.info_schema.innodb_metrics5.6从 information_schema.innodb_metrics收集指标
collect.info_schema.innodb_tablespaces5.7从information_schema.innodb_sys_tablespaces收集指标
collect.info_schema.innodb_cmp5.5从information_schema.innodb_cmp收集 InnoDB 压缩表指标。
collect.info_schema.innodb_cmpmem5.5从information_schema.innodb_cmpmem缓冲池压缩指标。
collect.info_schema.processlist5.1从 information_schema.processlist 收集线程状态计数
collect.info_schema.processlist.min_time5.1线程必须处于要计算的每个状态的最短时间。 (默认值:0)
collect.info_schema.query_response_time5.5如果 query_response_time_stats 为 ON,则收集查询响应时间分布。
collect.info_schema.replica_host5.6从 information_schema.replica_host_status 收集指标。
collect.info_schema.tables5.1从information_schema.tables收集指标。
collect.info_schema.tables.databases5.1要为其收集表统计信息的数据库列表,或为所有
collect.info_schema.tablestats5.1如果以 userstat=1 运行,设置为 true 以收集表统计信息。
collect.info_schema.schemastats5.1如果以 userstat=1 运行,设置为 true 以收集架构统计信息
collect.info_schema.userstats5.1如果以 userstat=1 运行,设置为 true 以收集用户统计信息。
collect.mysql.user5.5从 mysql.user 表中收集数据
collect.perf_schema.eventsstatements5.6从 performance_schema.events_statements_summary_by_digest 收集指标。
collect.perf_schema.eventsstatements.digest_text_limit5.6规范化语句文本的最大长度。 (默认值:120)
collect.perf_schema.eventsstatements.limit5.6按响应时间限制事件语句摘要的数量。 (默认值:250)
collect.perf_schema.eventsstatements.timelimit5.6以秒为单位限制“last_seen”事件语句的存在时间。 (默认值:86400)
collect.perf_schema.eventsstatementssum5.7从 performance_schema.events_statements_summary_by_digest 汇总收集指标。
collect.perf_schema.eventswaits5.5从 performance_schema.events_waits_summary_global_by_event_name 收集指标
collect.perf_schema.file_events5.6从 performance_schema.file_summary_by_event_name 收集指标
collect.perf_schema.file_instances5.5从 performance_schema.file_summary_by_instance 收集指标。
collect.perf_schema.file_instances.remove_prefix5.5删除 performance_schema.file_summary_by_instance 中的路径前缀。
collect.perf_schema.indexiowaits5.6从 performance_schema.table_io_waits_summary_by_index_usage 收集指标。
collect.perf_schema.memory_events5.7从 performance_schema.memory_summary_global_by_event_name 收集指标。
collect.perf_schema.memory_events.remove_prefix5.7删除 performance_schema.memory_summary_global_by_event_name 中的仪器前缀。
collect.perf_schema.tableiowaits5.6从 performance_schema.table_io_waits_summary_by_table 收集指标。
collect.perf_schema.tablelocks5.6从 performance_schema.table_lock_waits_summary_by_table 收集指标。
collect.perf_schema.replication_group_members5.7从 performance_schema.replication_group_members 收集指标。
collect.perf_schema.replication_group_member_stats5.7从 performance_schema.replication_group_member_stats 收集指标。
collect.perf_schema.replication_applier_status_by_worker5.7从 performance_schema.replication_applier_status_by_worker 收集指标。
collect.slave_status5.1从 SHOW SLAVE STATUS 收集(默认启用)
collect.slave_hosts5.1从 SHOW SLAVE HOSTS 收集
collect.heartbeat5.1从心跳收集
collect.heartbeat.database5.1从哪里收集心跳数据的数据库。 (默认:心跳)
collect.heartbeat.table5.1从哪里收集心跳数据的表。 (默认:心跳)
collect.heartbeat.utc5.1使用 UTC 作为当前服务器的时间戳(使用 --utc调用 pt-heartbeat)。 (默认值:假)

配置prometheus

bash
cd /data/docker/docker-prometheus/ cat >> prometheus/prometheus.yml << "EOF" - job_name: 'mysqld_exporter' static_configs: - targets: ['192.168.1.200:9104'] labels: instance: test服务器 EOF

常用监控指标

bash
mysql_up # 服务器是否在线 mysql_global_status_uptime # 运行时长,单位 s delta(mysql_global_status_bytes_received[1m]) # 网络接收的 bytes delta(mysql_global_status_bytes_sent[1m]) # 网络发送的 bytes mysql_global_status_threads_connected # 当前的客户端连接数 mysql_global_variables_max_connections # 允许的最大连接数 mysql_global_status_threads_running # 正在执行命令的客户端连接数,即非 sleep 状态 delta(mysql_global_status_aborted_connects[1m]) # 客户端建立连接失败的连接数,比如登录失败 delta(mysql_global_status_aborted_clients[1m]) # 客户端连接之后,未正常关闭的连接数 delta(mysql_global_status_commands_total{command="xx"}[1m]) > 0 # 每分钟各种命令的次数 delta(mysql_global_status_handlers_total{handler="xx"}[1m]) > 0 # 每分钟各种操作的次数 delta(mysql_global_status_handlers_total{handler="commit"}[1m]) > 0 # 每分钟 commit 的次数 delta(mysql_global_status_table_locks_immediate[1m]) # 请求获取锁,且立即获得的请求数 delta(mysql_global_status_table_locks_waited[1m]) # 请求获取锁,但需要等待的请求数。该值越少越好 delta(mysql_global_status_queries[1m]) # 每分钟的查询数 delta(mysql_global_status_slow_queries[1m]) # 慢查询数。如果未启用慢查询日志,则为 0 mysql_global_status_innodb_page_size # innodb 数据页的大小,单位 bytes mysql_global_variables_innodb_buffer_pool_size # innodb_buffer_pool 的限制体积 mysql_global_status_buffer_pool_pages{state="data"} # 包含数据的数据页数,包括洁页、脏页 mysql_global_status_buffer_pool_dirty_pages # 脏页数

触发器配置,通过cat创建mysqld.yml文件

yaml
cat >> prometheus/rules/mysqld.yml << "EOF" groups: - name: MySQL rules: - alert: MysqlDown expr: mysql_up == 0 for: 30s labels: severity: critical annotations: summary: "MySQL Down,实例:{{ $labels.instance }}" description: "MySQL_exporter连不上MySQL了,当前状态为:{{ $value }}" - alert: MysqlTooManyConnections expr: max_over_time(mysql_global_status_threads_connected[1m]) / mysql_global_variables_max_connections * 100 > 80 for: 2m labels: severity: warning annotations: summary: "Mysql连接数过多告警,实例:{{ $labels.instance }}" description: "MySQL连接数>80%,当前值:{{ $value }}" - alert: MysqlHighThreadsRunning expr: max_over_time(mysql_global_status_threads_running[1m]) > 20 for: 2m labels: severity: warning annotations: summary: "Mysql运行的线程过多,实例:{{ $labels.instance }}" description: "Mysql运行的线程 > 20,当前运行的线程:{{ $value }}" - alert: MysqlSlowQueries expr: increase(mysql_global_status_slow_queries[2m]) > 0 for: 2m labels: severity: warning annotations: summary: "Mysql慢日志告警,实例:{{ $labels.instance }}" description: "MySQL在过去2分钟有新的{{ $value }}条慢查询" #MySQL innodb 日志写入停滞 - alert: MysqlInnodbLogWaits expr: rate(mysql_global_status_innodb_log_waits[15m]) > 10 for: 0m labels: severity: warning annotations: summary: "MySQL innodb日志等待,实例:{{ $labels.instance }}" description: "MySQL innodb日志写入停滞,当前值: {{ $value }}" - alert: MysqlRestarted expr: mysql_global_status_uptime < 60 for: 0m labels: severity: info annotations: summary: "MySQL 重启,实例:{{ $labels.instance }}" description: "不到一分钟前,MySQL重启过" EOF

grafana展示,id: 7362,9625 这个id可以监控数据库的表

这个仪表盘部分指标需要重新编辑一下,把仪表盘的 Process States 和 Top Process States Hourly 这个里的 Process States 这个指标改成 mysql_info_schema_processlist_threads

监控springboot

监控java应用(tomcat/jar)

JMX exporter 负责收集 Java 虚拟机信息

bash
PROMETHEUS_JMX_EXPORTER_OPTS="-javaagent:../prometheus-exporter/jmx_prometheus_javaagent-0.18.0.jar=12345:../prometheus-exporter/tomcat.yml" JAVA_OPTS="-Xmx4096m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=2048m -Xss1024K $PROMETHEUS_JMX_EXPORTER_OPTS"

springboot项目

引入maven依赖,修改pom.xml添加如下代码,引入Spring Boot Actuator的相关依赖。

xml
<!-- spring-boot-actuator依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- prometheus依赖 --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>

在 application.properties 中添加相关配置暴露监测数据端口,如果是application.yaml格式,需要转成yaml,出于安全考虑,默认情况下除了/health和/info之外的所有actuator都是关闭的

server.port=8081 spring.application.name=springboot-demo management.endpoints.web.exposure.include=prometheus,health #management.endpoints.web.exposure.include=* #management.endpoints.web.exposure.exclude=env,beans management.metrics.tags.application=${spring.application.name}

使用docker运行 springboot 一个项目

bash
docker run -d --restart=always -p 8081:8080 --name springboot-demo linge365/springboot-demo

prometheus配置

yaml
cd /data/docker/docker-prometheus #在scrape_configs(搜刮配置):下面增加如下配置: cat >> prometheus/prometheus.yml << "EOF" # Spring Boot 2.x 应用数据采集配置 - job_name: 'springboot-demo' metrics_path: '/actuator/prometheus' scrape_interval: 5s static_configs: - targets: ['192.168.1.100:8081'] EOF

监控指标

bash
process_files_max_files # 最大文件处理数量 tomcat_sessions_active_current_sessions # Tomcat 当前活跃 session 数量 tomcat_sessions_alive_max_seconds # Tomcat session 最大存活时间 jvm_buffer_total_capacity_bytes # 预估的池中缓冲区的总容量 jvm_threads_daemon_threads # 当前守护进程的线程数量 tomcat_global_request_max_seconds{name="http-nio-8080",} # 全局最长一次请求的时间 tomcat_sessions_active_max_sessions # 最大活跃 session 数量 system_cpu_usage # CPU 利用率 jvm_buffer_memory_used_bytes # 预估 Java 虚拟机用于此缓冲池的内存 jvm_classes_loaded_classes # 当前在 Java 虚拟机中加载的类的数量 jvm_memory_committed_bytes # 为 Java 虚拟机提交的内存量(以字节为单位) jvm_threads_live_threads # 当前线程数,包括守护进程和非守护进程的线程 tomcat_threads_config_max_threads # 配置的 Tomcat 的最大线程数 tomcat_global_received_bytes_total # Tomcat 接收到的数据量 tomcat_global_sent_bytes_total # Tomcat 发送的数据量 tomcat_threads_current_threads # Tomcat 当前的线程数 tomcat_sessions_created_sessions_total # Tomcat 创建的 session 数 system_load_average_1m # 在一段时间内,排队到可用处理器的可运行实体数量和可用处理器上运行的可运行实体数量的总和的平均值 tomcat_sessions_expired_sessions_total # 过期的 session 数量 jvm_buffer_count_buffers # 预估的池中的缓冲区数量 jvm_memory_used_bytes# JVM 内存使用量 process_uptime_seconds # Java 虚拟机的正常运行时间 jvm_gc_memory_allocated_bytes_total # 增加一个 GC 到下一个 GC 之后年轻代内存池的大小增加 jvm_gc_pause_seconds_count # GC暂停耗时数量和总时间 jvm_gc_pause_seconds_sum jvm_gc_pause_seconds_max tomcat_sessions_rejected_sessions_total # 被拒绝的 session 总数 jvm_gc_live_data_size_bytes# Full GC 后的老年代内存池的大小 tomcat_threads_busy_threads # Tomcat 繁忙线程数 jvm_threads_peak_threads # 自 Java 虚拟机启动或峰值重置以来的最高活动线程数 jvm_threads_states_threads # 当前具有 NEW 状态的线程数 jvm_gc_max_data_size_bytes # jvm_gc内存池的最大大小 http_server_requests_seconds_count #某个接口的请求数量和请求总时间 http_server_requests_seconds_sum http_server_requests_seconds_max jvm_gc_memory_promoted_bytes_total # GC之前到GC之后的老年代内存池大小的正增加计数 # 日志按级别计数 logback_events_total{application="prometheus-demo",level="info",} 7.0 logback_events_total{application="prometheus-demo",level="trace",} 0.0 logback_events_total{application="prometheus-demo",level="warn",} 0.0 logback_events_total{application="prometheus-demo",level="debug",} 0.0 logback_events_total{application="prometheus-demo",level="error",} 0.0 process_start_time_seconds # 启动时间 process_files_open_files # 打开文件描述符的数量 tomcat_global_error_total # 异常数量 jvm_memory_max_bytes # 可用于内存管理的最大内存量(以字节为单位) process_cpu_usage # 最近的 CPU 利用率 jvm_classes_unloaded_classes_total # 自 Java 虚拟机开始执行以来卸载的类总数 system_cpu_count # CPU 核数 tomcat_global_request_seconds_count # 全局请求总数和总耗时 tomcat_global_request_seconds_sum

添加触发器(告警规则)

yaml
cat >> prometheus/rules/springboot.yml << "EOF" groups: - name: SprinBoot rules: - alert: SprinBooErrorEvents expr: increase(logback_events_total{level="error"}[2m]) > 0 for: 2m labels: severity: warning annotations: summary: "Springboot错误事件 容器: $labels.instance" description: "在过去2分钟有新的{{ $value }}个错误事件" EOF

系统进程监控

process exporter功能,项目地址

如果想要对主机的进程进行监控,例如chronyd,sshd等服务进程以及自定义脚本程序运行状态监控。我们使用node exporter就不能实现需求了,此时就需要使用process exporter来做进程状态的监控。

Process-Exporter 的做法是配置需要监控的进程的名称,他会去搜索该进程从而得到其需要的监控信息,其实也就是我们常做的 ps -efl | grep xxx 命令来查看对应的进程。

监控所有进程

bash
cd /data/docker/process_exporter cat >>process.yml << "EOF" process_names: - name: "{{.Comm}}" # 匹配模板 cmdline: - '.+' # 匹配所有名称 EOF

监控指定进程

bash
process_names: # - name: "{{.Comm}}" # cmdline: # - '.+' - name: "{{.Matches}}" cmdline: - 'nginx' #唯一标识 - name: "{{.Matches}}" cmdline: - 'mongod' - name: "{{.Matches}}" cmdline: - 'mysqld' - name: "{{.Matches}}" cmdline: - 'redis-server'

docker运行

bash
docker run -d --rm -p 9256:9256 --privileged -v /proc:/host/proc -v `pwd`:/config --name process-exporter ncabatoff/process-exporter --procfs /host/proc -config.path /config/process.yml

配置说明

参数说明
{{.Comm}}包含原始可执行文件的名称,即 /proc/stat
{{.ExeBase}}包含可执行文件的名称(默认)
{{.ExeFull}}包含可执行文件的路径
{{.Username}}包含的用户名
{{.Matches}}包含所有正则表达式而产生的匹配项(建议使用)
{{.PID}}包含进程的PID,一个PID仅包含一个进程(不建议使用)
{{.StartTime}}包含进程的开始时间(不建议使用)

Prometheus设置

bash
cd /data/docker/docker-prometheus cat >> prometheus/prometheus.yml << "EOF" - job_name: 'process' scrape_interval: 30s scrape_timeout: 15s static_configs: - targets: ['192.168.1.200:9256'] EOF

metrics说明

namedprocess_ namedprocess_namegroup_states{state="Zombie"} 查看僵尸 # 上下文切换数量 # Counter namedprocess_namegroup_context_switches_total # CPU user/system 时间(秒) # Counter namedprocess_namegroup_cpu_seconds_total # 主要页缺失次数 # Counter namedprocess_namegroup_major_page_faults_total # 次要页缺失次数 # Counter namedprocess_namegroup_minor_page_faults_total # 内存占用(byte) # Gauge namedprocess_namegroup_memory_bytes # 同名进程数量 # Gauge namedprocess_namegroup_num_procs # 同名进程状态分布 # Gauge namedprocess_namegroup_states # 线程数量 # Gauge namedprocess_namegroup_num_threads # 启动时间戳 # Gauge namedprocess_namegroup_oldest_start_time_seconds # 打开文件描述符数量 # Gauge namedprocess_namegroup_open_filedesc # 打开文件数 / 允许打开文件数 # Gauge namedprocess_namegroup_worst_fd_ratio # 读数据量(byte) # Counter namedprocess_namegroup_read_bytes_total # 写数据量(byte) # Counter namedprocess_namegroup_write_bytes_total # 内核wchan等待线程数量 # Gauge namedprocess_namegroup_threads_wchan

常用指标

指标名解释
namedprocess_namegroup_num_procs运行的进程数
namedprocess_namegroup_statesRunning/Sleeping/Other/Zombie状态的进程数
namedprocess_namegroup_cpu_seconds_total获取/proc/[pid]/stat 进程CPU utime、stime状态时间
namedprocess_namegroup_read_bytes_total获取/proc/[pid]/io 进程读取字节数
namedprocess_namegroup_write_bytes_total获取/proc/[pid]/io 进程写入字节数
namedprocess_namegroup_memory_bytes获取进程使用的内存字节数
namedprocess_namegroup_open_filedesc获取进程使用的文件描述符数量
namedprocess_namegroup_thread_count运行的线程数
namedprocess_namegroup_thread_cpu_seconds_total获取线程CPU状态时间
namedprocess_namegroup_thread_io_bytes_total获取线程IO字节数

添加触发器

yaml
cat > prometheus/rules/process.yml << "EOF" groups: - name: process rules: - alert: 进程数多告警 expr: sum(namedprocess_namegroup_states) by (instance) > 1000 for: 1m labels: severity: warning annotations: summary: "进程数超过1000" description: "服务器当前有{{ $value }}个进程" - alert: 僵尸进程数告警 expr: sum by(instance, groupname) (namedprocess_namegroup_states{state="Zombie"}) > 0 for: 1m labels: severity: warning annotations: summary: "有僵尸进程数" description: "进程{{ $labels.groupname }}{{ $value }}个僵尸进程" - alert: 进程重启告警 expr: ceil(time() - max by(instance, groupname) (namedprocess_namegroup_oldest_start_time_seconds)) < 60 for: 15s labels: severity: warning annotations: summary: "进程重启" description: "进程{{ $labels.groupname }}{{ $value }}秒前重启过" - alert: 进程退出告警 expr: max by(instance, groupname) (delta(namedprocess_namegroup_oldest_start_time_seconds{groupname=~"^java.*|^nginx.*"}[1d])) < 0 for: 1m labels: severity: warning annotations: summary: "进程退出" description: "进程{{ $labels.groupname }}退出了" EOF

黑盒监控

白盒监控和黑盒监控

“白盒监控“--需要把对应的 Exporter 程序安装到被监控的目标主机上,从而实现对主机各种资源及其状态的数据采集工作。

但是由于某些情况下操作技术或其他原因,不是所有的 Exporter 都能部署到被监控的主机环境中,最典型的例子是监控全国网络质量的稳定性,通常的方法是使用ping操作,对选取的节点进行ICMP测试,此时不可能在他人应用环境中部署相关的Exporter程序。针对这样的应用的场景,Prometheus社区提供了黑盒解决方案,BlackboxExporter 无须安装在被监控的目标环境中,用户只需要将其安装在与Prometheus和被监控目标互通的环境中,通过HTTP、HTTPS、DNS、TCP、ICMP等方式对网络进行探测监控,还可以探测SSL证书过期时间。

创建配置文件

yaml
mkdir /data/docker/blackbox_exporter cat > /data/docker/blackbox_exporter/config.yml << "EOF" modules: http_2xx: prober: http timeout: 20s http: preferred_ip_protocol: "ip4" http_post_2xx_query: prober: http timeout: 20s http: preferred_ip_protocol: "ip4" ##使用ipv4 method: POST headers: Content-Type: application/json ##header头 body: '{"hmac":"","params":{"publicFundsKeyWords":"xxx"}}' ##传参 tls_connect_tls: prober: tcp timeout: 5s tcp: tls: true tcp_connect: prober: tcp timeout: 5s # pop3s_banner: prober: tcp tcp: query_response: - expect: "^+OK" tls: true tls_config: insecure_skip_verify: false ssh_banner: prober: tcp tcp: query_response: - expect: "^SSH-2.0-" irc_banner: prober: tcp tcp: query_response: - send: "NICK prober" - send: "USER prober prober prober :prober" - expect: "PING :([^ ]+)" send: "PONG ${1}" - expect: "^:[^ ]+ 001" icmp: prober: icmp timeout: 20s EOF

docker直接运行

bash
docker run -d --restart=always --name blackbox-exporter -p 9115:9115 \ -v /data/docker/blackbox_exporter:/etc/blackbox_exporter prom/blackbox-exporter:v0.16.0 \ --config.file=/etc/blackbox_exporter/config.yml

docker-compose启动

bash
cd /data/docker/blackbox_exporter/ cat >docker-compose.yml << "EOF" version: '3.3' services: blackbox_exporter: image: prom/blackbox-exporter:v0.16.0 container_name: blackbox_exporter restart: always volumes: - /data/docker/blackbox_exporter:/etc/blackbox_exporter ports: - 9115:9115 EOF

添加Prometheus的配置

yaml
cd /data/docker/docker-prometheus cat >> prometheus/prometheus.yml << "EOF" #http 配置 - job_name: 'blackbox_http' metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - https://www.baidu.com - https://www.163.com relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.199:9115 #tcp 配置 - job_name: 'blackbox_tcp' metrics_path: /probe params: module: [tcp_connect] static_configs: - targets: - 192.168.1.200:22 - 192.168.1.199:9090 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.199:9115 #icmp 配置 ping - job_name: 'blackbox_icmp' metrics_path: /probe params: module: [icmp] static_configs: - targets: - 192.168.1.199 - 192.168.1.200 relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.199:9115 EOF

监控项

yaml
probe_ probe_success #是否探测成功(取值1、0,分别表示成功、失败) probe_duration_seconds #探测的耗时 #关于DNS probe_dns_lookup_time_seconds #DNS解析的耗时 probe_ip_protocol #IP协议取值为4、6 probe_ip_addr_hash #IP地址的哈希值,用于判断IP是否变化 #关于HTTP probe_http_status_code #HTTP响应的状态码,如果发生重定向,则取决于最后一次响应 probe_http_content_length #HTTP响应的body长度,单位bytes probe_http_version #HTTP响应的协议版本,比如1.1 probe_http_ssl #HTTP响应是否采用SSL,取值 1、0 probe_ssl_earliest_cert_expiry #SSL证书过期时间,为Unix时间戳

触发器

yaml
cd /data/docker/docker-prometheus cat > prometheus/rules/blackbox_exporter.yml << 'EOF' groups: - name: Blackbox rules: - alert: 黑盒子探测失败报警 expr: probe_success == 0 for: 1m labels: severity: critical annotations: summary: '黑盒子探测失败 {{ $labels.instance }}' description: "黑盒子探测失败,当前值{{ $value }}" - alert: 请求慢告警 expr: avg_over_time(probe_duration_seconds[1m]) > 1 for: 1m labels: severity: warning annotations: summary: '请求慢 {{ $labels.instance }}' description: "请求时间操过1秒,值{{ $value }}" - alert: http状态码检测失败 expr: probe_http_status_code <= 199 OR probe_http_status_code >= 400 for: 1m labels: severity: critical annotations: summary: 'http状态码检测失败{{ $labels.instance }}' description: "HTTP状态码非200-399,当前状态码为{{ $value }}" - alert: ssl证书即将到期 expr: probe_ssl_earliest_cert_expiry - time() < 86400 *30 for: 1m labels: severity: warning annotations: summary: '证书即将到期 {{ $labels.instance }}' description: "SSL 证书在30天后到期,值{{ $value }}" EOF

域名监控

域名监控通过 domain_exporter 来完成

docker运行命令

bash
docker run -d --restart=always --name domain_exporter -p 9222:9222 caarlos0/domain_exporter

Prometheus配置

yaml
cd /data/docker/docker-prometheus/ cat >> prometheus/prometheus.yml << "EOF" - job_name: domain #scrape_interval: 1h scrape_interval: 15s metrics_path: /probe relabel_configs: - source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: 192.168.1.200:9222 # domain_exporter address static_configs: - targets: - qq.com - baidu.cn EOF

常用监控指标

bash
domain_expiry_days 域名到期时间 domain_probe_success 域名检测状态

触发器

yaml
cat >> prometheus/rules/domain.yml << "EOF" groups: - name: domain rules: - alert: 域名检测失败 expr: domain_probe_success == 0 for: 2h labels: severity: warning annotations: summary: '{{ $labels.instance }}' description: '{{ $labels.domain }}域名检测失败' - alert: 域名过期 expr: domain_expiry_days < 30 for: 2h labels: severity: warning annotations: summary: '{{ $labels.instance }}' description: '{{ $labels.domain }}将在30天后过期' - alert: 域名过期 expr: domain_expiry_days < 5 for: 2h labels: severity: page annotations: summary: '{{ $labels.instance }}' description: '{{ $labels.domain }}将在5天后过期' EOF

监控总结

监控流程

  1. 需要在被监控的服务器上安装xx_exporter来收集数据
  2. 添加Prometheus配置,去收集(xx_exporter)提供的监控样本数据
  3. 配置触发器(告警规则)

exporter

名称监控啥
node_exporterLinux服务器的资源用量
nginx-prometheus-exporternginx
rabbitmq_exporterRabbitmq
mongodb_exportermongodb数据库
mysql_exportermysql数据库
Redis_exporterredis数据库
BlackBox_Exporter网络协议:http(get,post)、dns、tcp、icmp,ssl证书过期时间
domain_exporter域名过期时间
cAdvisordocker容器
pom.xml和application.yamlspringboot java应用
process-exporter进程

除了 node_exporter 我们还会根据自己的业务选择安装其他 exporter 或者自己编写,比较常用的 exporter 有

更多 exporter 请参考链接

pushgateway

Pushgateway 是 Prometheus 生态中一个重要工具,使用它的原因主要是:

  • Prometheus 采用 pull 模式,可能由于不在一个子网或者防火墙原因,导致 Prometheus 无法直接拉取各个 target 数据。
  • 在监控业务数据的时候,需要将不同数据汇总, 由 Prometheus 统一收集。
  • 当exporter不能满足需要时,也可以通过自定义(python、shell、java)监控我们想要的数据。

由于以上原因,不得不使用 pushgateway,但在使用之前,有必要了解一下它的一些弊端:

  • 将多个节点数据汇总到 pushgateway, 如果 pushgateway 挂了,受影响比多个 target 大。
  • Prometheus 拉取状态 up 只针对 pushgateway, 无法做到对每个节点有效。
  • Pushgateway 可以持久化推送给它的所有监控数据。

因此,即使你的监控已经下线,prometheus 还会拉取到旧的监控数据,需要手动清理 pushgateway 不要的数据。

docker命令运行

bash
docker run -d -p 9091:9091 --restart=always --name pushgateway prom/pushgateway

docker-compose运行

yaml
cat > docker-compose.yaml << "EOF" version: '3.3' services: pushgateway: image: prom/pushgateway container_name: pushgateway restart: always expose: - 9091 ports: - "9091:9091" EOF

Prometheus配置,去pull拉取pushgateway收集到的数据。

yaml
cat >> prometheus/prometheus.yml << "EOF" - job_name: pushgateway honor_labels: true #加上此配置,exporter节点上传数据中的一些标签将不会被pushgateway节点的相同标签覆盖 static_configs: - targets: ['192.168.1.199:9091'] labels: instance: pushgateway EOF

向Pushgateway推送监控数据

正常情况我们会使用 Client SDK 推送数据到 pushgateway, 但是我们还可以curl调用 API 来管理, 例如:

  • {job="some_job"} 添加单条数据:

    bash
    echo "some_metric 3.14" | curl --data-binary @- http://192.168.1.199:9091/metrics/job/some_job
  • 添加更多更复杂数据,通常数据会带上 instance(some_instance为instance名), 表示来源位置:

    cat << "EOF" | curl --data-binary @- http://192.168.1.199:9091/metrics/job/some_job/instance/some_instance # TYPE some_metric counter some_metric{label="val1"} 42 # TYPE another_metric gauge # HELP another_metric Just an example. another_metric 2398.283 EOF
  • 删除某个组下的某实例的所有数据:

    bash
    curl -X DELETE http://192.168.1.199:9091/metrics/job/some_job/instance/some_instance
  • 删除某个组下的所有数据:

    bash
    curl -X DELETE http://192.168.1.199:9091/metrics/job/some_job

使用python

安装 prometheus_client 模块

bash
pip install prometheus_client

python代码

python
from prometheus_client import CollectorRegistry, Gauge, push_to_gateway registry = CollectorRegistry() g = Gauge('job_last_success_unixtime', 'Last time a batch job successfully finished', registry=registry) g.set_to_current_time() push_to_gateway('localhost:9091', job='batchA', registry=registry)

监控data数据目录下的文件数量(需求)

shell脚本

bash
cat >> /data/file_num.sh << "EOF" #!/bin/sh FILENUM=`ls -l /data |sed 1d| wc -l` echo "data_file_num ${FILENUM}" | curl --data-binary @- http://192.168.1.199:9091/metrics/job/test_job/instance/test EOF

定时任务

bash
*/1 * * * * /bin/sh /data/file_num.sh > /dev/null 2>&1

python脚本

python
cat >> /data/file_num.py << "EOF" from prometheus_client import CollectorRegistry, Gauge, push_to_gateway import os path = '/data' # 输入文件夹地址 files = os.listdir(path) # 读入文件夹 num_png = len(files) # 统计文件夹中的文件个数 registry = CollectorRegistry() g = Gauge('python_data_file_num', 'data file num', ['instance'], registry=registry) g.labels('test').set(num_png) push_to_gateway('192.168.1.199:9091', job='test_job', registry=registry) EOF

定时任务

bash
*/1 * * * * /usr/bin/python3 /data/file_num.py > /dev/null 2>&1

配置告警规则

例如:当data目录下的文件数量超过5,报警出来

yaml
cat >> prometheus/rules/pushgateway.yml << "EOF" groups: - name: pushgateway rules: - alert: DataFileNum expr: data_file_num > 5 for: 0m labels: severity: warning annotations: summary: 'data数据目录文件数过多' description: "data数据目录文件数>5,当前数量:{{ $value }}" EOF

基于文件的服务发现

我们将学习 Prometheus 中是如何使用服务发现来查找和抓取目标的。我们知道在 Prometheus 配置文件中可以通过一个 static_configs 来配置静态的抓取任务,但是在云环境下,特别是容器环境下,抓取目标地址是经常变动的,所以用静态的方式就不能满足这些场景了,还有特别在很多服务器需要监控时。所以我们需要监控系统能够动态感知这个变化,不可能每次变动都去手动重新配置的,为了应对复杂的动态环境,Prometheus 也提供了与基础设施中的服务发现集成的功能。

image-20240826173759456

Prometheus 已经支持多种内置的服务发现机制:

  • 发现云服务商的 VM 虚拟机
  • Kubernetes 上的自动发现
  • 通用的服务查找,例如 DNS、Consul、Zookeeper 或自定义发现机制

我们都可以通过 Prometheus 配置文件中的 scrape_config 部分进行配置,Prometheus 会不断更新动态的抓取目标列表,自动停止抓取旧的实例,开始抓取新的实例,Prometheus 特别适合运行于 Kubernetes 集群下面,可以自动发现监控目标。

此外大部分服务发现机制还会提供目标的一些元数据,通常都是带有 __ 的前缀, 比如标签、注解、服务名等等,可以在 relabeling 阶段使用这些元数据来过滤修改目标,这些元信息标签在重新标记阶段后被删除。

基于文件的服务发现

除了基于 Consul 的服务发现之外,Prometheus 也允许我们进行自定义的发现集成,可以通过 watch 一组本地文件来获取抓取目标以及标签信息,也就是我们常说的基于文件的服务发现方式。

image-20240826174110585

基于文件的服务发现提供了一种更通用的方式来配置静态目标,并作为一个接口插入自定义服务发现机制。

它读取一组包含零个或多个 <static_config> 列表的文件,对所有定义的文件的变更通过磁盘监视被检测到并立即应用,文件可以以 YAML 或 JSON 格式提供。文件必须包含一个静态配置的列表:

当然该文件也可以使用 JSON 格式进行配置:

json
[ { "targets": [ "<host>", ... ], "labels": { "<labelname>": "<labelvalue>", ... } }, ... ]

如果是 YAML 文件则格式为:

yaml
- targets: [ - '<host>' ] labels: [ <labelname>: <labelvalue> ... ]

文件内容也会在指定的刷新间隔时间内定期重新读取。

bash
# Patterns for files from which target groups are extracted. files: [ - <filename_pattern> ... ] # Refresh interval to re-read the files. [ refresh_interval: <duration> | default = 5m ]

其中 <filename*pattern> 可以是一个以 .json.yml.yaml 结尾的路径,最后一个路径段可以包含一个匹配任何字符序列的 *,例如:my/path/tg_*.json

创建一个用于服务发现的目标文件,在与 prometheus.yml 文件相同目录下面创建一个名为 targets.yml 的文件,内容如下所示:

yaml
cd /data/docker/docker-prometheus mkdir prometheus/targets cat > prometheus/targets/targets.yml<<"EOF" - targets: ['localhost:9090'] labels: job: prometheus - targets: ['cadvisor:8080'] labels: instance: Prometheus服务器 job: cadvisor - targets: ['192.168.1.200:8080'] labels: instance: test服务器 job: cadvisor - targets: ['node_exporter:9100'] labels: instance: Prometheus服务器 job: node-exporter - targets: ['192.168.1.200:9100'] labels: instance: test服务器 job: node-exporter - targets: ['192.168.1.200:9113'] labels: instance: test服务器 job: nginx_exporter - targets: ['192.168.1.200:9121'] labels: instance: test服务器 job: redis_exporter - targets: ['192.168.1.200:9419'] labels: instance: test服务器 job: rabitmq_exporter - targets: ['192.168.1.200:9216'] labels: instance: test服务器 job: mongodb_exporter - targets: ['192.168.1.200:9104'] labels: instance: test服务器 job: mysqld_exporter - targets: ['192.168.1.200:9256'] labels: instance: test服务器 job: process EOF

springboot.yml

yaml
cat > prometheus/targets/springboot.yml << "EOF" - targets: - 192.168.1.200:8081 EOF

blackbox-exporter-http.yml

yaml
cat > prometheus/targets/blackbox-exporter-http.yml << "EOF" - targets: - https://www.baidu.com - https://www.jd.com EOF

blackbox-exporter-tcp.yml

yaml
cat > prometheus/targets/blackbox-exporter-tcp.yml << "EOF" - targets: - 192.168.1.199:22 - 192.168.1.199:9090 EOF

blackbox-exporter-icmp.yml

yaml
cat > prometheus/targets/blackbox-exporter-icmp.yml << "EOF" - targets: - 192.168.1.199 - 192.168.1.200 EOF

domain.yml

yaml
cat > prometheus/targets/domain.yml << "EOF" - targets: - qq.com - baidu.com EOF

配置文件服务发现

用于发现的目标文件创建完成后,要让 Prometheus 能够从上面的 targets.yml 文件中自动读取抓取目标,需要在 prometheus.yml 配置文件中的 scrape_configs 部分添加如下所示的抓取配置:

备份文件

bash
cp -a prometheus/prometheus.yml{,.bak} ls -l prometheus/prometheus.yml.bak

创建文件

yaml
cat > prometheus/prometheus.yml << "EOF" # 全局配置 global: scrape_interval: 15s # 将搜刮间隔设置为每15秒一次。默认是每1分钟一次。 evaluation_interval: 15s # 每15秒评估一次规则。默认是每1分钟一次。 # Alertmanager 配置 alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] # 报警(触发器)配置 rule_files: - "alert.yml" - "rules/*.yml" # 搜刮配置 scrape_configs: - job_name: "file-sd-test" file_sd_configs: - refresh_interval: 10s files: - "targets/targets.yml" # Spring Boot 2.x 应用数据采集配置 - job_name: 'file-springboot-demo' metrics_path: '/actuator/prometheus' file_sd_configs: - refresh_interval: 10s files: - targets/springboot.yml #http配置 - job_name: "file-blackbox_http" metrics_path: /probe params: module: [http_2xx] file_sd_configs: - refresh_interval: 10s files: - targets/blackbox-exporter-http.yml relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.11.62:9115 #tcp检查配置 - job_name: "file-blackbox_tcp" metrics_path: /probe params: module: [tcp_connect] file_sd_configs: - refresh_interval: 10s files: - targets/blackbox-exporter-tcp.yml relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.11.62:9115 #icmp检查配置 ping - job_name: "blackbox_icmp" metrics_path: /probe params: module: [icmp] file_sd_configs: - refresh_interval: 10s files: - targets/blackbox-exporter-http.yml relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.11.62:9115 - job_name: domain #scrape_interval: 1h scrape_interval: 15s metrics_path: /probe relabel_configs: - source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: 192.168.11.62:9222 # domain_exporter address file_sd_configs: - refresh_interval: 10s files: - targets/domain.yml EOF

然后我们可以尝试改变 targets.yml 的内容,比如为192.168.11.62:8080实例增加一个 env: test的标签,不用重新加载 Prometheus 配置,Prometheus 将 watch 该文件,并自动接收任何变化。

注意:当在生产环境 Prometheus 服务器中改变 file_sd 目标文件时,确保改变是原子的,以避免重新加载出现错误,最好的方法是在一个单独的位置创建更新的文件,然后将其重命名为目标文件名(使用 mv 命令或 rename() 系统调用)。

这样我们就完成了基于文件的通用服务发现机制,可以让我们动态地改变 Prometheus 的监控目标,而不需要重新启动或重新加载 Prometheus 服务。

基于Consul的服务发现

Consul 是由 HashiCorp 开发的一个支持多数据中心的分布式服务发现和键值对存储服务的开源软件,是一个通用的服务发现和注册中心工具,被大量应用于基于微服务的软件架构当中。

我们通过api将exporter服务注册到 Consul,然后配置 Prometheus 从 Consul 中发现实例。关于 Consul 本身的使用可以查看官方文档 https://learn.hashicorp.com/consul 了解更多。

docker安装Consul

bash
docker run -d --name consul -p 8500:8500 consul:1.14.5

docker-compose启动

yaml
cat > consul.yml << "EOF" version: '3' services: consul: image: consul:1.14.5 container_name: consul hostname: consul restart: always ports: - "8500:8500" volumes: - /data/docker/consul/data:/consul/data - /data/docker/consul/config:/consul/config command: ["consul","agent","-server","-bootstrap","-data-dir","/consul","-ui","-bind","127.0.0.1","-client","0.0.0.0"] EOF

consul http访问地址

http://192.168.1.199:8500/

通过api注册到Consul

bash
curl -X PUT -d '{"id": "node1","name": "node_exporter","address": "node_exporter","port": 9100,"tags": ["exporter"],"meta": {"job": "node_exporter","instance": "Prometheus服务器"},"checks": [{"http": "http://192.168.1.199:9100/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register

把json数据放在文件中,使用这个json文件注册

json
mkdir /data/docker/consul cd /data/docker/consul cat > node_exporter.json << "EOF" { "id": "node2", "name": "node_exporter", "address": "192.168.1.200", "port": 9100, "tags": ["exporter"], "meta": { "job": "node_exporter", "instance": "test服务器" }, "checks": [{ "http": "http://192.168.1.199:9100/metrics", "interval": "10s" }] } EOF

使用json文件注册

bash
curl --request PUT --data @node_exporter.json http://localhost:8500/v1/agent/service/register

除了我们注册的 2 个 demo 服务之外,Consul agent 还会将自己注册为一个名为 consul 的服务,我们可以在浏览器中访问 http://192.168.1.199:8500 查看注册的服务。

配置 Prometheus

在 Prometheus 的配置文件 prometheus.yml 文件中的 scrape_configs 部分添加如下所示的抓取配置:

备份源文件

bash
cd /data/docker/docker-prometheus cp -a prometheus/prometheus.yml prometheus/prometheus.yml.bak ls -l prometheus/prometheus.yml.bak

使用cat更新文件内容

yaml
cat > prometheus/prometheus.yml << "EOF" # 全局配置 global: scrape_interval: 15s # 将搜刮间隔设置为每15秒一次。默认是每1分钟一次。 evaluation_interval: 15s # 每15秒评估一次规则。默认是每1分钟一次。 # Alertmanager 配置 alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] # 报警(触发器)配置 rule_files: - "alert.yml" - "rules/*.yml" # 搜刮配置 scrape_configs: - job_name: 'prometheus' # 覆盖全局默认值,每15秒从该作业中刮取一次目标 scrape_interval: 15s static_configs: - targets: ['localhost:9090'] - job_name: 'alertmanager' # 覆盖全局默认值,每15秒从该作业中刮取一次目标 scrape_interval: 15s static_configs: - targets: ['alertmanager:9093'] - job_name: 'consul_exporter' consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*exporter.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap # Spring Boot 2.x 应用数据采集配置 - job_name: 'consul_springboot_demo' metrics_path: '/actuator/prometheus' scrape_interval: 5s consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*springboot.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap #http配置 - job_name: "consul-blackbox_http" metrics_path: /probe params: module: [http_2xx] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_http.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #tcp检查配置 - job_name: "consul_blackbox_tcp" metrics_path: /probe params: module: [tcp_connect] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_tcp.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #icmp检查配置 - job_name: "consul_blackbox_icmp" metrics_path: /probe params: module: [icmp] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_icmp.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #域名检测 - job_name: consul_domain_exporter scrape_interval: 10s metrics_path: /probe consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*domain.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - target_label: __address__ replacement: 192.168.1.200:9115 EOF

通过 consul_sd_configs 配置用于自动发现的 Consul 服务地址,服务名为[],我们通过 relabel_configs 的过滤规则只接收指定的exporter

创建添加脚本,使用预先准备好的脚本,一次添加多个targets:

shell
cat > /data/docker/consul/api.sh << "EOF" #nginx curl -X PUT -d '{"id": "nginx1","name": "nginx_exporter","address": "192.168.1.200","port": 9113,"tags": ["exporter"],"meta": {"job": "nginx_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9113/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #rabbitmq curl -X PUT -d '{"id": "rabbitmq1","name": "rabbitmq_exporter","address": "192.168.1.200","port": 9419,"tags": ["exporter"],"meta": {"job": "rabbitmq_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9419/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #redis curl -X PUT -d '{"id": "redis1","name": "redis_exporter","address": "192.168.1.200","port": 9121,"tags": ["exporter"],"meta": {"job": "redis_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9121/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #mongodb curl -X PUT -d '{"id": "mongodb1","name": "mongodb_exporter","address": "192.168.1.200","port": 9216,"tags": ["exporter"],"meta": {"job": "mongodb_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9216/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #mysql curl -X PUT -d '{"id": "mysql1","name": "mysqld_exporter","address": "192.168.1.200","port": 9104,"tags": ["exporter"],"meta": {"job": "mysqld_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9104/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #cadvisor curl -X PUT -d '{"id": "cadvisor1","name": "cadvisor","address": "cadvisor","port": 8080,"tags": ["exporter"],"meta": {"job": "cadvisor","instance": "Prometheus服务器","env":"test"},"checks": [{"http": "http://192.168.1.199:8080/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register curl -X PUT -d '{"id": "cadvisor2","name": "cadvisor","address": "192.168.1.200","port": 8080,"tags": ["exporter"],"meta": {"job": "cadvisor","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:8080/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #springboot curl -X PUT -d '{"id": "springboot1","name": "springboot","address": "192.168.1.200","port": 8081,"tags": ["springboot"],"meta": {"job": "springboot","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:8081/actuator/prometheus", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #process_exporter curl -X PUT -d '{"id": "process1","name": "process_exporter","address": "192.168.1.200","port": 9256,"tags": ["exporter"],"meta": {"job": "process_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9256/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #http curl -X PUT -d '{"id": "http1","name": "blackbox_http","address": "https://www.jd.com","tags": ["blackbox_http"],"checks": [{"http": "http://192.168.1.199:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #tcp curl -X PUT -d '{"id": "tcp1","name": "blackbox_tcp","address": "192.168.1.199:9090","tags": ["blackbox_tcp"],"checks": [{"http": "http://192.168.1.199:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #icmp curl -X PUT -d '{"id": "icmp1","name": "blackbox_icmp","address": "192.168.1.200","tags": ["blackbox_icmp"],"checks": [{"http": "http://192.168.1.199:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #domin curl -X PUT -d '{"id": "domain1","name": "domain_exporter","address": "baidu.com","tags": ["domain"],"checks": [{"http": "http://192.168.1.200:9222", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register EOF

consul删除服务

bash
curl --request PUT http://127.0.0.1:8500/v1/agent/service/deregister/<ID>

ConsulManager

官方gitee地址

1、ConsulManager需要依赖Consul,请先完成Consul的部署。(暂时最高支持Consul v1.14.5)(docs/Consul部署说明.md

2、使用docker-compose来部署ConsulManager

  • 下载:wget https://starsl.cn/static/img/docker-compose.yml(仓库根目录下docker-compose.yml
  • 编辑:
vim docker-compose.yml

修改3个环境变量: consul_token:consul的登录token(如何获取?),当然也可以不获取token,这样consul使用无密码登录(不安全)。 consul_url:consul的URL(http开头,/v1要保留) admin_passwd:登录ConsulManager Web的admin密码

  • 启动:docker-compose pull && docker-compose up -d
  • 访问:http://{IP}:1026,使用配置的变量 admin_passwd 登录

Relabeling机制

在采集样本数据之前,对Target实例的标签(Metadata)进行重写的机制在Prometheus被称为Relabeling。Relabeling最基本的应用场景就是基于Target实例中包含的metadata标签,动态的添加或者覆盖标签。

在采集任务设置中通过relabel_configs来添加自定义的Relabeling过程。

默认情况下,当Prometheus加载Target实例完成后,这些Target时候都会包含一些默认的标签:

  • __address__:当前Target实例的访问地址<host>:<port>,如果在重新标记期间未设置标签,则默认将__address__标签值赋值给instance。
  • __scheme__:采集目标地址的协议,HTTP或者HTTPS
  • __metrics_path__:采集目标服务访问地址的访问路径
  • __param_<name>:采集任务目标服务的中包含的请求参数
  • job:设置为job_name相应的抓取配置的值。
  • __scrape_interval__:scrape抓取数据时间间隔(秒)
  • __scrape_timeout__: scrape超时时间(秒)

一般来说,Target以__作为前置的标签是在系统内部使用的,因此这些标签不会被写入到样本数据中。不过这里有一些例外,例如,我们会发现所有通过Prometheus采集的样本数据中都会包含一个名为instance的标签,该标签的内容对应到Target实例的__address__。 这里实际上是发生了一次标签的重写处理。

通过Consul动态发现的服务实例还会包含以下Metadata标签信息:

  • __meta_consul_address:consul地址
  • __meta_consul_dc:consul中服务所在的数据中心
  • __meta_consul_metadata:服务的metadata
  • __meta_consul_health: 健康检查
  • __meta_consul_node:服务所在consul节点的信息
  • __meta_consul_service_address:服务访问地址
  • __meta_consul_service_id:服务ID
  • __meta_consul_service_port:服务端口
  • __meta_consul_service:服务名称
  • __meta_consul_tags:服务包含的标签信息

relabel_configs配置

  • source_labels:源标签,没有经过relabel处理之前的标签名字。

  • target_labels:通过relabel处理之后的标签名字。

  • separator:源标签的值的连接分隔符。默认是";"

  • module:取源标签值散列的模数

  • regex:正则表达式,匹配源标签的值。默认是(.*)

  • replacement:通过分组替换后标签(target_label)对应的值。默认是$1

  • action:根据正则表达式匹配执行的动作。默认是replace

  • replace:替换标签值,根据regex正则匹配到原标签值,使用replacement来引用表达式匹配的分组

  • keep:满足regex正则条件的实例进行采集,把source_labels中没有匹配到regex正则内容的target实例丢掉,即只采集匹配成功的实例

  • drop:满足regex正则条件的实例不采集,把source_labels中没有匹配到regex正则内容的target实例丢掉,即只采集没有匹配成功的实例

  • hashmod: 使用hashmod计算source_labels的hash值并进行对比,基于自定义的模数取模,以实现对目标进行分类、重新赋值等功能

  • labelmap: 匹配regex所有标签名称,然后复制匹配标签的值进行分组,通过replacement分组引用(1,1,2,...)替代

  • labeldrop: 匹配regex所有标签名称,对匹配到的实例标签进行删除

  • labelkeep: 匹配regex所有标签名称,对匹配到的实例标签进行保留

替换标签值

可以通过 replace 这个操作来完成,如果没有指定 action 字段,则默认就是 replace

注:源数据需要加[]以便区分。目标数据不需要加。

案例1

yaml
relabel_configs: - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115
bash
源数据:__meta_consul_service_address="192.168.1.200" 会变成:target="192.168.1.200",instance="192.168.1.200",endpoint="192.168.1.200:9115/prod"

案例2

从Node Exporter实例采集上来的样本数据如下所示:

bash
node_load1{instance="test服务器", job="node_exporter"} 0.04

我们希望能有一个额外的标签dc,可以表示该样本所属的数据中心:

bash
node_load1{instance="test服务器", job="node_exporter",dc="dc1"} 0.04

relabel_config配置:

yaml
relabel_configs: - source_labels: ["__meta_consul_dc"] target_label: "dc"
bash
源数据:__meta_consul_dc="dc1" 会变成:dc="dc1"

保留或丢弃对象,通过keep 或 drop 这两个动作可以来完成

案例1

bash
relabel_configs: - source_labels: [__meta_consul_tags] regex: .*exporter.* action: keep 源数据为:__meta_consul_tags=",exporter," 会保留。如果action: drop就相反 源数据为:__meta_consul_tags=",domain," 会丢弃,如果action: drop就相反

标签集映射,把源标签的值映射到一组新的标签中去,使用 labelmap 这个动作完成

案例1

bash
relabel_configs: - regex: __meta_consul_service_metadata_(.+) action: labelmap 源数据为:__meta_consul_service_metadata_job="test" 会变成: job="test"

保留或删除标签,使用 labelkeeplabeldrop 这两个操作

案例1

bash
relabel_configs: - regex: job action: labeldrop 数据:probe_success{instance="192.168.11.61:9090", job="consul_blackbox_tcp"} 变成:probe_success{instance="192.168.11.61:9090"} action: labelkeep 刚好相反

Consul服务发现的prometheus配置

yaml
- job_name: 'consul_exporter' consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*exporter.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: ["__meta_consul_dc"] target_label: "dc" # Spring Boot 2.x 应用数据采集配置 - job_name: 'consul_springboot_demo' metrics_path: '/actuator/prometheus' scrape_interval: 5s consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*springboot.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap #http配置 - job_name: "consul-blackbox_http" metrics_path: /probe params: module: [http_2xx] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_http.* action: keep - regex: job action: labeldrop - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #tcp检查配置 - job_name: "consul_blackbox_tcp" metrics_path: /probe params: module: [tcp_connect] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_tcp.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #icmp检查配置 - job_name: "consul_blackbox_icmp" metrics_path: /probe params: module: [icmp] consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*blackbox_icmp.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: 192.168.1.200:9115 #域名检测 - job_name: consul_domain_exporter scrape_interval: 10s metrics_path: /probe consul_sd_configs: - server: '192.168.1.199:8500' services: [] relabel_configs: - source_labels: [__meta_consul_tags] regex: .*domain.* action: keep - regex: __meta_consul_service_metadata_(.+) action: labelmap - source_labels: [__meta_consul_service_address] target_label: __param_target - target_label: __address__ replacement: 192.168.1.200:9222

curl调用consul api命令

bash
#node_exporter curl -X PUT -d '{"id": "node1","name": "node_exporter","address": "node_exporter","port": 9100,"tags": ["exporter"],"meta": {"job": "node_exporter","instance": "Prometheus服务 器"},"checks": [{"http": "http://192.168.1.199:9100/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #nginx curl -X PUT -d '{"id": "nginx1","name": "nginx_exporter","address": "192.168.1.200","port": 9113,"tags": ["exporter"],"meta": {"job": "nginx_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9113/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #rabbitmq curl -X PUT -d '{"id": "rabbitmq1","name": "rabbitmq_exporter","address": "192.168.1.200","port": 9419,"tags": ["exporter"],"meta": {"job": "rabbitmq_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9419/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #redis curl -X PUT -d '{"id": "redis1","name": "redis_exporter","address": "192.168.1.200","port": 9121,"tags": ["exporter"],"meta": {"job": "redis_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9121/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #mongodb curl -X PUT -d '{"id": "mongodb1","name": "mongodb_exporter","address": "192.168.1.200","port": 9216,"tags": ["exporter"],"meta": {"job": "mongodb_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9216/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #mysql curl -X PUT -d '{"id": "mysql1","name": "mysqld_exporter","address": "192.168.1.200","port": 9104,"tags": ["exporter"],"meta": {"job": "mysqld_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9104/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #cadvisor curl -X PUT -d '{"id": "cadvisor1","name": "cadvisor","address": "cadvisor","port": 8080,"tags": ["exporter"],"meta": {"job": "cadvisor","instance": "Prometheus服务器","env":"test"},"checks": [{"http": "http://192.168.1.199:8080/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register curl -X PUT -d '{"id": "cadvisor2","name": "cadvisor","address": "192.168.1.200","port": 8080,"tags": ["exporter"],"meta": {"job": "cadvisor","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:8080/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #springboot curl -X PUT -d '{"id": "springboot1","name": "springboot","address": "192.168.1.200","port": 8081,"tags": ["springboot"],"meta": {"job": "springboot","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:8081/actuator/prometheus", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #process_exporter curl -X PUT -d '{"id": "process1","name": "process_exporter","address": "192.168.1.200","port": 9256,"tags": ["exporter"],"meta": {"job": "process_exporter","instance": "test服务器","env":"test"},"checks": [{"http": "http://192.168.1.200:9256/metrics", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #http curl -X PUT -d '{"id": "http1","name": "blackbox_http","address": "https://www.jd.com","tags": ["blackbox_http"],"checks": [{"http": "http://192.168.1.200:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #tcp curl -X PUT -d '{"id": "tcp1","name": "blackbox_tcp","address": "192.168.1.199:9090","tags": ["blackbox_tcp"],"checks": [{"http": "http://192.168.1.200:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #icmp curl -X PUT -d '{"id": "icmp1","name": "blackbox_icmp","address": "192.168.1.200","tags": ["blackbox_icmp"],"checks": [{"http": "http://192.168.1.200:9115", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register #domin curl -X PUT -d '{"id": "domain1","name": "domain_exporter","address": "baidu.com","tags": ["domain"],"checks": [{"http": "http://192.168.1.200:9222", "interval": "5s"}]}' http://localhost:8500/v1/agent/service/register

PromQL基础使用

PromQL (Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言,语言表现力非常丰富,内置函数很多,在日常数据可视化(Grafana)以及rule 告警中都会使用到它。

PromQL数据类型,在Prometheus的表达式语言中,PromQL数据类型归类为以下四种:

  • 瞬时向量(instant vector),是指同一时刻的一组时间序列,每个时间序列包含一个样本,所有样本共享相同的时间戳,即每个时序只有一个点。
  • 区间向量(range vector),是指在任何一个时间范围内的一组时间序列,包含每个时间序列随时间变化的一系列数据点,这时每个时序有多个点。
  • 标量(scalar),即纯量数据,一个简单的数字浮点值,只有一个数字,没有时序。
  • 字符串(string),这是一个表示文本的值。在PromQL中,字符串并不常见,但在某些特定的标签操作或文本函数中会出现。

瞬时向量(Instant vector):我们在Prometheus的查询页面输入指标 node_memory_Active_bytes 进行查询。

区间向量(Range vector):区间向量类型数据是指时序有一个时间区间的数据,这种类型的数据成为区间向量(Range vector)。我们在Prometheus的查询页面输入一个查询语句 node_memory_Active_bytes[1m] 进行查询。

以上的查询语句是查询 最近一分钟数据,因为采集的周期是 15s 所以[1m]每一个时序会有4个数据。

标量(Scalar):标量只有一个数字,没有时序。例如: 1024

需要注意的是,当使用表达式count(http_requests_total),返回的数据类型,依然是瞬时向量。用户可以通过内置函数scalar()将单个瞬时向量转换为标量。

字符串(String):直接使用字符串,作为PromQL表达式,则会直接返回字符串。(目前未被使用)

时间序列过滤器

瞬时向量过滤器

瞬时向量过滤器允许在指定的时间戳内选择一组时间序列和每个时间序列的单个样本值。在最简单的形式中,近指定指标(metric)名称。这将生成包含此指标名称的所有时间序列的元素的瞬时向量。

例如:选择指标名称为 node_cpu_seconds_total 的所有时间序列

bash
node_cpu_seconds_total

可以通过向花括号{}里附加一组标签来进一步过滤时间序列

例如:选择指标名称为 node_cpu_seconds_totalinstance 标签值为 Prometheus服务器mode 标签值为 idle 的时间序列:

bash
node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}

PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。总共有以下几种标签匹配运算符:

  • = : 选择与提供的字符串完全相同的标签。
  • != : 选择与提供的字符串不相同的标签。
  • =~ : 选择正则表达式与提供的字符串(或子字符串)相匹配的标签。
  • !~ : 选择正则表达式与提供的字符串(或子字符串)不匹配的标签。

例如:选择指标名称为 node_cpu_seconds_total,mode为 idleusersystemcpu!=0 的时间序列:

bash
node_cpu_seconds_total{mode=~"idle|user|system",cpu!="0"}

没有指定标签的标签过滤器会选择该指标名称的所有时间序列。

Prometheus 中的所有正则表达式都使用 RE2语法。

所有的 PromQL 表达式必须至少包含一个指标名称,或者一个不会匹配到空字符串的标签过滤器。

除了使用 <metric name>{label=value} 的形式以外,我们还可以使用内置的 __name__ 标签来指定监控指标名称。例如:表达式 node_cpu_seconds_total 等效于 {__name__="node_cpu_seconds_total"}

区间向量过滤器

区间向量与瞬时向量的工作方式类似,唯一的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 [] 进行定义,以指定应为每个返回的区间向量样本值中提取多长的时间范围。

时间范围通过数字来表示,单位可以使用以下其中之一的时间单位:

  • s - 秒
  • m - 分钟
  • h - 小时
  • d - 天
  • w - 周
  • y - 年

例如:选择在过去 5 分钟内指标名称为 node_cpu_seconds_totaljob 标签值为 prometheus 的所有时间序列:

bash
node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}[1m]

时间位移操作

在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:

bash
node_cpu_seconds_total{} # 瞬时向量表达式,选择当前最新的数据 node_cpu_seconds_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据

而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为 offset

例如,以下表达式返回相对于当前查询时间过去 5 分钟的 node_cpu_seconds_total 值:

bash
node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"} offset 5m

注意:offset 关键字需要紧跟在选择器{}后面。以下表达式是正确的:

bash
sum(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"} offset 5m)

下面的表达式是不合法的:

bash
sum(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}) offset 5m

该操作同样适用于区间向量。以下表达式返回指标 node_cpu_seconds_total 一周前的 5 分钟之内的 cpu 空闲率:

bash
rate(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}[5m] offset 1w)

sum是聚合运算符,rate是内置函数

PromQL二元运算符

Prometheus 的查询语言支持基本的逻辑运算和算术运算。对于两个瞬时向量, 匹配行为可以被改变。

算术二元运算符

在 Prometheus 系统中支持下面的二元算术运算符:

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • %
  • ^ 幂等

二元运算操作符支持 scalar/scalar(标量/标量)vector/scalar(瞬时向量/标量)、和 vector/vector(瞬时向量/瞬时向量) 之间的操作。

在两个标量之间进行数学运算,得到的结果也是标量。

表达式:

bash
(63+3)*3

瞬时向量和标量之间进行算数运算时,算术运算符会一次作用与瞬时向量中的每一个样本值,从而得到一组新的时间序列

例如:我们通过监控指标node_memory_MemTotal_bytes(主机内存总大小)单位为byte,如果换成mb时。

表达式:

bash
node_memory_MemTotal_bytes/(1024*1024)

瞬时向量与瞬时向量之间进行数学运算时,过程会相对复杂一点,

运算符会依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。同时新的时间序列将不会包含指标名称。

例如,如果我们 node_memory_MemAvailable_bytes(可用内存) 和 node_memory_MemTotal_bytes(总内存) 获取内存可用率%,可以使用如下表达式:

bash
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100

案例 幂运算

bash
process_open_fds ^ 3

关系运算符

目前,Prometheus 支持以下关系运算符:

  • == (相等)
  • != (不相等)
  • > (大于)
  • < (小于)
  • >= (大于等于)
  • <= (小于等于)

关系运算符被应用于 scalar/scalar(标量/标量)vector/scalar(瞬时向量/标量),和vector/vector(瞬时向量/瞬时向量)。默认情况下关系运算符只会根据时间序列中样本的值,对时间序列进行过滤。我们可以通过在运算符后面使用 bool 修饰符来改变关系运算的默认行为。使用 bool 修改符后,关系运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果 0 或者 1

在两个标量之间进行关系运算,必须提供 bool 修饰符,得到的结果也是标量,即 0false)或 1true)。

例如:

bash
2 > bool 1 # 结果为 1

瞬时向量和标量之间的关系运算,这个运算符会应用到某个当前时刻的每个时序数据上,如果一个时序数据的样本值与这个标量比较的结果是 false,则这个时序数据被丢弃掉,如果是 true, 则这个时序数据被保留在结果中。如果提供了 bool 修饰符,那么比较结果是 0 的时序数据被丢弃掉,而比较结果是 1 的时序数据被保留。

例如:

bash
node_load1 > 1 # 结果为 true 或 false node_load1 > bool 1 # 结果为 1 或 0 up == 1 up !=1

瞬时向量与瞬时向量直接进行关系运算时,同样遵循默认的匹配模式:依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行相应的操作,如果没找到匹配元素,或者计算结果为 false,则直接丢弃。如果匹配上了,则将左边向量的度量指标和标签的样本数据写入瞬时向量。如果提供了 bool 修饰符,那么比较结果是 0 的时序数据被丢弃掉,而比较结果是 1 的时序数据(只保留左边向量)被保留。

例如:

bash
node_memory_MemAvailable_bytes > bool node_memory_MemTotal_bytes 或 node_memory_MemAvailable_bytes < bool node_memory_MemTotal_bytes

集合运算符

使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。 通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。目前,Prometheus 支持以下集合运算符:

  • and (并且)
  • or (或者)
  • unless (排除)

vector1 and vector2 会产生一个由vector1的元素组成的新的向量。该向量包含vector1中完全匹配vector2中的元素。。

vector1 or vector2 会产生一个新的向量,该向量包含vector1的所有原始元素(标签集+值)的向量,以及vector2中没有与vector1匹配标签集的所有元素。

vector1 unless vector2 会产生一个由vector1的元素组成的向量,而这些元素在vector2中没有与标签集完全匹配的元素,两个向量中的所有匹配元素都被删除。

and表达式:

bash
node_cpu_seconds_total{mode=~"idle|user|system"} and node_cpu_seconds_total{mode=~"user|system|iowait"}

时钟不同步触发器

bash
min_over_time(node_timex_sync_status[1m]) == 0 and node_timex_maxerror_seconds >= 16

or表达式

bash
node_cpu_seconds_total{mode=~"idle|user|system"} or node_cpu_seconds_total{mode=~"user|system|iowait"}

状态码非200-399触发器

bash
probe_http_status_code <= 199 OR probe_http_status_code >= 400

unless表达式

bash
node_cpu_seconds_total{mode=~"idle|user|system"} unless node_cpu_seconds_total{mode=~"user|system|iowait"}

聚合操作

Prometheus 还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个具有较少样本值的新的时间序列。

  • sum (求和)
  • min (最小值)
  • max (最大值)
  • avg (平均值)
  • stddev (标准差)
  • stdvar (标准差异)
  • count (计数)
  • count_values (对 value 进行计数)
  • bottomk (样本值最小的 k 个元素)
  • topk (样本值最大的k个元素)
  • quantile (分布统计)

这些操作符被用于聚合所有标签维度,或者通过 without 或者 by 子语句来保留不同的维度。

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

其中只有 count_values, quantile, topk, bottomk 支持参数(parameter)。

without(排除标签名称)

by(保留标签名称): 类似sql的:goup by

sum结果求和

表达式:

bash
sum(node_cpu_seconds_total) without (cpu,job,mode)

等价于

bash
sum(node_cpu_seconds_total) by (instance)

计算prometheus http请求总量,表达式:

bash
sum(prometheus_http_requests_total)

max 最大值

bash
max(node_cpu_seconds_total) by (mode)

avg 平均值

bash
avg(node_cpu_seconds_total) by (mode)

cpu负载> 80%触发器

bash
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100) > 80

count(统计数量)

bash
count(prometheus_http_requests_total)

bottomk (统计最小的几个值)

bash
bottomk(3, sum(node_cpu_seconds_total) by (mode))

topk (统计最大的几个值)

类似sql:ORDER BY vaule DESC limit 3

bash
topk(3, sum(node_cpu_seconds_total) by (mode))

基于时间聚合

前面我们已经学习了如何使用 sum()avg() 和相关的聚合运算符从标签维度进行聚合,这些运算符在一个时间内对多个序列进行聚合,但是有时候我们可能想在每个序列中按时间进行聚合,例如,使尖锐的曲线更平滑,或深入了解一个序列在一段时间内的最大值。

为了基于时间来计算这些聚合,PromQL 提供了一些与标签聚合运算符类似的函数,但是在这些函数名前面附加了 _over_time()

  • avg_over_time(range-vector):区间向量内每个指标的平均值。
  • min_over_time(range-vector):区间向量内每个指标的最小值。
  • max_over_time(range-vector):区间向量内每个指标的最大值。
  • sum_over_time(range-vector):区间向量内每个指标的求和。
  • count_over_time(range-vector):区间向量内每个指标的样本数据个数。
  • quantile_over_time(scalar, range-vector):区间向量内每个指标的样本数据值分位数。
  • stddev_over_time(range-vector):区间向量内每个指标的总体标准差。
  • stdvar_over_time(range-vector):区间向量内每个指标的总体标准方差。

max_over_time:MySQL运行的线程过多触发器,1分钟最大的值

bash
max_over_time(mysql_global_status_threads_running[1m]) > 20

avg_over_time:HTTP请求慢告警触发器,1分钟平均的值

bash
avg_over_time(probe_duration_seconds[1m]) > 1

min_over_time:时钟不同步告警触发器,1分钟最小的值

bash
min_over_time(node_timex_sync_status[1m]) == 0

向量匹配

在标量和瞬时向量之间使用运算符可以满足很多需求,但是在两个瞬时向量之间使用运算符时,哪些样本应该适用于哪些其他样本?这种瞬时向量的匹配称为向量匹配。Prometheus提供了两种基本的向量匹配模式:one-to-one向量匹配和many-to-one(one-to-many)向量匹配。

接下来将介绍在 PromQL 中有两种典型的匹配模式:一对一(one-to-one),多对一(many-to-one)或一对多(one-to-many)。

一对一(one-to-one)

一对一匹配模式会从操作符两边表达式获取的瞬时向量依次比较并找到唯一匹配(标签完全一致)的样本值。默认情况下

使用表达式:

bash
vector1 <operator> vector2

例如当存在样本:

process_open_fds{instance="Prometheus服务器", job="node-exporter"} 9 process_max_fds{instance="Prometheus服务器", job="node-exporter"} 1048576

使用 PromQL 案例:

process_open_fds{instance="Prometheus服务器", job="node-exporter"} / process_max_fds{instance="Prometheus服务器", job="node-exporter"}

结果如下

{instance="Prometheus服务器", job="node-exporter"} 0.00000858306884765625

在操作符两边表达式标签不一致的情况下,可以使用 on(label list) 或者 ignoring(label list)来修改便签的匹配行为。使用 ignoreing 可以在匹配时忽略某些便签。而 on 则用于将匹配行为限定在某些便签之内。

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

例如

image-20240828152012271

表达式

sum by(instance, job)(rate(node_cpu_seconds_total{mode="idle"}[5m]))

表达式

bash
sum by(instance)(rate(node_cpu_seconds_total[5m]))

使用on表达式:

sum by(instance, job)(rate(node_cpu_seconds_total{mode="idle"}[5m])) / on(instance) sum by(instance)(rate(node_cpu_seconds_total[5m]))

使用ignoring表达式

sum by(instance)(rate(node_cpu_seconds_total[5m])) / ignoring(job) sum by(instance, job)(rate(node_cpu_seconds_total{mode="idle"}[5m]))

多对一和一对多

多对一和一对多的匹配模式,可以理解为向量元素中的一个样本数据匹配到了多个样本数据标签。在使用该匹配模式时,需要使用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>

多对一和一对多两种模式一定是出现在操作符两侧表达式返回的向量标签不一致的情况。因此需要使用 ignoring 和 on 修饰符来排除或者限定匹配的标签列表。

使用group_left指定左侧操作数组中可以有多个匹配样本

例如,表达式:

sum without(cpu)(rate(node_cpu_seconds_total[5m])) / ignoring(mode) group_left sum without(mode, cpu)(rate(node_cpu_seconds_total[5m]))

二元运算符优先级

在 Prometheus 系统中,二元运算符优先级从高到低的顺序为:

  1. ^
  2. *, /, %
  3. +, -
  4. ==, !=, <=, <, >=, >
  5. and, unless
  6. or

具有相同优先级的运算符是满足结合律的(左结合)。例如,2 * 3 % 2 等价于 (2 * 3) % 2。运算符 ^ 例外,^ 满足的是右结合,例如,2 ^ 3 ^ 2 等价于 2 ^ (3 ^ 2)

PromQL内置函数

数学函数

数学函数对瞬时向量执行标准的数学运算,如计算绝对值或取对数。瞬时向量中的每个样本都是独立处理的,并且在返回值中删除指标名称。 (1)abs() 该函数输入瞬时向量,返回其每个值的绝对值。例如,对于表达式process_open_fds,调试后返回信息为:

process_open_fds{instance="localhost:9090",job="prometheus"}

使用函数表达式abs(process_open_fds-19)abs(process_open_fds-17)求绝对值后返回信息为:

{instance="localhost:9090",job="prometheus"}

(2)sqrt() 该函数返回瞬时向量中值的平方根,例如表达式sqrt(vector(25)),返回结果为:

{} 5

(3)round()

该函数将瞬时向量中的值四舍五入到最近的整数。例如表达式round(vector(7.5)),返回结果为:

{} 8

时间函数

Prometheus使用的是协调世界时(UTC),没有时区的概念。为了使用户在使用中不用自己实现与日期相关的逻辑,Prometheus提供了一些时间函数。 (1)time() 该函数是最基本的时间函数,它将查询的计算时间以秒为单位返回。

例如,查看进程运行了多长时间,可以使用表达式:

time()-process_start_time_seconds

结果

{instance="localhost:9090", job="prometheus"} 3137.62700009346 {instance="node_exporter:9100", job="node-exporter"} 3138.367000102997

触发器案例:证书还有30天到期

probe_ssl_earliest_cert_expiry - time() < 86400 * 30

计算Counter指标增长率函数

我们知道Counter类型的监控指标其特点是只增不减,在没有发生重置(如服务器重启,应用重启)的情况下其样本值应该是不断增大的。为了能够更直观

++的表示样本数据的变化剧烈情况,需要计算样本的增长速率。

increase(v range-vector)函数是PromQL中提供的众多内置函数之一。其中参数v是一个区间向量,increase函数获取区间向量中的第一个后最后一个样本并返回其增长量。因此,可以通过以下表达式Counter类型指标的增长率:

increase(node_load1[2m]) / 120

这里通过node_cpu[2m]获取时间序列最近两分钟的所有样本,increase计算出最近两分钟的增长量,最后除以时间120秒得到node_cpu样本在最近两分钟的平均增长率。并且这个值也近似于主机节点最近两分钟内的平均CPU使用率。

除了使用increase函数以外,PromQL中还直接内置了rate(v range-vector)函数,rate函数可以直接计算区间向量v在时间窗口内平均增长速率。因此,通过以下表达式可以得到与increase函数相同的结果:

rate(node_load1[2m])

需要注意的是使用rate或者increase函数去计算样本的平均增长速率,容易陷入“长尾问题”当中,其无法反应在时间窗口内样本数据的突发变化。 例如,对于主机而言在2分钟的时间窗口内,可能在某一个由于访问量或者其它问题导致CPU占用100%的情况,但是通过计算在时间窗口内的平均增长率却无法反应出该问题。

为了解决该问题,PromQL提供了另外一个灵敏度更高的函数irate(v range-vector)。irate同样用于计算区间向量的计算率,但是其反应出的是瞬时增长率。irate函数是通过区间向量中最后两个样本数据来计算区间向量的增长速率。这种方式可以避免在时间窗口范围内的“长尾问题”,并且体现出更好的灵敏度,通过irate函数绘制的图标能够更好的反应样本数据的瞬时变化状态。

irate(node_load1[2m])

irate函数相比于rate函数提供了更高的灵敏度,不过当需要分析长期趋势或者在告警规则中,irate的这种灵敏度反而容易造成干扰。因此在长期趋势分析或者告警中更推荐使用rate函数。

预测Gauge指标变化趋势函数

在一般情况下,系统管理员为了确保业务的持续可用运行,会针对服务器的资源设置相应的告警阈值。例如,当磁盘空间只剩512MB时向相关人员发送告警通知。 这种基于阈值的告警模式对于当资源用量是平滑增长的情况下是能够有效的工作的。 但是如果资源不是平滑变化的呢? 比如有些某些业务增长,存储空间的增长速率提升了高几倍。这时,如果基于原有阈值去触发告警,当系统管理员接收到告警以后可能还没来得及去处理问题,系统就已经不可用了。 因此阈值通常来说不是固定的,需要定期进行调整才能保证该告警阈值能够发挥去作用。 那么还有没有更好的方法吗?

PromQL中内置的predict_linear(v range-vector, t scalar) 函数可以帮助系统管理员更好的处理此类情况,predict_linear函数可以预测时间序列v在t秒后的值。它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。例如,基于1小时的样本数据,来预测主机可用磁盘空间的是否在24个小时候被占满,可以使用如下表达式:

predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs"}[1h], 24 * 3600) < 0

node_exporter触发器解释

(node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes < 10 and ON (instance, device, mountpoint) predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs"}[1h], 24 * 3600) < 0 and ON (instance, device, mountpoint) node_filesystem_readonly == 0

磁盘可用率<10% 并且 基于1小时的样本数据,来预测主机可用磁盘空间的是否在24个小时候被占满 并且 文件系统不等于只读

node_filesystem_readonly :只读文件系统

node_filesystem_avail_bytes: 磁盘剩余空间大小(字节)

node_filesystem_size_bytes: 磁盘总大小(字节)

标签操作函数

一般来说来说,使用PromQL查询到时间序列后,可视化工具会根据时间序列的标签来渲染图表。例如通过up指标可以获取到当前所有运行的Exporter实例以及其状态:

up{instance="192.168.1.199", job="blackbox_icmp"} 1 up{instance="192.168.1.199:22", job="blackbox_tcp"} 1 up{instance="192.168.1.199:9090", job="blackbox_tcp"} 1 up{instance="192.168.1.200", job="blackbox_icmp"} 1 up{instance="192.168.1.200:8081", job="springboot-demo"} 1 up{instance="192.168.1.200:9222", job="domain"} 1 up{instance="192.168.1.200:9256", job="process"} 1

这是可视化工具渲染图标时可能根据,instance和job的值进行渲染,为了能够让客户端的图标更具有可读性,可以通过label_replace标签为时间序列添加额外的标签。label_replace的具体参数如下:

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)

该函数会依次对v中的每一条时间序列进行处理,通过regex匹配src_label的值,并将匹配部分relacement写入到dst_label标签中。如下所示:

label_replace(up, "host", "$1", "instance", "(.*):.*")

函数处理后,时间序列将包含一个host标签,host标签的值为Exporter实例的IP地址:

up{instance="192.168.1.199", job="blackbox_icmp"} 1 up{host="192.168.1.199", instance="192.168.1.199:22", job="blackbox_tcp"} 1 up{host="192.168.1.199", instance="192.168.1.199:9090", job="blackbox_tcp"} 1 up{instance="192.168.1.200", job="blackbox_icmp"} 1 up{host="192.168.1.200", instance="192.168.1.200:8081", job="springboot-demo"} 1 up{host="192.168.1.200", instance="192.168.1.200:9222", job="domain"} 1 up{host="192.168.1.200", instance="192.168.1.200:9256", job="process"} 1

除了label_replace以外,Prometheus还提供了label_join函数,该函数可以将时间序列中v多个标签src_label的值,通过separator作为连接符写入到一个新的标签dst_label中:

label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)

表达式:

up{instance="192.168.1.199", job="blackbox_icmp"}

使用label_join表达式:

label_join(up{instance="192.168.1.199", job="blackbox_icmp"},"ip",",","job")

label_replace和label_join函数提供了对时间序列标签的自定义能力,从而能够更好的于客户端或者可视化工具配合。

除了上文介绍的这些内置函数以外,PromQL还提供了大量的其它内置函数。可以阅读 官方文档

prometheus告警

告警能力在Prometheus的架构中被划分成两个独立的部分。通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。

Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如当接收到大量重复告警时能够消除重复的告警信息,同时对告警信息进行分组并且路由到正确的通知方,Prometheus内置了对邮件,Slack等多种通知方式的支持,同时还支持与Webhook的集成,以支持更多定制化的场景。例如,目前还不支持钉钉,那用户完全可以通过Webhook与钉钉机器人进行集成,从而通过钉钉接收告警信息。同时AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。

Alertmanager除了提供基本的告警通知能力以外,还主要提供了如:分组、抑制以及静默等告警特性:

分组

分组机制可以将详细的告警信息合并成一个通知。在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位。

例如,当集群中有数百个正在运行的服务实例,并且为每一个实例设置了告警规则。假如此时发生了网络故障,可能导致大量的服务实例无法连接到数据库,结果就会有数百个告警被发送到Alertmanager。

而作为用户,可能只希望能够在一个通知中就能查看哪些服务实例收到影响。这时可以按照服务所在集群或者告警名称对告警进行分组,而将这些告警内聚在一起成为一个通知。

告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。

抑制 抑制是指当某一告警发出后,可以停止重复发送由此告警引发的其它告警的机制。

例如,当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。

抑制机制同样通过Alertmanager的配置文件进行设置。

静默 静默提供了一个简单的机制可以快速根据标签对告警进行静默处理。如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。

静默设置需要在Alertmanager的Werb页面上进行设置。

Alertmanager配置

Alertmanager主要负责对Prometheus产生的告警进行统一处理,因此在Alertmanager配置中一般会包含以下几个主要部分:

  • 全局配置(global):用于定义一些全局的公共参数,如全局的SMTP配置,Slack配置等内容;
  • 模板(templates):用于定义告警通知时的模板,如HTML模板,邮件模板等;
  • 告警路由(route):根据标签匹配,确定当前告警应该如何处理;
  • 接收人(receivers):接收人是一个抽象的概念,它可以是一个邮箱也可以是微信,Slack或者Webhook等,接收人一般配合告警路由使用;
  • 抑制规则(inhibit_rules):合理设置抑制规则可以减少垃圾告警的产生

其完整配置格式如下:

global: [ resolve_timeout: <duration> | default = 5m ] [ smtp_from: <tmpl_string> ] [ smtp_smarthost: <string> ] [ smtp_hello: <string> | default = "localhost" ] [ smtp_auth_username: <string> ] [ smtp_auth_password: <secret> ] [ smtp_auth_identity: <string> ] [ smtp_auth_secret: <secret> ] [ smtp_require_tls: <bool> | default = true ] [ slack_api_url: <secret> ] [ victorops_api_key: <secret> ] [ victorops_api_url: <string> | default = "https://alert.victorops.com/integrations/generic/20131114/alert/" ] [ pagerduty_url: <string> | default = "https://events.pagerduty.com/v2/enqueue" ] [ opsgenie_api_key: <secret> ] [ opsgenie_api_url: <string> | default = "https://api.opsgenie.com/" ] [ hipchat_api_url: <string> | default = "https://api.hipchat.com/" ] [ hipchat_auth_token: <secret> ] [ wechat_api_url: <string> | default = "https://qyapi.weixin.qq.com/cgi-bin/" ] [ wechat_api_secret: <secret> ] [ wechat_api_corp_id: <string> ] [ http_config: <http_config> ] templates: [ - <filepath> ... ] route: <route> receivers: - <receiver> ... inhibit_rules: [ - <inhibit_rule> ... ]

在全局配置中需要注意的是resolve_timeout,该参数定义了当Alertmanager持续多长时间未接收到告警后标记告警状态为resolved(已解决)。该参数的定义可能会影响到告警恢复通知的接收时间,读者可根据自己的实际场景进行定义,其默认值为5分钟。在接下来的部分,我们将已一些实际的例子解释Alertmanager的其它配置内容。

Prometheus告警规则

Prometheus中的告警规则允许你基于PromQL表达式定义告警触发条件,Prometheus后端对这些触发规则进行周期性计算,当满足触发条件后则会触发告警通知。默认情况下,用户可以通过Prometheus的Web界面查看这些告警规则以及告警的触发状态。当Promthues与Alertmanager关联之后,可以将告警发送到外部服务如Alertmanager中并通过Alertmanager可以对这些告警进行进一步的处理。告警规则是配置在prometheus服务器。

与Alertmanager关联

Prometheus把产生的告警发送给Alertmanager进行告警处理时,需要在Prometheus使用的配置文件中添加关联Alertmanager组件的对应配置内容。

1)编辑prometheus.yml文件加入关联Alertmanager组件的访问地址,示例如下:

# Alertmanager 配置 alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093']

2)添加监控Alertmanager,让Prometheus去收集Alertmanager的监控指标。

- job_name: 'alertmanager' # 覆盖全局默认值,每15秒从该作业中刮取一次目标 scrape_interval: 15s static_configs: - targets: ['alertmanager:9093']

3)重启prometheus

curl -X POST http://localhost:9090/-/reload

配置告警规则

Prometheus添加配置

- job_name: 'node-exporter' scrape_interval: 15s static_configs: - targets: ['node_exporter:9100'] labels: instance: Prometheus服务器

创建告警规则文件

#进入到prometheus docker安装目录 cd /data/docker/docker-prometheus vim prometheus/alert.yml

告警规则配置如下:

yaml
groups: - name: Prometheus alert rules: # 对任何实例超过1分钟无法联系的情况发出警报 - alert: 服务告警 expr: up == 0 for: 1m labels: severity: critical annotations: summary: "服务异常,实例:{{ $labels.instance }}" description: "{{ $labels.job }} 服务已关闭"

在告警规则文件中,我们可以将一组相关的规则设置定义在一个group下。在每一个group中我们可以定义多个告警规则(rule)。一条告警规则主要由以下几部分组成:

  • alert:告警规则的名称。
  • expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
  • for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。
  • labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。
  • annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager。

指定加载告警规则

为了能够让Prometheus能够启用定义的告警规则,我们需要在Prometheus全局配置文件中通过rule_files指定一组告警规则文件的访问路径,Prometheus启动后会自动扫描这些路径下规则文件中定义的内容,并且根据这些规则计算是否向外部发送通知:

格式:

rule_files: [ - <filepath_glob> ... ]

具体配置

# 报警(触发器)配置 rule_files: - "alert.yml" - "rules/*.yml"

重载配置文件

curl -X POST http://localhost:9090/-/reload

查看告警状态

重启Prometheus后,用户可以通过Prometheus WEB界面中的 Alerts 菜单查看当前Prometheus下的所有告警规则,以及其当前所处的活动状态。

同时对于已经pending或者firing的告警,Prometheus也会将它们存储到时间序列ALERTS{}中。

可以通过表达式,查询告警实例:

ALERTS{}

样本值为1表示当前告警处于活动状态(pending或者firing),当告警从活动状态转换为非活动状态时,样本值则为0。

163邮箱告警

获取邮箱授权码并开启smtp服务

  1. https://mail.163.com/ 登陆自己的163账号
  2. pop3/smtp/imap服务,点开启。弹出来扫描二维码点框。手机扫描发送短信。获取授权码。复制授权码。就是用于第三方登录163邮箱的密码

修改alertmanager配置文件

yaml
# 进入目录 cd /data/docker/docker-prometheus # 编辑配置文件 vim alertmanager/alertmanager.yml #填入如下内容: global: #163服务器 smtp_smarthost: 'smtp.163.com:465' #发邮件的邮箱 smtp_from: '[email protected]' #发邮件的邮箱用户名,也就是你的邮箱      smtp_auth_username: '[email protected]' #发邮件的邮箱密码 smtp_auth_password: 'your-password' #tls验证配置,false为关闭 smtp_require_tls: false route: group_by: ['alertname'] # 当收到告警的时候,等待group_wait配置的时间10s,看是否还有告警,如果有就一起发出去 group_wait: 10s # 如果上次告警信息发送成功,此时又来了一个新的告警数据,则需要等待group_interval配置的时间才可以发送出去 group_interval: 10s # 如果上次告警信息发送成功,且问题没有解决,则等待 repeat_interval配置的时间再次发送告警数据 repeat_interval: 4h # 全局报警组,这个参数是必选的,和下面报警组名要相同 receiver: 'email' receivers: - name: 'email' #收邮件的邮箱 email_configs: - to: '[email protected]' send_resolved: true inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname', 'dev', 'instance']

多个收邮件的邮箱账号配置,如下:

yaml
receivers: - name: 'email' #收邮件的邮箱 email_configs: - to: '[email protected]' - to: '[email protected]' - to: '[email protected]'

重启alertmanager或重新加载配置文件

bash
curl -X POST http://localhost:9093/-/reload

访问告警模块的web页面 http://192.168.1.199:9090/alerts

  • INACTIVE:活跃中,即表示正常无告警产生。
  • PENDING:待触发,表示已经达到预设的阈值,但没达到预设的时间。
  • FIRING:表示达到预设的阈值并超过预设的时间触发告警

使用模版(非必需)

创建目录

bash
cd /data/docker/docker-prometheus mkdir alertmanager/template

创建模板文件

yaml
cat > alertmanager/template/email.tmpl <<'EOF' {{ define "email.html" }} {{- if gt (len .Alerts.Firing) 0 -}}{{ range .Alerts }} <h2>@告警通知</h2> 告警程序: prometheus_alert <br> 告警级别: {{ .Labels.severity }} <br> 告警类型: {{ .Labels.alertname }} <br> 故障主机: {{ .Labels.instance }} <br> 告警主题: {{ .Annotations.summary }} <br> 告警详情: {{ .Annotations.description }} <br> 触发时间: {{ .StartsAt.Local.Format "2006-01-02 15:04:05" }} <br> {{ end }}{{ end -}} {{- if gt (len .Alerts.Resolved) 0 -}}{{ range .Alerts }} <h2>@告警恢复</h2> 告警程序: prometheus_alert <br> 故障主机: {{ .Labels.instance }}<br> 故障主题: {{ .Annotations.summary }}<br> 告警详情: {{ .Annotations.description }}<br> 告警时间: {{ .StartsAt.Local.Format "2006-01-02 15:04:05" }}<br> 恢复时间: {{ .EndsAt.Local.Format "2006-01-02 15:04:05" }}<br> {{ end }}{{ end -}} {{- end }} EOF

修改alertmanager配置,增加html这行

yaml
vim alertmanager/config.yml #模版配置 templates: - '/etc/alertmanager/template/*.tmpl' .... receivers: - name: 'email' #收邮件的邮箱 email_configs: - to: '[email protected]' #发送邮件的内容(调用模板文件中的) html: '{{ template "email.html" .}}' send_resolved: true

重载配置

bash
curl -X POST http://localhost:9093/-/reload

本文作者:柯南

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!