概述
快速帮你学会Docker+Prometheus+Alertmanager+Grafana搭建告警体系,Prometheus中配置警报规则,将警报发送到Alertmanager,Alertmanager发送通知有多种方式,其内部集成了邮箱、钉钉等多种方式,也提供了webhook的方式来扩展报警通知方式,网上也有大量例子实现对第三方软件的集成,如企业微信、飞书等。本文介绍邮件、钉钉报警方式和通过使用java来搭建webhook自定义通知报警的方式。
Windows安装Docker Desktop
Docker Desktop是Windows上运行Docker的最友好方式。它集成了Docker Engine、CLI 和Kubernetes,让你轻松构建、测试和部署容器应用。
官方资源:
Windows安装系统要求检查
WSL 2端要求:
WSL版本:2.1.5或更高。
Windows 10 64位:Enterprise、Pro或Education版,版本22H2(build 19045)或更高。
Windows 11 64位:Enterprise、Pro或Education版,版本23H2(build 22631)或更高。
启用WSL 2功能(详见下文)。
硬件:支持虚拟化(在BIOS中启用VT-x/AMD-V),至少4GB RAM(推荐8GB+)。
Hyper-V要求:
Windows 10/11:同上,但需启用Hyper-V和Containers功能。
注意:Hyper-V不支持Arm架构,且Windows Home版只能用WSL 2运行Linux容器。
系统要求检查界面——必须先确认你的Windows是否达标。
如果不符合,别慌:升级Windows或用虚拟机试试(但不推荐,可能会导致性能差)。
步骤1:启用WSL 2(推荐后端)
- 以管理员身份打开PowerShell或命令提示符。
- 运行wsl --install(如果已安装,用wsl --update更新)。
- 重启电脑。如果提示错误,检查Microsoft Store是否可用,或从WSL GitHub下载MSI包安装。
验证WSL版本:运行wsl --version。如果显示版本信息,OK!
步骤2:如果用Hyper-V
- 在控制面板 > 程序和功能 > 启用或关闭Windows功能中,勾选Hyper-V和Windows容器
- 重启电脑
下载和安装Docker Desktop
- 从官方下载安装程序
- 双击Docker Desktop Installer.exe运行(通常会安装在C盘,默认安装路径:C:\Program Files\Docker)
# 如果不想安装在C盘,使用以下命令安装到指定位置
"D:\Docker Desktop Installer.exe" install --accept-license --installation-dir="D:\software\Docker"
# 参数解释
"D:\Docker Desktop Installer.exe" 下载Docker Desktop位置
--accept-license:自动接受许可协议
--installation-dir="D:\software\Docker" 指定安装目录
注意:Docker 依赖的一些服务(如 wsl 和 Hyper-V)仍然会安装在 C盘。
- 安装完成后CMD验证Docker是否正常运行
docker --version
- 首次启动初始化设置
首次启动会看到 Docker Desktop 的设置向导,来到登录账号这里,我们可以暂时跳过登录即可。然后就会进入到 Docker Desktop 里面了
- 修改磁盘镜像存储数据
这个目录存储了所有 Docker 数据:包含所有镜像、容器、数据卷。一般来说,至少几十个G,安装到非C盘,可以节省C盘空间,提高性能,便于备份和管理。并且还建议大家一定要修改下面这个目录,这样所有的数据都不会存储在C盘了。
- 配置国内镜像源
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://mirror.ccs.tencentyun.com",
"https://docker.m.daocloud.io",
"https://docker.imgdb.de",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com",
"https://docker.1ms.run",
"https://func.ink",
"https://lispy.org",
"https://docker.xiaogenban1993.com"
]
}
安装Prometheus
# 搜索镜像
docker search prometheus
# 拉取镜像
docker pull prom/prometheus
# 也可以指定镜像版本,例如:docker pull prom/prometheus:v2.41.0
# 准备相关挂载目录及文件
# 在这里就不多讲啦!通过Docker Compose方式一键部署,Grafana、Alertmanager同理
安装Grafana
# 搜索镜像
docker search grafana
# 拉取镜像
docker pull grafana/grafana
# 也可以指定镜像版本,例如:docker pull grafana/grafana:9.3.2
安装Alertmanager
# 搜索镜像
docker search alertmanager
# 拉取镜像
docker pull prom/alertmanager
# 也可以指定镜像版本,例如:docker pull prom/alertmanager:v0.25.0
注意:从小编安装的版本来看grafana已经内置了alertmanager,确保alertmanager集成进prometheus,还是需要安装alertmanager
用Docker Compose一键部署Prometheus全家桶
安装docker-compose组件
Docker Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。对于 Windows 用户,Docker Desktop已经内置了Docker Compose,因此不需要单独安装。
# Linux系统安装
#从github中拉取下载docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose
#设置文件具备执行权限
sudo chmod +x /usr/local/bin/docker-compose
#查看已安装的版本,如果能正常输出版本号说明安装compose完毕
docker-compose -v
# 主要docker compose命令
#启动一个compose
docker-compose up 或 docker compose up # 不同版本docker compose启动方式不太一样
#关闭一个compose
docker-compose down 或 docker compose down
Windows 用户安装Docker Desktop时已经安装了docker compose,不放心检查下是否安装docker compose
Docker compose安装Prometheus+Alertmanager+Grafana
主要文件及树形结构
docker-prometheus
├── alertmanager
│ ├── config
│ └── alertmanager.yml
│ ├── template
│ └── data
├── docker-compose.yaml
├── grafana
│ ├── config
│ └── grafana.ini
│ └── data
└── prometheus
├── config
└── prometheus.yml
├── rules
└── data
创建基本目录结构
#linux系统下
mkdir /data/docker-prometheus -p
mkdir /data/docker-prometheus/{grafana,prometheus,alertmanager} -p
cd /data/docker-prometheus/
# windows系统下直接在C盘或D盘下直接新建就行
# 按照上述文件结构图创建文件夹即可
创建prometheus配置文件
# 全局配置
global:
scrape_interval: 15s # 将抓取间隔设置为每15一次,根据情况调整。
evaluation_interval: 15 # 每15秒评估一次规则,根据情况调整。
# Alertmanager配置
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093'] # 或者- targets:127.0.0.1:9093
scheme: http
# 数据存储配置(保存90天)
storage:
tsdb:
retention: 90d
# 告警规则文件配置
rule_files:
- "/etc/prometheus/rules/*.yml" # 加载rules所有告警规则文件
# 抓取配置
scrape_configs:
# Prometheus自身监控,确保监控系统本身正常工作
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
scheme: http
# Alertmanager监控,alertmanager是Docker容器名,需要在同一Docker网络
- job_name: 'alertmanager'
static_configs:
- targets: ['alertmanager:9093']
scheme: http
# cAdvisor容器监控,Google开发的容器监控工具
# - job_name: 'cadvisor'
# static_configs:
# - targets: ['cadvisor:8080']
# labels:
# instance: 'Prometheus服务器'
# scheme: http
# Node Exporter 主机监控,监控Linux主机指标的工具
# - job_name: 'node-exporter'
# static_configs:
# - targets: ['node-exporter:9100']
# labels:
# instance: 'Prometheus服务器'
# scheme: http
# windows_exporter主机监控,如果是监控本地windows电脑需要此配置,需要安装windwos_exporter
- job_name: "windwos_exporter"
static_configs:
- targets: ["192.168.110.55:9182"]
scheme: http
创建Alertmanager配置文件
global:
resolve_timeout: 5m # 告警恢复判定超时时间
smtp_from: "xxx@qq.com" # 发件邮箱
smtp_smarthost: "smtp.qq.com:465" # SMTP服务器
smtp_auth_username: "xxx@qq.com" # 发件邮箱帐号
smtp_auth_password: "xxxx" # 邮箱密码/客户端授权码
smtp_require_tls: false # 是否启用TLS
# 引用外部模板文件
templates:
- "/etc/alertmanager/template/*.tmpl"
# 路由规则
route:
receiver: "webhook" # 默认接收器
group_by: ["alertname"] # 按告警名称+实例分组
group_wait: 1m # 等待时间,看是否有更多告警一起发送
group_interval: 2m # 同一分组内发送新告警的等待时间
repeat_interval: 5m # 重复发送告警的时间间隔
# 子路由
routes:
- match:
severity: "critical" # 告警级别
receiver: "webhook" # 子路由接收器
repeat_interval: 2h
receivers:
# 配置API告警接收器
- name: "webhook"
webhook_configs:
- url: "http://192.168.110.55:8081/alerts"
# 添加相应的认证信息(可选)
send_resolved: true
http_config:
tls_config:
insecure_skip_verify: true # 关键配置:跳过 HTTPS 证书验证
# 配置邮箱告警接收器
- name: "email"
email_configs:
- to: "xxx@qq.com" #可以多人
send_resolved: true # 告警恢复通知
html: '{{ template "email.html" . }}' # 只引用模板\
# 可选:添加纯文本备用(防止HTML渲染失败)
# text: '{{ template "email.txt" . }}'
# 抑制规则:当有严重告警时,抑制对应的警告级别告警
inhibit_rules:
- source_match: # 源告警(触发抑制的告警)
severity: 'critical'
alertname: 'ServerDown'
target_match: # 目标告警(被抑制的告警)
severity: 'warning'
equal: ['alertname', 'dev', 'instance'] # 需要匹配的标签
注意:引用告警模版时要挂载到/etc/alertmanager/template,否则不生效。或直接指定目录templates:- 'D:\template*.tmpl'
创建grafana配置文件
[server]
domain = localhost
root_url = %(protocol)s://%(domain)s:%(http_port)s/
[database]
type = sqlite3
path = /var/lib/grafana/grafana.db
[security]
admin_user = admin
admin_password = admin
secret_key = SW2YcwTIb9zpOOhoPsMm
[auth.anonymous]
enabled = false
[users]
allow_sign_up = false
auto_assign_org = true
auto_assign_org_role = Editor
创建docker-compose.yaml文件
version: "3.8"
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
hostname: grafana
labels:
- "cn=grafana"
- "sn=grafana"
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: admin
GF_USERS_ALLOW_SIGN_UP: false
GF_INSTALL_PLUGINS: ""
volumes:
- ./grafana/data:/var/lib/grafana
- ./grafana/config:/etc/grafana
ports:
- "3000:3000"
networks:
- monitoring-net
restart: unless-stopped
depends_on:
- prometheus
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--storage.path=/alertmanager"
volumes:
- ./alertmanager/config:/etc/alertmanager
- ./alertmanager/data:/alertmanager
- ./alertmanager/template:/etc/alertmanager/template
ports:
- "9093:9093"
user: "65534:65534"
networks:
- monitoring-net
restart: unless-stopped
depends_on:
- prometheus
prometheus:
image: prom/prometheus:latest
container_name: prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=7d'
- '--web.enable-lifecycle'
- '--web.enable-remote-write-receiver'
volumes:
- ./prometheus/config:/etc/prometheus
- ./prometheus/data:/prometheus
- ./prometheus/rules:/etc/prometheus/rules/
ports:
- "9090:9090"
networks:
- monitoring-net
restart: unless-stopped
networks:
monitoring-net:
driver: bridge
这段配置内容解释如下:
- Prometheus:用于收集监控数据(监听端口:9090)。
- Alertmanager:用于告警(监听端口:9093)。
- Grafana:用于展示图表和监控信息(监听端口:3000)
启动 Docker Compose
在 Docker Compose目录下,打开命令提示符(CMD)或 PowerShell ,运行以下命令启动 Docker Compose
docker compose up -d # 或者 docker-compose up -d
# docker compose版本不同启动方式有区别
# 通过以下命令查看正在运行的容器
docker ps
验证确认容器是否正常运行
在浏览器中分别访问:
- Prometheus:http://localhost:9090
- Grafana:http://localhost:3000
- Alertmanager:http://localhost:9093
Prometheus告警规则及设计规范
告警通过告警规则(Alerting Rules)和Alertmanager协同实现,告警规则(Alerting Rules)基于 PromQL 表达式定义的条件,当指标满足条件时触发告警。
告警规则核心组成
- 告警名称(alert):告警组内唯一标识,命名清晰、见名知义,避免模糊命名。
- 触发条件(expr):基于promql表达式用于判断指标是否正常,执行结果为true表示需要告警。
- 持续时间(for):持续满足条件的时间阈值,避免瞬时波动误报
- 标签(labels):附加标签,用于告警路由和分类
- 注释(annotations):告警详情模板,支持变量插值(如
{{ $labels.instance }})。
告警规则示例:
groups: # 规则组,可将同类规则归为一组,支持批量管理和执行
- name: test # 组的名字,在这个文件中必须要唯一
interval: 15s # 规则执行间隔,默认继承Prometheus全局抓取间隔,可单独配置
rules: # 具体告警规则列表
- alert: InstanceDown # 告警的名称,在组中需要唯一,需简洁明了,体现告警场景
expr: up == 0 # PromQL表达式, 执行结果为true: 表示需要告警 0:下线,1:在线,一般表示明确如mysql_up==0
for: 1m # 告警持续时间,即指标满足条件后(up==0)需持续多久才触发告警,避免瞬时波动误告警
labels: # 告警标签,用于Alertmanager分组、路由,可自定义
severity: critical # 定义标签,告警级别(常用:critical-紧急、warning-警告、info-信息)
annotations: # 告警注释,用于补充告警详情,展示在通知中
summary: "实例 {{ $labels.instance }} 下线了" # 告警摘要
description: "实例{{ $labels.instance }} 下线超过1分钟,当前值 {{$value}} 请立即检查处理!" # 告警详情,支持变量渲染
注意: 1、for 指定达到告警阈值之后,一致要持续多长时间,才发送告警数据。 2、labels中可以指定自定义的标签,如果定义的标签已经存在,则会被覆盖。可以使用模板。 3、annotations中的数据,可以使用模板,labels表示告警数据的标签,{ {labels表示告警数据的标签,{ {value}}表示时间序列的值。
告警数据的状态
inactive:表示没有达到告警的阈值,即expr表达式不成立。例如:在CPU使用率告警规则中,当CPU使用率低于设定的阈值(如 80%)时,对应的告警就处于inactive状态
pending:表示达到了告警的阈值,即expr表达式成立,告警先进入pending状态不会立即发送告警通知,但是未满足告警的持续时间,即for的值。
firing:已经达到阈值且满足了告警的持续时间,将告警信息发送到对应的告警接收端(如Alertmanager,然后由 Alertmanager进一步将告警信息发送到邮件、钉钉等工具)。经测试发现,如果同一个告警数据达到了Firing,那么不会再次产生一个告警数据,除非该告警解决了(设置保持触发)。
告警规则设计规范
告警规则设计原则
准确性:减少告警误报和漏报,提高告警的可信度。
层次性:严格按照告警严重性和优先级进行分层。
分组化:以功能或业务维度对告警进行分组管理。
易维护性:告警规则结构清晰、命名统一、标签规范等。
告警分组和分层设计
告警分组
根据监控指标和业务维度分为以下类别
业务维度:数据库告警(mysql、postgresql等)、中间件(redis、kafka、nginx等)、应用服务等。
功能维度:资源使用率(cpu、内存、磁盘等)、服务和组件运行状态等。
告警分层
一级告警(critical):严重影响业务的故障(服务宕机、关键资源耗尽),需立即通知并触告警处理。
二级告警(warning):潜在风险(性能临近瓶颈、非核心服务异常),需要关注采取预防措施。
三级告警(info):非紧急问题(低优先级的日志或配置异常),日常巡查中可处理。
告警命名、标签、注释规范
- 告警命名格式(alert):统一的命名规则可以提升规则的可读性和易维护性。
命名格式:Component_Metric_Condition 告警组件名称_监控指标 _描述 (遵循见名知义即可、尽量使用英文)
示例:
HighCpuUsage //cpu使用率过高
MysqlDown //mysql宕机
- 标签设计(Labels):用于分类和路由告警信息,是告警收敛和静默的重要依据。
必要标签:severity:告警级别(critical、warning、info)、service:关联服务名称、(可选标签:environment:运行环境(如 prod、dev、test)、team:处理告警的责任人(如 infra、app、db))
示例:
labels:
severity: critical
environment: prod
team: database
service: mysql
- 注释设计(Annotations):提供详细信息,帮助运维人员快速定位和解决问题。
必要注释:summary:告警的简要描述、description:告警详情包括上下文信息、runbook_url:指向处理步骤的文档或链接。
示例:
annotations:
summary: "实例 {{ $labels.instance }} 下线了"
description: "实例{{ $labels.instance }} 下线超过1分钟,当前值 {{$value}} 请立即检查处理!"
runbook_url: "xxxxx链接地址"
PromQL表达式
PromQL是 Prometheus 内置的数据查询语言,对事件序列数据的查询、聚合、逻辑运算等。实现对数据查询、可视化、告警处理。
PromQL数据类型
在Prometheus的表达式语言中,表达式或子表达式的计算结果可以为四种类型之一
- 瞬时/即时向量(Instant vector):一组时间序列,每个时间序列包含一个样本,都共享相同的时间戳。
- 瞬时向量选择器用来选择一组时序在某个采样点的采样值
示例:
表达式:node_cpu_seconds_total # 选择出所有属于该度量指标的时序的当前采样值
# 可以通过在后面添加用大括号包围起来的一组标签键值对来对时序进行过滤。
node_cpu_seconds_total{job="node-exporter", mode="idle"}
# 匹配标签值时可以是等于,也可以使用正则表达式
= : 选择与提供的字符串完全相同的标签。
!= : 选择与提供的字符串不相同的标签。
=~ : 选择正则表达式与提供的字符串(或子字符串)相匹配的标签。
!~ : 选择正则表达式与提供的字符串(或子字符串)不匹配的标签。
- 区间向量(Range vector):一组时间序列,其中包含每个时间序列随时间变化的一系列数据点。
- 区间向量选择器类似于瞬时向量选择器,不同的是它选择的是过去一段时间的采样值
示例:
表达式:node_cpu_seconds_total{mode="idle"}[5m] #在瞬时向量选择器后面添加包含在[]里的时长来得到区间向量选择器
node_cpu_seconds_total{mode="idle"}[5m] # 选出了所有度量指标为node_cpu_seconds_total{mode="idle"}的时序在过去5分钟的采样值
# 时长的单位可以以下几种:
s:秒、m:分钟、h:小时、d:天、w:周、y:年
- 简单向量/标量(Scalar vector):一个简单的数字浮点值。
- 字符串(String):文本字符串(支持单引号、双引号、反引号引用)。
PromQL 操作符
- 算术运算符:主要用于对查询结果进行计算
+:加、-:减、*:乘、/:除、%:取余、∧:幂运算
rate(http_requests_total[5m]) * 100 #将请求速率结果乘以 100。
- 比较运算符:用于对查询结果进行比较
==:等于、!=:不等于、>:大于、<:小于、>=:大于等于、<=:小于等于
up == 1 # 状态为1的实例(表示健康)
node_cpu_seconds_total{cpu="1",mode=~"i.*"} #CPU第一个核,idle、iowait、irq状态的使用时间
- 逻辑运算符:对不同的查询结果进行逻辑运算
and:交集、or:并集、unless:差集
up == 1 and http_requests_total > 100 # 返回所有健康且请求数大于100的实例。
- 聚合运算符:将多条时间序列合并为一条
sum:求和、avg:平均值、max/min:最大值/最小值、
count:计数、count_values:对value进行计数
topk(n, ...):前n条时序、bottomk(n, ...):后n条时序、
stddev:标准差、stdvar:标准方差
avg(irate(node_disk_io_time_seconds_total[1m])) # 取磁盘IO在过去1分钟的平均值
- 匹配运算符
by():以某一个标签进行计算,用于在聚合函数中指定如何分组数据
sum(node_cpu_seconds_total) by (cpu)
without():舍弃某个标签进行计算:用于在聚合函数中指定需要舍弃的标签,与by刚好相反
PromQL内置函数
- 时间序列计算函数
rate():计算时间序列在某段时间内容平均速率
irate():计算时间序列的瞬时速率
increase():计算某个区间内指标值增量
# 注意:rate与irate的区别
# 1、rate计算区间增长率,对短时间的突变不敏感
# 2、irate通过最后两个计算的增长率反应出的是瞬时增长率,对突变敏感
# 分析长期趋势或者在告警规则中,irate的这种灵敏度反而容易造成干扰。因此在长期趋势分析或者告警中更推荐使用rate函数
- 统计函数:
avg_over_time():计算时间区间内平均值
sum_over_time():计算时间区间内的总和
max_over_time():计算时间区间内的最大值
- 特殊函数:
abs():绝对值
absent():是否存在 # 当指标存在时返回空(无数据);当指标不存在时返回1
clamp_max():限制最大值
clamp_min():现在最小值
- 其他函数
ceil():向上取整
floor():向下取整
round():四舍五入
sort():正向排序(升序)
sort_desc():逆向排序(降序)
# 偏移数据
offset:查询指定时间之内的数据,允许向前或向后偏移数据时间点
示例:
rate(node_cpu_seconds_total{mode="idle"}[5m] offset 1h) #查询1h前数据
# 子查询
max_over_time( rate(http_requests_total[5m])[1h:] ) # 计算过去1小时内每5分钟速率的最大值
常用告警规则示例
# 服务器告警规则
# 服务是否可用 value : 0表示宕机 1 表示可用
expr: up == 0
# CPU使用率过高告警
expr: floor(100 - (irate(node_cpu_seconds_total{mode="idle"}[5m]) by (instance)* 100)) > 90
# CPU负载过高
expr: node_load1 > (0.9 * count by(instance) (node_cpu_seconds_total{mode="idle"}))
# 内存使用率过高
expr: floor(100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 80
# 磁盘使用率过高
expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint="/"} / node_filesystem_size_bytes{fstype=~"ext4|xfs",mountpoint="/"} *100) > 80
# 磁盘挂载 / 目录使用率
expr: floor(100 * ((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"})) > 90
# 磁盘挂载 /home 目录使用率
expr: floor(100 * ((node_filesystem_size_bytes{mountpoint="/home"} - node_filesystem_avail_bytes{mountpoint="/home"}) / node_filesystem_size_bytes{mountpoint="/home"})) > 90
# 磁盘挂载 /data 目录使用率
expr: floor(100 * ((node_filesystem_size_bytes{mountpoint="/data"} - node_filesystem_avail_bytes{mountpoint="/data"}) / node_filesystem_size_bytes{mountpoint="/data"})) > 90
# 磁盘IO使用率
expr: avg by(instance, job) (irate(node_disk_io_time_seconds_total[1m])) * 100 > 90
# 磁盘写速率
expr: sum by (instance) (rate(node_disk_written_bytes_total[2m])) / 1024 / 1024 > 50
expr: sum by (instance) (rate(node_disk_read_bytes_total[2m])) / 1024 / 1024 > 50
# 网络流出速率
expr: (irate(node_network_transmit_bytes_total{device!~"lo"}[1m]) / 1000) > ${value}
# 网络流入速率
(irate(node_network_receive_bytes{device!~"lo"}[1m]) / 1000) > ${value}
# mysql
# mysql服务宕机
expr: mysql_up == 0
# mysql QPS过高
expr: irate(mysql_global_status_questions[1m]) > 10000
# MySQL连接数使用率
expr: rate(mysql_global_status_threads_connected[1m] / mysql_global_variables_max_connections ) by (instance) *100 > 80
# MySQL线程使用率
expr: rate(mysql_global_status_threads_running[1m] / mysql_global_variables_max_connections ) by (instance) *100 > 80
# mysql慢查询
expr: rate(mysql_global_status_slow_queries[5m]) > 5
# MySQL预处理语句过去1分钟内最大使用率>80%
expr: max_over_time(mysql_global_status_prepared_stmt_count[1m]) / mysql_global_variables_max_prepared_stmt_count * 100 > 80
# mysql打开文件使用率>80%
expr: mysql_global_status_innodb_num_open_files / mysql_global_variables_open_files_limit * 100 > 80
# 监控应用相关
# 请求延迟高
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]) by (host, node, le)) > 1
# HTTP 5xx错误率过高
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
# 应用QPS 过高
expr: sum(rate(http_requests_total[1m])) > 2000
# JVM堆内存使用率监控
expr: sum by (instance)(jvm_memory_used_bytes{area="heap"}) / sum by (instance)(jvm_memory_max_bytes{area="heap"}) * 100 > 80
# JVM非堆内存使用率监控
expr: sum by (instance)(jvm_memory_used_bytes{area="nonheap"}) / sum by (instance)(jvm_memory_max_bytes{area="nonheap"}) * 100 > 80
# 服务存活状态异常
expr: probe_success == 0
告警规则设计最佳方式
告警阈值贴合业务:不同服务的资源阈值差异大(如CPU 使用率 80% 可能正常),需根据历史数据调整。
合理设置for时间:高频波动指标(如 CPU)设 3-5分钟,缓慢变化指标(如磁盘)设 10-15分钟,减少误报。
标签与级别清晰:用 severity 标签区分 critical(紧急)、warning(提醒)。
注释信息具体化:description需包含实例、当前值、阈值等关键信息,例如 “实例10.50.115.102的 CPU 使用率 85%(阈值 80%)”,可以加速故障定位。
告警规则配置及GUI页面查看规则
prometheus GUI页面Graph页面编写expr表达式查看,编写好expr表达式与告警规则进行组合,必须严格遵循yml格式。
注意:expr表达式要遵循promql语法及合理性。
规则目录配置及实现
参考docker-compose.yaml
注意:
1.rule_files配置路径/etc/prometheus/rules/路径,由宿主机(如/opt/prometheus/rules/)目录挂载映射而来
2.告警规则文件必须存放于宿主机对应规则目录
3.规则文件需严格遵循YAML语法规范,并确保PromQL表达式合理性,否则都会导致规则文件加载失败
4.路径配置方式,①推荐使用 - "/etc/prometheus/rules/*.yml",匹配容器内rules目录下所有.yml规则文件
②递归匹配子目录推荐使用 - "/etc/prometheus/rules/**/*.yml"
5.配置完成需要重启使其生效
http://localhost:9090/查看规则配置及规则文件,status->Configuration路径下看下rule_files配置路径
status->rules路径下查看规则文件,yml文件可配置多个告警,属于同组在一个rule显示
alerts路径下查看规则告警状态
注意:规则文件未生效,进入容器内用promtool校验规则文件是否存在格式问题
promtool check rules xxx.yml,rule_files路径是否配置正确。建议直接使用vscode编写好,yml文件格式化好,放到宿主机rules目录下
curl -X POST ``http://IP:9090/-/reload热加载配置规则使其生效。
Grafana内置Alertmanager实现邮箱/钉钉告警通知
以Grafana告警内置 Alertmanager为例,Grafana支持添加新的Alertmanager,也可以部署Alertmanager自定义告警。
邮箱告警推送通知配置
需要在grafana.ini文件配置邮箱,然后重启grafana,不配置邮箱告警推送通知失败。
[smtp]
# 开启邮箱
enabled = true //默认是false,启用SMTP功能(必须设为true)
host = smtp.qq.com:465 //示例:QQ邮箱的SMTP地址+端口
user = xxxxxxx@qq.com //你的登录邮箱的账号
password = xxxxx //你的SMTP授权授权码
from_address = 测试<xxxxx@qq.com> //邮件发送者(显示在收件箱的「发件人」,格式:名称 <邮箱>)
from_name = 测试Grafana监控 //发件人名称,自定义
ssl = true //加密方式(推荐ssl,对应465端口;或tls对应587端口)
// 可选配置,一般不生效需要添加skip_verify,timeout
skip_verify = true //避免证书问题,跳过SSL证书验证
timeout = 30s //延长超时时间(解决网络慢的问题)
注意:QQ邮箱示例:需要开启邮箱
在
Addresses中就填写需要通知的邮箱地址,多个邮箱地址之间用";" 或者"\n" 或者","分隔
**注意:**没有配置[smtp]邮箱,测试通知失败如图:
钉钉机器人告警推送通知配置
创建一个钉钉/企业微信群-->添加机器人-->添加机器人后,有一个webhook地址
自己定义关键字:根据关键词用于触发消息通知,否则不生效
加签:生产环境推荐,https://oapi.dingtalk.com/robot/send?access_token=XXXXXX×tamp=XXX&sign=XXX
IP地址段:公网IP地址(非局域网地址),否则不在白名单内失败
选择
DingDing也可以选择webhook,如果选择DingDing,message type可根据需要自行选择。若是选择webhook模式,url连接一样的方法来自钉钉群机器人,然后下方有个message要配置,否则消息不是推送到钉钉群,这个message信息内容根据你的需求自行设定
钉钉群测试报警信息如下:
Grafana内置Alertmanager告警配置
新增告警配置(Alert rules)
首先,在报警模块中找到Alerting/Alert rules模块,创建一个新的警报规则。
- Enter alert rule name:首先,给你的报警取个名字
- Define query and alert condition:是报警规则的主体,选择数据源后自定义报警规则,也是报警判断依据。
- 开启
高级选项、Builder、code根据自己需要来设置,code可以直接写PromQL表达式比较方便 - 添加查询支持添加多个告警规则
- 开启
3. Add folder and labels:添加文件夹和标签
- 同一个项目的报警规则可以放在一个文件夹中。
- 标签方便后续搜索查询,标签可添加也可不添加,可根据自己需求添加。
- 文件夹名称要见名知义,方便定位失败,添加的文件夹及告警规则在仪表盘显示
- Set evaluation behavior:
- 评估组或间隔:设置报警的频率和报警的时机。
- Pending period(待处理时段):触发告警前,阈值条件必须持续满足的时间段。如果选择 “None”,则一旦满足条件就会立即触发告警。
- keep firing for(持续触发时间):在阈值条件不再被触发后,告警仍然保持“触发(firing)”状态的时间。如果选择 “None”,则一旦条件恢复正常,告警会立即恢复为正常状态。
- Configure notifications:配置通知中就是报警时需要通知的地方,也是刚刚创建的联络点(邮箱或钉钉)。
- 配置通知消息(选填):摘要中填写简要总结发生了什么以及原因。描述说明此警报规则的功能。
联络点(Contact points)
Contact Points(联络点):可以配置邮箱、钉钉等告警通知方式,详见:邮箱、钉钉机器人告警推送通知配置。
通知策略(Notification policies)
通知策略:确定警报如何路由到联络点,通过新增子策略,可自定义设置策略类型。
标签中写符合你要求的内容,联络点选择你刚刚设置的,当需要报警时,满足这个标签的,这个根据自己的需要写。此时报警系统已经建立,当出现异常的时候,就会有消息通知到
静默(Silences)
配置静默,用于停止接收来自特定警报规则的通知,可以停止来自一个或多个警报规则的通知
告警通知(Active notifications)
用于展示告警通知,以分组形式展示
Alertmanger配置外部API和邮箱发送告警
邮箱配置
alertmanger.yml配置详见Alertmanager配置文件
注意:挂载到/etc/alertmanager/template,否则不生效。或者直接指定目录templates:- 'xxxxx/*.tmpl'
自定义邮件通知告警模版
{{ define "email.html" }} <!-- 这里的名称必须和配置中引用的完全一致 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>监控告警通知</title>
</head>
<body>
{{ if .Alerts.Firing }}
<h3>🚨 新告警触发</h3>
{{ else if .Alerts.Resolved }}
<h3>✅ 告警已恢复</h3>
{{ end }}
<div style="border:1px solid #eee; padding:10px; margin:10px 0;">
{{ range $alert := .Alerts }}
<p><strong>告警状态:</strong>{{ $alert.Status }}</p>
<p><strong>告警级别:</strong>{{ index $alert.Labels "severity" }}</p>
<p><strong>告警类型:</strong>{{ index $alert.Labels "alertname" }}</p>
<p><strong>告警主机:</strong>{{ index $alert.Labels "instance"}}</p>
<p><strong>告警详情:</strong>{{ index $alert.Annotations "description" }}</p>
<p><strong>告警时间:</strong>{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}</p>
<hr>
{{ end }}
</div>
</body>
</html>
{{ end }}
注意:告警模版要符合要求,否则收到告警邮件无告警内容
如:no such template email.html 或template: email.tmpl:17: function default not defined"
<p><strong>告警级别:</strong>{{ index $alert.Labels "severity" | default "未知" }}</p>
解决方式:
<!-- 使用if判断处理可能为空的字段 -->
<p><strong>级别:</strong>
{{ if .Labels.severity }}{{ .Labels.severity }}{{ else }}未指定{{ end }}
</p>
自定义告警邮件模版示例:
外发API方式(webhook)告警配置
Alertmanager使用webhook方式告警
alertmanger.yml配置详见Alertmanager配置文件
使用webhook方式,alertmanager会给配置的webhook地址发送一个http类型的post请求,参数为json字符串(字符串类型),如下:
{
"receiver": "测试",
"status": "resolved",
"alerts": [
{
"status": "resolved",
"labels": {
"alertname": "测试",
"grafana_folder": "测试",
"instance": "192.168.110.248:9182",
"job": "windows_export"
},
"annotations": {
"grafana_state_reason": "RuleDeleted"
},
"startsAt": "2026-03-09T06:42:50Z",
"endsAt": "2026-03-09T07:03:50.014865164Z",
"generatorURL": "http://localhost:3000/alerting/grafana/affgziuxbcnb4b/view?orgId=1",
"fingerprint": "f7a8096601312c82",
"silenceURL": "http://localhost:3000/alerting/silence/new?alertmanager=grafana&matcher=__alert_rule_uid__%3Daffgziuxbcnb4b&matcher=instance%192.168.110.55%3A9182&matcher=job%3Dwindows_export&orgId=1",
"dashboardURL": "",
"panelURL": "",
"values": null,
"valueString": "[ var='A' labels={__name__=up, instance=192.168.110.55:9182, job=windows_export} value=0 ], [ var='C' labels={__name__=up, instance=192.168.110.55:9182, job=windows_export} value=1 ]",
"orgId": 1
}
],
"groupLabels": {
"alertname": "测试",
"grafana_folder": "测试"
},
"commonLabels": {
"alertname": "测试",
"grafana_folder": "测试",
"instance": "192.168.110.55:9182",
"job": "windows_export"
},
"commonAnnotations": {
"grafana_state_reason": "RuleDeleted"
},
"externalURL": "http://localhost:3000/",
"version": "1",
"groupKey": "{}/{__grafana_autogenerated__=\"true\"}/{__grafana_receiver__=\"测试\"}:{alertname=\"测试\", grafana_folder=\"测试\"}",
"truncatedAlerts": 0,
"orgId": 1,
"title": "[RESOLVED] 测试 测试 (192.168.110.55:9182 windows_export)",
"state": "ok",
"message": "**Resolved**\n\nValue: [no value]\nLabels:\n - alertname = 测试\n - grafana_folder = 测试\n - instance = 192.168.110.248:9182\n - job = windows_export\nAnnotations:\n - grafana_state_reason = RuleDeleted\nSource: http://localhost:3000/alerting/grafana/affgziuxbcnb4b/view?orgId=1\nSilence: http://localhost:3000/alerting/silence/new?alertmanager=grafana&matcher=__alert_rule_uid__%3Daffgziuxbcnb4b&matcher=instance%3D192.168.110.248%3A9182&matcher=job%3Dwindows_export&orgId=1\n"
}
搭建个http的请求处理器来处理报警通知,如下:
package com.dbapp.demo.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Controller
@RequestMapping("/")
public class AlertController {
@PostMapping(value = "/alerts")
public String pstn(@RequestBody String json) {
log.debug("alert notify params: {}", json);
Map<String, Object> result = new HashMap<>();
result.put("msg", "报警失败");
result.put("code", 0);
if(StringUtils.isBlank(json)){
return JSON.toJSONString(result);
}
JSONObject jo = JSON.parseObject(json);
JSONObject commonAnnotations = jo.getJSONObject("commonAnnotations");
String status = jo.getString("status");
if (commonAnnotations == null) {
return JSON.toJSONString(result);
}
String subject = commonAnnotations.getString("summary");
String content = commonAnnotations.getString("description");
List<String> emailusers = new ArrayList<>();
emailusers.add("xxx@aliyun.com");
return JSON.toJSONString(result);
}
}
Alertmanager配置功能很强大,完全能够按照自己的目标定义灵活的通知和报警方式,尤其是对webhook的支持,简直不能更灵活了。Alertmanager还支持定义template来更清晰的彰显要通知的内容。
好了,文章到这里结束了,快去试试吧~~