一、prometheus介绍
Prometheus是一个开源系统监控和警报工具包,受启发于Google的Brogmon监控系统(相似的Kubernetes是从Google的Brog系统演变而来),从2012年开始由前Google工程师在Soundcloud以开源软件的形式进行研发,并且于2015年早期对外发布早期版本。2016年5月继Kubernetes之后成为第二个正式加入CNCF基金会的项目,同年6月正式发布1.0版本。2017年底发布了基于全新存储层的2.0版本。能更好地与容器平台、云平台配合
二、prometheus特点:
三、核心组件
四、基础架构
从这个架构图,也可以看出Prometheus的主要模块包含,Server,Exporters,Pushgateway,PromQL,Alertmanager,WebUl等。 它大致使用逻辑是这样:
五、Prometheus 与 Zabbix 的对比
Zabbix | Prometheus |
---|---|
后端用C开发,界面用PHP开发,定制化难度很高 | 后端用 golang 开发,前端是 Grafana,JSON 编辑即可解决定制化难度较低 |
6.0支持单个Zabbix实例监控超过10万个业务服务 | 支持更大的集群规模,速度也更快 |
更适合监控物理机环境(物理主机,交换机,网络等监控) | 更适合云环境的监控,对 OpenStack, Kubernetes 有更好的集成 |
监控数据存储在关系型数据库内,如 MySQL,很难从现有数据中扩展维度 | 监控数据存储在基于时间序列的数据库内,便于对已有数据进行新的聚合。十万级监控数据,Prometheus 数据查询速率比 Zabbix 更快 |
安装简单,zabbix-server 一个软件包中包含了所有的服务端功能 | 安装相对复杂,监控、告警和界面都分属于不同的组件 |
图形化界面比较成熟,界面上基本能完成全部的配置操作 | 界面相对较弱,很多配置需要修改配置文件 |
发展时间更长,对于很多监控场景,都有线程的解决方案 | 2015年后开始快速发展,发展时间短,但现在也非常的成熟 |
安装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 用户:
bashuseradd -M -s /usr/sbin/nologin prometheus
更改 prometheus 用户的文件夹权限:
bashchown prometheus:prometheus -R /data/prometheus/prometheus
创建 systemd 服务:
bashcat > /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
bashsystemctl start prometheus
查看状态
bashsystemctl status prometheus
访问地址
应用 | 访问地址 | 备注 |
---|---|---|
Prometheus | http://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服务:
bashcat > /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
bashsystemctl start alertmanager
查看状态
bashsystemctl status alertmanager
访问地址:
应用 | 访问地址 |
---|---|
alertmanager | http://192.168.1.199:9093/ |
修改Prometheus配置
加入alertmanager
yamlvim /data/prometheus/prometheus/prometheus.yml
alerting:
alertmanagers:
- static_configs:
- targets:
- localhost:9093
rule_files:
- "alert.yml"
增加触发器配置文件
yamlcat > /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
检查配置
bashcd /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服务:
bashcat > /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
bashsystemctl start grafana
查看状态
bashsystemctl status grafana
访问地址:
应用 | 访问地址 | 账号 | 密码 |
---|---|---|---|
grafana | http://192.168.1.199:3000/ | admin | admin |
安装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服务:
bashcat > /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
启动服务
bashsystemctl start node_exporter
查看服务状态
bashsystemctl status node_exporter
访问地址:
应用 | 访问地址 |
---|---|
node_exporter | http://192.168.1.199:9100/metrics |
修改配置
yamlcat >> /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
重载配置
bashcurl -X POST http://localhost:9090/-/reload
创建prometheus监控文件夹
bashmkdir -p /data/docker/docker-prometheus/{grafana,prometheus,alertmanager}
cd /data/docker/docker-prometheus/
创建 alertmanager配置文件
yamlcat > 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超级管理员的密码
bashcat > grafana/config.monitoring << EOF
GF_SECURITY_ADMIN_PASSWORD=admin
GF_USERS_ALLOW_SIGN_UP=false
EOF
创建prometheus配置文件
yamlcat > 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报警文件
yamlcat > 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访问地址
应用 | 访问地址 | 用户名/密码 |
---|---|---|
Prometheus | http://192.168.1.199:9090/ | 无用户和密码 |
granfana | http://192.168.1.199:3000/ | admin/admin |
alertmanager | http://192.168.1.199:9093/ | 无用户和密码 |
node-exporter | http://192.168.1.199:9100/metrics | 无用户和密码 |
登录grafana
应用 | 访问地址 | 用户名 | 密码 |
---|---|---|---|
grafana | http://192.168.1.199:3000/ | admin | admin |
创建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),样本由以下三部分组成:
如下所示:
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)都通过如下格式表示:
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:
bashprocess_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类型的指标其工作方式和计数器一样,只增不减(除非系统发生重置)。常见的监控指标,如 http_requests_total,node_cpu 都是Counter类型的监控指标。一般在定义Counter类型指标的名称时推荐使用 _total
作为后缀
通过Counter指标可以统计HTTP请求数量,请求错误数,接口调用次数等单调递增的数据,同时可结合 increase
和 rate
等函数统计变化速率
例如,通过PromQL内置的聚合rate0函数获取HTTP请求量的评价增长率:
bashrate(prometheus_http_requests_total[5m])
查询当前系统中,访问量前10的HTTP地址:
bashtopk(10, prometheus_http_requests_total)
与Counter不同Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如: node_memory_MemFree_bytes
(主机当前空闲的物理内存大小)、 node_memory_MemAvailable_bytes
(可用内存大小)都是Gauge类型的监控指标。
通过Gauge指标,通过PromQL可以直接查看系统的当前空闲物理内存大小:
bashnode_memory_MemFree_bytes
对于Gauge类型的监控指标,通过PromQL内置函数 delta() 可以获取样本在一段时间内返回的变化情况。例如,计算CPU温度在两个小时内的差异:
bashdelta(cpu_temp_celsius{host="zeus"}[2h])
还可以使用 deriv() 计算样本的线性回归模式,甚至是直接使用 predict_linear() 对数据的变化趋势进行预测。例如,预测系统磁盘空间在4小时之后的剩余情况:
bashpredict_linear(node_filesystem_avail_bytes{}[1h], 4 * 3600)
除了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 叫做 ×(指标名)
,如果 ×
是 histogram
或 summary
类型必需满足以下条件:
x_sum
。x_count
。summary
类型的采样数据的 quantile 应表示为 x{quantile="y"}
。histogram
类型的采样分区统计数据将表示为 x_bucket{le="y"}
。histogram
类型的采样必须包含 x_bucket{le="+Inf"}
,它的值等于 x_count
的值。summary
和 historam
中 quantile
和 le
必须按从小到大顺序排序。概述: 在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 暴露的服务中获取监控指标数据。
bashscrape_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 页面查看当前所有的监控采集任务,以及各个任务下所有实例的状态。
概述:所有可以向 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
里面所有监控样本数据
社区提供的
社区提供的(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直接内置了相应的应用程序,用于向Prometheus直接提供Target数据支持。这样设计的好处是,可以更好地监控各自系统的内部运行状态,同时也适合更多自定义监控指标的项目实施。例如cAdvisor、Kubernetes等,它们均内置了用于向Prometheus提供监控数据的端点。
原始监控目标并不直接支持Prometheus,需要我们使用Prometheus提供的 Client Library 编写该监控目标的监控采集程序,用户可以将该程序独立运行,去获取指定的各类监控数据值。例如,由于Linux操作系统自身并不能直接支持Prometheus,用户无法从操作系统层面上直接提供对Prometheus的支持,因此单独安装Node exporter,还有数据库或网站HTTP应用类等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> <时间戳>
监控样本数据规范
bashmetric_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 的样本必须按照一个组的形式排列,并且每一行必须是唯一的指标名称和标签键值对组合。
环境介绍
主机名 | IP地址 | 系统 | 说明 |
---|---|---|---|
localhost | 192.168.1.199 | CentOS Linux release 7.9.2009 | docker方式安装prometheus |
test | 192.168.1.200 | CentOS Linux release 7.9.2009 | docker方式安装node_exporter对服务器监控 |
环境准备
更换 192.168.1.200 的主机名
bashhostnamectl 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
检查文件
bashcat docker-compose.yml
运行node_exporter
bashdocker-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
创建用户
bashuseradd -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
bashsystemctl 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-exporter | http://192.168.1.200:9100/metrics |
常用的监控指标
cpu采集
bashnode_cpu_seconds_total
名称 | 含义 |
---|---|
node_load1 | 1分钟内cpu负载 |
node_load5 | 5分钟内cpu负载 |
node_load15 | 15分钟内cpu负载 |
内存采集
/proc/meminfo 文件
bashnode_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_bytes | swap内存空闲大小 | |
node_memory_SwapTotal_bytes | swap内存总大小 |
磁盘采集
bashnode_disk_
文件系统采集
bashnode_filesystem_
名称 | 含义 | |
---|---|---|
node_filesystem_avail_bytes | 空闲磁盘大小,单位字节 | /1024/1024=MB,/1024/1024/1024=GB |
node_filesystem_size_bytes | 磁盘总大小 | |
node_filesystem_files_free | 空闲inode大小,单位个 | |
node_filesystem_files | inode总大小,单位个 |
网络采集
bashnode_network_
名称 | 含义 | |
---|---|---|
node_network_transmit_bytes_total | 网络流出流量,单位字节(Byte) | /1024/1024=Mb/s |
node_network_receive_bytes_total | 网络流入流量 |
触发器设置
yamlcd /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
检查
bahscat prometheus/alert.yml
检查配置:
bashdocker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml
重新加载配置:
bashcurl -X POST http://localhost:9090/-/reload
检查
bashhttp://192.168.1.199:9090/alerts
之后就可以在 http://192.168.1.199:3000/ grafana面板查看监控信息了
环境搭建
创建nginx目录
bashmkdir /data/docker/nginx/conf.d -p
cd /data/docker/nginx/conf.d
在 /data/docker/nginx/conf.d
目录里新增加nginx的配置文件
bashcat >> 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
检查
bashcat server.conf
docker-compose安装rabbitmq、nginx、mongo、redis
bashmkdir /data/docker/docker-compose -p
cd /data/docker/docker-compose/
通过cat创建docker-compose.yml文件
yamlcat > 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
运行
bashdocker-compose up -d
检查
bashdocker ps
监控nginx
nginx开启 stub_status
检查是否安装有with-http_stub_status_module模块
bashdocker exec -it nginx nginx -V 2>&1 | grep -o with-http_stub_status_module
with-http_stub_status_module
nginx开启stub_status配置
bashcd /data/docker/nginx/conf.d
vim server.conf
bashserver {
....
location /stub_status {
stub_status on;
access_log off;
#allow nginx_export的ip;
allow 0.0.0.0/0;
deny all;
}
....
}
检查配置
bashdocker exec -it nginx nginx -t
重新加载配置文件
bashdocker 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
参数解释:
docker安装nginx_exporter
通过cat创建docker-compose.yml文件
bashcd /data/docker/nginx/
yamlcat > 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
启动
bashdocker-compose up -d
检查
bashdocker ps
参数解释
Environment variable | 命令行参数 | description |
---|---|---|
-nginx.scrape-uri | nginx stub_status 复制 |
metrics地址
安装好Exporter后会暴露一个 http://ip:port/metrics
的HTTP服务
名称 | 地址 |
---|---|
nginx_exporter | http://192.168.1.200:9113/metrics |
修改prometheus配置
配置prometheus去采集(拉取)nginx_exporter的监控样本数据
yamlcd /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
重新加载配置
bashcurl -X POST http://localhost:9090/-/reload
常用的监控指标
bashnginx_connections_accepted 接收请求数 nginx_connections_active 活动连接数 nginx_connections_handled 成功处理请求数 nginx_connections_reding 正在进行读操作的请求数 nginx_connections_waiting 正在等待的请求数 nginx_connections_writing 正在进行写操作的请求数 nginx_connections_requests 总请求数
添加触发器
bashcd /data/docker/docker-prometheus
yamlcat >> 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
检查配置
bashdocker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml
重新加载配置
bashcurl -X POST http://localhost:9090/-/reload
grafana展示prometheus从nginx_exporter收集到的的数据
https://grafana.com/grafana/dashboards/ 在官网找到合适的nginx仪表盘,点进去拷贝id,在grafana上导入就可以了
docker安装redis_exporter
docker直接运行
bashdocker 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方式
bashcd /data/docker/redis/redis_exporter
yamlcat > 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
启动
bashdocker-compose up -d
检查
bashdocker ps
参数解释
Environment variable | 值 | description |
---|---|---|
REDIS_ADDR | 192.168.1.200:6379 | redis服务器地址,如:ip:6379 |
REDIS_PASSWORD | 123456 | redis服务器管理密码 |
metrics地址
名称 | 地址 | 备注 |
---|---|---|
redis_exporter | http://192.168.1.200:9121/metrics |
配置prometheus
bashcd /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
重新加载配置
bashcurl -X POST http://localhost:9090/-/reload
常用的监控指标
bashredis_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触发器(告警规则)
因为是单机,所以未配置集群的触发器
yamlcat >> 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
检查配置:
bashdocker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml
重载配置
bashcurl -X POST http://localhost:9090/-/reload
grafana展示prometheus从redis_exporter收集到的的数据
在官网找到合适的模板id,在grafana导入就可以了
docker安装
docker直接安装
bashdocker 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方式
bashcat > 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
启动
bashdocker-compose up -d
参数解释
Environment variable | default | description |
---|---|---|
RABBIT_URL | http://127.0.0.1:15672 | rabbitMQ管理插件的url(必须以http(s)://开头) |
RABBIT_USER | guest | rabbitMQ 管理插件的用户名。 |
RABBIT_PASSWORD | guest | rabbitMQ 管理插件的密码。 |
OUTPUT_FORMAT | JSON | 输出格式 |
PUBLISH_PORT | 9419 | 运行端口(监听端口) |
metrics地址
名称 | 地址 | 备注 |
---|---|---|
rabbitmq_exporter | http://192.168.1.200:9419/metrics |
Prometheus配置
配置prometheus去采集(拉取)rabbitmq_exporter的监控样本数据
bashcd /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
常用的监控指标
bashrabbitmq_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 可用的文件描述符总数
触发器配置(告警规则)
也是单节点,未配置集群触发器
yamlcat > 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创建监控用户,权限为“readAnyDatabase”,如果是cluster环境,需要有权限“clusterMonitor”
登录mongodb(docker安装的mongo)
bashdocker 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安装
直接运行
bashdocker 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方式运行
yamlcat > 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.uri | MongoDB 连接 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_exporter | http://192.168.1.200:9216/metrics |
Prometheus配置
yamlcd /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
常用的监控指标
bashmongodb_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单点,所以未配置复制触发器
yamlcat >> 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的stats命令获取到当前主机上运行容器的统计信息,可以查看容器的CPU利用率、内存使用量、网络IO总量以及磁盘IO总量等信息。
bashdocker stats
使用CAdvisor
CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行CAdvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示。
docker命令安装
bashdocker 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安装
yamlmkdir /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
yamlcd /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_10s | gauge | 过去10秒容器CPU的平均负载 |
container_cpu_usage_seconds_total | counter | 容器在每个CPU内核上的累积占用时间 (单位:秒) |
container_cpu_system_seconds_total | counter | System CPU累积占用时间(单位:秒) |
container_cpu_user_seconds_total | counter | User CPU累积占用时间(单位:秒) |
container_fs_usage_bytes | gauge | 容器中文件系统的使用量(单位:字节) |
container_fs_limit_bytes | gauge | 容器可以使用的文件系统总量(单位:字节) |
container_fs_reads_bytes_total | counter | 容器累积读取数据的总量(单位:字节) |
container_fs_writes_bytes_total | counter | 容器累积写入数据的总量(单位:字节) |
container_memory_max_usage_bytes | gauge | 容器的最大内存使用量(单位:字节) |
container_memory_usage_bytes | gauge | 容器当前的内存使用量(单位:字节 |
container_spec_memory_limit_bytes | gauge | 容器的内存使用量限制 |
machine_memory_bytes | gauge | 当前主机的内存总量 |
container_network_receive_bytes_total | counter | 容器网络累积接收数据总量(单位:字节) |
container_network_transmit_bytes_total | counter | 容器网络累积传输数据总量(单位:字节) |
触发器配置
添加docker触发器(告警规则)
yamlcat >> 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
docker-compose安装
yamlmkdir /data/docker/mysql
cd /data/docker/mysql/
通过cat 创建docker-compose.yml文件
yamlcat > 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
bashdocker exec -it mysql mysql -uroot -p
创建用户
bashCREATE USER 'exporter'@'%' IDENTIFIED BY 'password' WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
docker-compose运行
注:latest版本配置方法改变了,指定v0.14.0版本。如下:
yamlmkdir /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配置文件
bashcat > my.cnf << "EOF"
[client]
host=192.168.1.200
user=exporter
password=password
port=3306
EOF
参数解释
Name | MySQL Version | Description |
---|---|---|
collect.auto_increment.columns | 5.1 | 从 information_schema 收集 auto_increment 列和最大值. |
collect.binlog_size | 5.1 | 收集所有注册的binlog文件的当前大小 |
collect.engine_innodb_status | 5.1 | 收集SHOW ENGINE INNODB STATUS |
collect.engine_tokudb_status | 5.6 | 收集SHOW ENGINE TOKUDB STATUS . |
collect.global_status | 5.1 | 收集SHOW GLOBAL STATUS(默认启用) |
collect.global_variables | 5.1 | 收集SHOW GLOBAL VARIABLES(默认启用) |
collect.info_schema.clientstats | 5.5 | 如果以 userstat=1 运行,设置为 true 以收集客户端统计信息 |
collect.info_schema.innodb_metrics | 5.6 | 从 information_schema.innodb_metrics收集指标 |
collect.info_schema.innodb_tablespaces | 5.7 | 从information_schema.innodb_sys_tablespaces收集指标 |
collect.info_schema.innodb_cmp | 5.5 | 从information_schema.innodb_cmp收集 InnoDB 压缩表指标。 |
collect.info_schema.innodb_cmpmem | 5.5 | 从information_schema.innodb_cmpmem缓冲池压缩指标。 |
collect.info_schema.processlist | 5.1 | 从 information_schema.processlist 收集线程状态计数 |
collect.info_schema.processlist.min_time | 5.1 | 线程必须处于要计算的每个状态的最短时间。 (默认值:0) |
collect.info_schema.query_response_time | 5.5 | 如果 query_response_time_stats 为 ON,则收集查询响应时间分布。 |
collect.info_schema.replica_host | 5.6 | 从 information_schema.replica_host_status 收集指标。 |
collect.info_schema.tables | 5.1 | 从information_schema.tables收集指标。 |
collect.info_schema.tables.databases | 5.1 | 要为其收集表统计信息的数据库列表,或为所有 |
collect.info_schema.tablestats | 5.1 | 如果以 userstat=1 运行,设置为 true 以收集表统计信息。 |
collect.info_schema.schemastats | 5.1 | 如果以 userstat=1 运行,设置为 true 以收集架构统计信息 |
collect.info_schema.userstats | 5.1 | 如果以 userstat=1 运行,设置为 true 以收集用户统计信息。 |
collect.mysql.user | 5.5 | 从 mysql.user 表中收集数据 |
collect.perf_schema.eventsstatements | 5.6 | 从 performance_schema.events_statements_summary_by_digest 收集指标。 |
collect.perf_schema.eventsstatements.digest_text_limit | 5.6 | 规范化语句文本的最大长度。 (默认值:120) |
collect.perf_schema.eventsstatements.limit | 5.6 | 按响应时间限制事件语句摘要的数量。 (默认值:250) |
collect.perf_schema.eventsstatements.timelimit | 5.6 | 以秒为单位限制“last_seen”事件语句的存在时间。 (默认值:86400) |
collect.perf_schema.eventsstatementssum | 5.7 | 从 performance_schema.events_statements_summary_by_digest 汇总收集指标。 |
collect.perf_schema.eventswaits | 5.5 | 从 performance_schema.events_waits_summary_global_by_event_name 收集指标 |
collect.perf_schema.file_events | 5.6 | 从 performance_schema.file_summary_by_event_name 收集指标 |
collect.perf_schema.file_instances | 5.5 | 从 performance_schema.file_summary_by_instance 收集指标。 |
collect.perf_schema.file_instances.remove_prefix | 5.5 | 删除 performance_schema.file_summary_by_instance 中的路径前缀。 |
collect.perf_schema.indexiowaits | 5.6 | 从 performance_schema.table_io_waits_summary_by_index_usage 收集指标。 |
collect.perf_schema.memory_events | 5.7 | 从 performance_schema.memory_summary_global_by_event_name 收集指标。 |
collect.perf_schema.memory_events.remove_prefix | 5.7 | 删除 performance_schema.memory_summary_global_by_event_name 中的仪器前缀。 |
collect.perf_schema.tableiowaits | 5.6 | 从 performance_schema.table_io_waits_summary_by_table 收集指标。 |
collect.perf_schema.tablelocks | 5.6 | 从 performance_schema.table_lock_waits_summary_by_table 收集指标。 |
collect.perf_schema.replication_group_members | 5.7 | 从 performance_schema.replication_group_members 收集指标。 |
collect.perf_schema.replication_group_member_stats | 5.7 | 从 performance_schema.replication_group_member_stats 收集指标。 |
collect.perf_schema.replication_applier_status_by_worker | 5.7 | 从 performance_schema.replication_applier_status_by_worker 收集指标。 |
collect.slave_status | 5.1 | 从 SHOW SLAVE STATUS 收集(默认启用) |
collect.slave_hosts | 5.1 | 从 SHOW SLAVE HOSTS 收集 |
collect.heartbeat | 5.1 | 从心跳收集 |
collect.heartbeat.database | 5.1 | 从哪里收集心跳数据的数据库。 (默认:心跳) |
collect.heartbeat.table | 5.1 | 从哪里收集心跳数据的表。 (默认:心跳) |
collect.heartbeat.utc | 5.1 | 使用 UTC 作为当前服务器的时间戳(使用 --utc 调用 pt-heartbeat )。 (默认值:假) |
配置prometheus
bashcd /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
常用监控指标
bashmysql_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文件
yamlcat >> 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
监控java应用(tomcat/jar)
JMX exporter 负责收集 Java 虚拟机信息
bashPROMETHEUS_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 一个项目
bashdocker run -d --restart=always -p 8081:8080 --name springboot-demo linge365/springboot-demo
prometheus配置
yamlcd /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
监控指标
bashprocess_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
添加触发器(告警规则)
yamlcat >> 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
命令来查看对应的进程。
监控所有进程
bashcd /data/docker/process_exporter
cat >>process.yml << "EOF"
process_names:
- name: "{{.Comm}}" # 匹配模板
cmdline:
- '.+' # 匹配所有名称
EOF
监控指定进程
bashprocess_names:
# - name: "{{.Comm}}"
# cmdline:
# - '.+'
- name: "{{.Matches}}"
cmdline:
- 'nginx' #唯一标识
- name: "{{.Matches}}"
cmdline:
- 'mongod'
- name: "{{.Matches}}"
cmdline:
- 'mysqld'
- name: "{{.Matches}}"
cmdline:
- 'redis-server'
docker运行
bashdocker 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设置
bashcd /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_states | Running/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字节数 |
添加触发器
yamlcat > 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证书过期时间。
创建配置文件
yamlmkdir /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直接运行
bashdocker 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启动
bashcd /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的配置
yamlcd /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
监控项
yamlprobe_
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时间戳
触发器
yamlcd /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运行命令
bashdocker run -d --restart=always --name domain_exporter -p 9222:9222 caarlos0/domain_exporter
Prometheus配置
yamlcd /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
常用监控指标
bashdomain_expiry_days 域名到期时间 domain_probe_success 域名检测状态
触发器
yamlcat >> 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
监控流程
exporter
名称 | 监控啥 |
---|---|
node_exporter | Linux服务器的资源用量 |
nginx-prometheus-exporter | nginx |
rabbitmq_exporter | Rabbitmq |
mongodb_exporter | mongodb数据库 |
mysql_exporter | mysql数据库 |
Redis_exporter | redis数据库 |
BlackBox_Exporter | 网络协议:http(get,post)、dns、tcp、icmp,ssl证书过期时间 |
domain_exporter | 域名过期时间 |
cAdvisor | docker容器 |
pom.xml和application.yaml | springboot java应用 |
process-exporter | 进程 |
除了 node_exporter 我们还会根据自己的业务选择安装其他 exporter 或者自己编写,比较常用的 exporter 有
更多 exporter 请参考链接。
Pushgateway 是 Prometheus 生态中一个重要工具,使用它的原因主要是:
由于以上原因,不得不使用 pushgateway,但在使用之前,有必要了解一下它的一些弊端:
up
只针对 pushgateway, 无法做到对每个节点有效。因此,即使你的监控已经下线,prometheus 还会拉取到旧的监控数据,需要手动清理 pushgateway 不要的数据。
docker命令运行
bashdocker run -d -p 9091:9091 --restart=always --name pushgateway prom/pushgateway
docker-compose运行
yamlcat > 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收集到的数据。
yamlcat >> 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"}
添加单条数据:
bashecho "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
删除某个组下的某实例的所有数据:
bashcurl -X DELETE http://192.168.1.199:9091/metrics/job/some_job/instance/some_instance
删除某个组下的所有数据:
bashcurl -X DELETE http://192.168.1.199:9091/metrics/job/some_job
使用python
安装 prometheus_client
模块
bashpip install prometheus_client
python代码
pythonfrom 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脚本
bashcat >> /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脚本
pythoncat >> /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,报警出来
yamlcat >> 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 也提供了与基础设施中的服务发现集成的功能。
Prometheus 已经支持多种内置的服务发现机制:
我们都可以通过 Prometheus 配置文件中的 scrape_config
部分进行配置,Prometheus 会不断更新动态的抓取目标列表,自动停止抓取旧的实例,开始抓取新的实例,Prometheus 特别适合运行于 Kubernetes 集群下面,可以自动发现监控目标。
此外大部分服务发现机制还会提供目标的一些元数据,通常都是带有 __
的前缀, 比如标签、注解、服务名等等,可以在 relabeling 阶段使用这些元数据来过滤修改目标,这些元信息标签在重新标记阶段后被删除。
基于文件的服务发现
除了基于 Consul 的服务发现之外,Prometheus 也允许我们进行自定义的发现集成,可以通过 watch 一组本地文件来获取抓取目标以及标签信息,也就是我们常说的基于文件的服务发现方式。
基于文件的服务发现提供了一种更通用的方式来配置静态目标,并作为一个接口插入自定义服务发现机制。
它读取一组包含零个或多个 <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
的文件,内容如下所示:
yamlcd /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
yamlcat > prometheus/targets/springboot.yml << "EOF"
- targets:
- 192.168.1.200:8081
EOF
blackbox-exporter-http.yml
yamlcat > prometheus/targets/blackbox-exporter-http.yml << "EOF"
- targets:
- https://www.baidu.com
- https://www.jd.com
EOF
blackbox-exporter-tcp.yml
yamlcat > prometheus/targets/blackbox-exporter-tcp.yml << "EOF"
- targets:
- 192.168.1.199:22
- 192.168.1.199:9090
EOF
blackbox-exporter-icmp.yml
yamlcat > prometheus/targets/blackbox-exporter-icmp.yml << "EOF"
- targets:
- 192.168.1.199
- 192.168.1.200
EOF
domain.yml
yamlcat > prometheus/targets/domain.yml << "EOF"
- targets:
- qq.com
- baidu.com
EOF
配置文件服务发现
用于发现的目标文件创建完成后,要让 Prometheus 能够从上面的 targets.yml
文件中自动读取抓取目标,需要在 prometheus.yml
配置文件中的 scrape_configs
部分添加如下所示的抓取配置:
备份文件
bashcp -a prometheus/prometheus.yml{,.bak}
ls -l prometheus/prometheus.yml.bak
创建文件
yamlcat > 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 是由 HashiCorp 开发的一个支持多数据中心的分布式服务发现和键值对存储服务的开源软件,是一个通用的服务发现和注册中心工具,被大量应用于基于微服务的软件架构当中。
我们通过api将exporter服务注册到 Consul,然后配置 Prometheus 从 Consul 中发现实例。关于 Consul 本身的使用可以查看官方文档 https://learn.hashicorp.com/consul 了解更多。
docker安装Consul
bashdocker run -d --name consul -p 8500:8500 consul:1.14.5
docker-compose启动
yamlcat > 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访问地址
通过api注册到Consul
bashcurl -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文件注册
jsonmkdir /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文件注册
bashcurl --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 部分添加如下所示的抓取配置:
备份源文件
bashcd /data/docker/docker-prometheus
cp -a prometheus/prometheus.yml prometheus/prometheus.yml.bak
ls -l prometheus/prometheus.yml.bak
使用cat更新文件内容
yamlcat > 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:
shellcat > /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删除服务
bashcurl --request PUT http://127.0.0.1:8500/v1/agent/service/deregister/<ID>
ConsulManager
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
登录在采集样本数据之前,对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标签信息:
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分组引用(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实例采集上来的样本数据如下所示:
bashnode_load1{instance="test服务器", job="node_exporter"} 0.04
我们希望能有一个额外的标签dc,可以表示该样本所属的数据中心:
bashnode_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"
保留或删除标签,使用 labelkeep
和 labeldrop
这两个操作
案例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 (Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言,语言表现力非常丰富,内置函数很多,在日常数据可视化(Grafana)以及rule 告警中都会使用到它。
PromQL数据类型,在Prometheus的表达式语言中,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
的所有时间序列
bashnode_cpu_seconds_total
可以通过向花括号{}
里附加一组标签来进一步过滤时间序列
例如:选择指标名称为 node_cpu_seconds_total
,instance
标签值为 Prometheus服务器
,mode
标签值为 idle
的时间序列:
bashnode_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}
PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。总共有以下几种标签匹配运算符:
=
: 选择与提供的字符串完全相同的标签。!=
: 选择与提供的字符串不相同的标签。=~
: 选择正则表达式与提供的字符串(或子字符串)相匹配的标签。!~
: 选择正则表达式与提供的字符串(或子字符串)不匹配的标签。例如:选择指标名称为 node_cpu_seconds_total
,mode为 idle
、user
或 system
,cpu!=0
的时间序列:
bashnode_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_total
,job
标签值为 prometheus
的所有时间序列:
bashnode_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}[1m]
时间位移操作
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准:
bashnode_cpu_seconds_total{} # 瞬时向量表达式,选择当前最新的数据
node_cpu_seconds_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据
而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为 offset
。
例如,以下表达式返回相对于当前查询时间过去 5 分钟的 node_cpu_seconds_total
值:
bashnode_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"} offset 5m
注意:offset
关键字需要紧跟在选择器{}
后面。以下表达式是正确的:
bashsum(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"} offset 5m)
下面的表达式是不合法的:
bashsum(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}) offset 5m
该操作同样适用于区间向量。以下表达式返回指标 node_cpu_seconds_total
一周前的 5 分钟之内的 cpu 空闲率:
bashrate(node_cpu_seconds_total{ instance="Prometheus服务器", mode="idle"}[5m] offset 1w)
sum是聚合运算符,rate是内置函数
Prometheus 的查询语言支持基本的逻辑运算和算术运算。对于两个瞬时向量, 匹配行为可以被改变。
在 Prometheus 系统中支持下面的二元算术运算符:
+
加法-
减法*
乘法/
除法%
模^
幂等二元运算操作符支持 scalar/scalar(标量/标量)
、vector/scalar(瞬时向量/标量)
、和 vector/vector(瞬时向量/瞬时向量)
之间的操作。
在两个标量之间进行数学运算,得到的结果也是标量。
表达式:
bash(63+3)*3
瞬时向量和标量之间进行算数运算时,算术运算符会一次作用与瞬时向量中的每一个样本值,从而得到一组新的时间序列
例如:我们通过监控指标node_memory_MemTotal_bytes
(主机内存总大小)单位为byte,如果换成mb时。
表达式:
bashnode_memory_MemTotal_bytes/(1024*1024)
瞬时向量与瞬时向量之间进行数学运算时,过程会相对复杂一点,
运算符会依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。同时新的时间序列将不会包含指标名称。
例如,如果我们 node_memory_MemAvailable_bytes
(可用内存) 和 node_memory_MemTotal_bytes
(总内存) 获取内存可用率%,可以使用如下表达式:
bashnode_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100
案例 幂运算
bashprocess_open_fds ^ 3
关系运算符
目前,Prometheus 支持以下关系运算符:
==
(相等)!=
(不相等)>
(大于)<
(小于)>=
(大于等于)<=
(小于等于)关系运算符被应用于 scalar/scalar(标量/标量)
、vector/scalar(瞬时向量/标量)
,和vector/vector(瞬时向量/瞬时向量)
。默认情况下关系运算符只会根据时间序列中样本的值,对时间序列进行过滤。我们可以通过在运算符后面使用 bool
修饰符来改变关系运算的默认行为。使用 bool 修改符后,关系运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果 0
或者 1
。
在两个标量之间进行关系运算,必须提供 bool 修饰符,得到的结果也是标量,即 0
(false
)或 1
(true
)。
例如:
bash2 > bool 1 # 结果为 1
瞬时向量和标量之间的关系运算,这个运算符会应用到某个当前时刻的每个时序数据上,如果一个时序数据的样本值与这个标量比较的结果是 false
,则这个时序数据被丢弃掉,如果是 true
, 则这个时序数据被保留在结果中。如果提供了 bool 修饰符,那么比较结果是 0
的时序数据被丢弃掉,而比较结果是 1
的时序数据被保留。
例如:
bashnode_load1 > 1 # 结果为 true 或 false
node_load1 > bool 1 # 结果为 1 或 0
up == 1
up !=1
瞬时向量与瞬时向量直接进行关系运算时,同样遵循默认的匹配模式:依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行相应的操作,如果没找到匹配元素,或者计算结果为 false,则直接丢弃。如果匹配上了,则将左边向量的度量指标和标签的样本数据写入瞬时向量。如果提供了 bool 修饰符,那么比较结果是 0
的时序数据被丢弃掉,而比较结果是 1
的时序数据(只保留左边向量)被保留。
例如:
bashnode_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表达式:
bashnode_cpu_seconds_total{mode=~"idle|user|system"} and node_cpu_seconds_total{mode=~"user|system|iowait"}
时钟不同步触发器
bashmin_over_time(node_timex_sync_status[1m]) == 0 and node_timex_maxerror_seconds >= 16
or表达式
bashnode_cpu_seconds_total{mode=~"idle|user|system"} or node_cpu_seconds_total{mode=~"user|system|iowait"}
状态码非200-399触发器
bashprobe_http_status_code <= 199 OR probe_http_status_code >= 400
unless表达式
bashnode_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结果求和
表达式:
bashsum(node_cpu_seconds_total) without (cpu,job,mode)
等价于
bashsum(node_cpu_seconds_total) by (instance)
计算prometheus http请求总量,表达式:
bashsum(prometheus_http_requests_total)
max 最大值
bashmax(node_cpu_seconds_total) by (mode)
avg 平均值
bashavg(node_cpu_seconds_total) by (mode)
cpu负载> 80%触发器
bash100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100) > 80
count(统计数量)
bashcount(prometheus_http_requests_total)
bottomk (统计最小的几个值)
bashbottomk(3, sum(node_cpu_seconds_total) by (mode))
topk (统计最大的几个值)
类似sql:ORDER BY vaule DESC limit 3
bashtopk(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分钟最大的值
bashmax_over_time(mysql_global_status_threads_running[1m]) > 20
avg_over_time:HTTP请求慢告警触发器,1分钟平均的值
bashavg_over_time(probe_duration_seconds[1m]) > 1
min_over_time:时钟不同步告警触发器,1分钟最小的值
bashmin_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)
一对一匹配模式会从操作符两边表达式获取的瞬时向量依次比较并找到唯一匹配(标签完全一致)的样本值。默认情况下
使用表达式:
bashvector1 <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>
例如
表达式
sum by(instance, job)(rate(node_cpu_seconds_total{mode="idle"}[5m]))
表达式
bashsum 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 系统中,二元运算符优先级从高到低的顺序为:
^
*
, /
, %
+
, -
==
, !=
, <=
, <
, >=
, >
and
, unless
or
具有相同优先级的运算符是满足结合律的(左结合)。例如,2 * 3 % 2
等价于 (2 * 3) % 2
。运算符 ^
例外,^
满足的是右结合,例如,2 ^ 3 ^ 2
等价于 2 ^ (3 ^ 2)
。
数学函数
数学函数对瞬时向量执行标准的数学运算,如计算绝对值或取对数。瞬时向量中的每个样本都是独立处理的,并且在返回值中删除指标名称。 (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中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。
Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如当接收到大量重复告警时能够消除重复的告警信息,同时对告警信息进行分组并且路由到正确的通知方,Prometheus内置了对邮件,Slack等多种通知方式的支持,同时还支持与Webhook的集成,以支持更多定制化的场景。例如,目前还不支持钉钉,那用户完全可以通过Webhook与钉钉机器人进行集成,从而通过钉钉接收告警信息。同时AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。
Alertmanager除了提供基本的告警通知能力以外,还主要提供了如:分组、抑制以及静默等告警特性:
分组
分组机制可以将详细的告警信息合并成一个通知。在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位。
例如,当集群中有数百个正在运行的服务实例,并且为每一个实例设置了告警规则。假如此时发生了网络故障,可能导致大量的服务实例无法连接到数据库,结果就会有数百个告警被发送到Alertmanager。
而作为用户,可能只希望能够在一个通知中就能查看哪些服务实例收到影响。这时可以按照服务所在集群或者告警名称对告警进行分组,而将这些告警内聚在一起成为一个通知。
告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。
抑制 抑制是指当某一告警发出后,可以停止重复发送由此告警引发的其它告警的机制。
例如,当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。
抑制机制同样通过Alertmanager的配置文件进行设置。
静默 静默提供了一个简单的机制可以快速根据标签对告警进行静默处理。如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。
静默设置需要在Alertmanager的Werb页面上进行设置。
Alertmanager主要负责对Prometheus产生的告警进行统一处理,因此在Alertmanager配置中一般会包含以下几个主要部分:
其完整配置格式如下:
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
告警规则配置如下:
yamlgroups:
- name: Prometheus alert
rules:
# 对任何实例超过1分钟无法联系的情况发出警报
- alert: 服务告警
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "服务异常,实例:{{ $labels.instance }}"
description: "{{ $labels.job }} 服务已关闭"
在告警规则文件中,我们可以将一组相关的规则设置定义在一个group下。在每一个group中我们可以定义多个告警规则(rule)。一条告警规则主要由以下几部分组成:
指定加载告警规则
为了能够让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。
获取邮箱授权码并开启smtp服务
修改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']
多个收邮件的邮箱账号配置,如下:
yamlreceivers:
- name: 'email'
#收邮件的邮箱
email_configs:
- to: '[email protected]'
- to: '[email protected]'
- to: '[email protected]'
重启alertmanager或重新加载配置文件
bashcurl -X POST http://localhost:9093/-/reload
访问告警模块的web页面 http://192.168.1.199:9090/alerts
使用模版(非必需)
创建目录
bashcd /data/docker/docker-prometheus
mkdir alertmanager/template
创建模板文件
yamlcat > 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这行
yamlvim alertmanager/config.yml
#模版配置
templates:
- '/etc/alertmanager/template/*.tmpl'
....
receivers:
- name: 'email'
#收邮件的邮箱
email_configs:
- to: '[email protected]'
#发送邮件的内容(调用模板文件中的)
html: '{{ template "email.html" .}}'
send_resolved: true
重载配置
bashcurl -X POST http://localhost:9093/-/reload
本文作者:柯南
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!