1. 从零搭建监控告警体系:为什么选 Prometheus 加 Grafana 这套组合
监控这件事,很多团队都是等到线上出了故障才开始重视。我见过太多这样的情况:服务挂了半小时,运维还在翻日志,业务方电话已经打爆了。等到事后复盘,大家一致认为"得搞个监控",然后就开始选型。市面上的方案不少,商业的、开源的、自建的都有,但如果你问我中小团队最稳妥的起点是什么,我会毫不犹豫地说:Prometheus 加 Grafana。
这套组合的核心逻辑其实很朴素。Prometheus 负责采集和存储指标数据,它采用拉取模式,每隔固定间隔去目标端点抓取数据,数据以时间序列的形式存在本地。Grafana 则负责把这些数据可视化出来,做成仪表盘,让你一眼就能看出系统当前的健康状况。两者之间的衔接非常自然,Grafana 原生支持 Prometheus 作为数据源,配置几行就能跑通。
但光有监控还不够,真正让监控产生价值的是告警。你不可能二十四小时盯着屏幕看曲线,所以需要一套机制在指标异常时主动通知你。Prometheus 自带的 Alertmanager 就是干这个的,它支持多种通知渠道,邮件是最基础的,PagerDuty 则是更专业的告警管理平台,适合需要值班轮换和告警升级的团队。
这篇文章面向的是有一定 Linux 基础的运维或后端开发人员,我会把安装部署、数据备份、邮件告警配置、PagerDuty 告警接入这几个环节完整走一遍。每个步骤我都会解释为什么这么做,以及我在实际操作中踩过哪些坑。你跟着走一遍,基本就能搭出一套可用的监控告警体系。
注意:本文涉及的所有配置均基于常见实践总结,具体参数需根据你的实际环境调整。生产环境部署前建议先在测试环境验证。
2. 安装部署:Prometheus 与 Grafana 的落地细节
2.1 安装方式的选择:包管理还是二进制
安装 Prometheus 和 Grafana 有好几种方式:用系统包管理器、用 Docker 容器、直接下载二进制文件。这几种方式各有适用场景,我分别说一下我的经验。
用包管理器安装最省事,比如在基于 Debian 的系统上apt install prometheus就能搞定。但问题在于,仓库里的版本往往比较旧,而且配置文件路径、服务管理方式都跟官方文档有差异,出了问题不好排查。Docker 方式适合已经容器化的环境,部署快、隔离好,但数据持久化和网络配置需要额外注意。二进制方式最灵活,版本可控,配置文件路径清晰,适合需要精细控制的生产环境。
我个人的建议是:如果你是第一次搭建,想快速看到效果,可以用 Docker 跑一遍熟悉流程;如果是正式的生产环境,用二进制方式部署,配合 systemd 管理服务,这样后续升级和维护都更可控。
2.2 Prometheus 二进制的部署步骤
先从官方下载页面获取对应架构的压缩包。假设我们部署在/opt/prometheus目录下,操作流程如下:
# 创建专用用户,避免以 root 运行 useradd --no-create-home --shell /bin/false prometheus # 创建目录结构 mkdir -p /opt/prometheus mkdir -p /var/lib/prometheus mkdir -p /etc/prometheus # 下载并解压(版本号根据实际情况替换) cd /tmp wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz tar xvf prometheus-2.45.0.linux-amd64.tar.gz cd prometheus-2.45.0.linux-amd64 # 复制二进制文件和配置 cp prometheus promtool /opt/prometheus/ cp -r consoles console_libraries /opt/prometheus/ cp prometheus.yml /etc/prometheus/ # 设置权限 chown -R prometheus:prometheus /opt/prometheus chown -R prometheus:prometheus /var/lib/prometheus chown -R prometheus:prometheus /etc/prometheus这里有几个细节值得展开说。第一,创建专用用户是安全基线,Prometheus 不需要 root 权限就能运行,用 root 跑反而增加风险。第二,/var/lib/prometheus是数据存储目录,这个目录会随着时间增长,需要提前规划磁盘空间。第三,promtool这个工具很多人忽略,但它非常有用,可以用来检查配置文件语法、验证告警规则,后面我会详细讲。
接下来配置 systemd 服务文件/etc/systemd/system/prometheus.service:
[Unit] Description=Prometheus Wants=network-online.target After=network-online.target [Service] User=prometheus Group=prometheus Type=simple ExecStart=/opt/prometheus/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus/ \ --storage.tsdb.retention.time=30d \ --web.listen-address=0.0.0.0:9090 \ --web.enable-lifecycle [Install] WantedBy=multi-user.target--storage.tsdb.retention.time=30d这个参数控制数据保留时长,默认是 15 天。设成 30 天意味着磁盘占用会翻倍,你需要根据数据量和磁盘容量来权衡。--web.enable-lifecycle开启后,可以通过 HTTP 接口热加载配置,改完配置文件不用重启服务,这个在调试告警规则时特别方便。
2.3 Grafana 的安装与初始配置
Grafana 的安装相对简单,官方提供了各系统的安装包。以二进制方式为例:
# 下载并解压 cd /tmp wget https://dl.grafana.com/oss/release/grafana-10.0.0.linux-amd64.tar.gz tar xvf grafana-10.0.0.linux-amd64.tar.gz mv grafana-10.0.0 /opt/grafana # 创建数据目录 mkdir -p /var/lib/grafana chown -R grafana:grafana /var/lib/grafanaGrafana 的配置文件在conf/defaults.ini,但我不建议直接改这个文件,而是创建conf/custom.ini来覆盖默认配置。这样升级时不会丢失你的自定义设置。关键配置项包括:
[server] http_port = 3000 domain = your-domain.com root_url = https://your-domain.com/grafana/ [database] type = sqlite3 path = /var/lib/grafana/grafana.db [security] admin_user = admin admin_password = your-strong-passwordroot_url这个配置在反向代理场景下特别重要。如果你用 Nginx 做代理,路径不是根路径,必须正确设置root_url,否则 Grafana 的静态资源加载会出问题,页面显示异常。
2.4 验证安装与首次登录
Prometheus 启动后,访问http://your-server:9090应该能看到自带的 Web UI。在 "Status" 菜单下的 "Targets" 页面,可以看到 Prometheus 自身作为监控目标的状态。如果显示 "UP",说明采集正常。
Grafana 启动后访问http://your-server:3000,用配置的管理员账号登录。首次登录后第一件事是添加数据源:Configuration -> Data Sources -> Add data source -> Prometheus,填入 Prometheus 的地址,保存后测试连接。如果提示成功,说明两者已经打通。
提示:Grafana 默认的 SQLite 数据库适合小规模使用,如果团队人数多、仪表盘复杂,建议换成 MySQL 或 PostgreSQL,性能和并发能力会好很多。
3. 数据备份:别等丢了数据才后悔
3.1 Prometheus 数据备份的特殊性
Prometheus 的数据存储用的是自己实现的 TSDB(时间序列数据库),数据文件在--storage.tsdb.path指定的目录下。很多人以为直接cp -r复制目录就行,但这样做有风险:Prometheus 运行时会持有文件句柄,直接复制可能得到不一致的快照。
正确的做法是用 Prometheus 提供的管理 API 来创建快照。前提是启动时加了--web.enable-admin-api参数。创建快照的命令:
curl -X POST http://localhost:9090/api/v1/admin/tsdb/snapshot执行成功后会返回快照的路径,类似{"name":"20240101T120000Z-abc123"}。快照数据存放在--storage.tsdb.path下的snapshots目录里。你可以把这个快照目录打包备份到远程存储。
这个机制的好处是:快照创建时 Prometheus 会确保数据一致性,不会出现半个写入的数据块。而且快照是只读的,备份过程中不影响正常采集。
3.2 备份策略的制定
备份策略要考虑两个维度:备份频率和保留周期。Prometheus 的数据是时间序列,越近的数据价值越高。我的建议是:
| 备份类型 | 频率 | 保留周期 | 存储位置 |
|---|---|---|---|
| 全量快照 | 每天一次 | 7天 | 本地加远程对象存储 |
| 增量配置备份 | 每次变更 | 永久 | 版本控制系统 |
| Grafana 数据库 | 每天一次 | 30天 | 远程对象存储 |
配置文件(prometheus.yml、告警规则文件、Grafana 的仪表盘 JSON)建议纳入版本控制,每次变更都提交。这样即使服务器完全损坏,也能快速重建。
3.3 Grafana 仪表盘的导出与导入
Grafana 的仪表盘是监控体系的核心资产,丢了就得重新做。导出方式有两种:通过 UI 导出 JSON,或者直接备份数据库。
通过 UI 导出适合单个仪表盘:打开仪表盘,点击右上角分享图标,选择 "Export",可以导出为 JSON 文件。这个 JSON 可以导入到任何 Grafana 实例。
批量备份建议直接备份数据库文件。如果用的是 SQLite,停掉 Grafana 服务后复制grafana.db即可。如果用的是 MySQL 或 PostgreSQL,用对应的数据库备份工具。注意 Grafana 的数据库里还存了用户、组织、数据源配置等信息,整体备份最省心。
3.4 恢复演练:备份不验证等于没备份
我见过太多团队备份做了,但从来没验证过恢复流程,真出事的时候发现备份文件损坏或者恢复步骤不对。建议每季度做一次恢复演练:在一台测试机上,用备份数据完整恢复一套环境,确认数据完整、仪表盘正常、告警规则生效。
Prometheus 的恢复很简单:停掉服务,把快照目录里的数据复制到--storage.tsdb.path下,启动服务即可。Grafana 的恢复就是替换数据库文件。但要注意版本兼容性,跨大版本恢复可能有问题,所以备份时要记录版本号。
4. 邮件告警:从规则定义到通知送达
4.1 Alertmanager 的部署与基础配置
Prometheus 本身只负责产生告警,实际的通知发送由 Alertmanager 完成。所以你需要额外部署一个 Alertmanager 实例。下载解压后,配置文件alertmanager.yml是核心。
一个基础的邮件告警配置长这样:
global: smtp_smarthost: 'smtp.example.com:587' smtp_from: 'alertmanager@example.com' smtp_auth_username: 'alertmanager@example.com' smtp_auth_password: 'your-password' smtp_require_tls: true route: group_by: ['alertname', 'instance'] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: 'email-notifications' receivers: - name: 'email-notifications' email_configs: - to: 'ops-team@example.com' send_resolved: true这里几个参数需要重点理解。group_wait是首次告警的等待时间,设成 30 秒意味着收到告警后等 30 秒再发,这样同一组内的多条告警可以合并成一封邮件。group_interval是同一组告警再次发送的间隔。repeat_interval是告警持续未恢复时重复通知的间隔,设成 4 小时是为了避免邮件轰炸。send_resolved: true表示告警恢复时也发一封邮件,这个很有用,能让你知道问题已经解决了。
4.2 告警规则的编写要点
告警规则文件在 Prometheus 配置里通过rule_files引入。一条典型的告警规则:
groups: - name: instance-health rules: - alert: InstanceDown expr: up == 0 for: 2m labels: severity: critical annotations: summary: "实例 {{ $labels.instance }} 已下线" description: "{{ $labels.instance }} 已经超过 2 分钟无法访问。"expr是 PromQL 表达式,up == 0表示目标不可达。for: 2m表示持续 2 分钟才触发告警,这个参数非常重要,能过滤掉网络抖动导致的误报。labels里的severity用于告警分级,后面在 Alertmanager 的路由里可以根据这个标签走不同的通知渠道。
写告警规则有几个经验:第一,for的值不要设太小,否则误报多;第二,annotations里的描述要包含足够的信息,最好带上实例名、当前值等,方便排查;第三,告警规则要定期 review,业务变化后旧的规则可能不再适用。
4.3 邮件告警的常见坑
邮件告警看起来简单,但实际操作中坑不少。我列几个最常见的:
第一个坑是 SMTP 认证失败。很多邮件服务商要求用授权码而不是登录密码,而且发件人地址必须和认证用户名一致。如果配置了smtp_from但和smtp_auth_username不同,有些服务商会拒绝发送。
第二个坑是 TLS 配置。smtp_require_tls: true在大多数情况下是对的,但如果你的 SMTP 服务器用的是自签名证书,会报证书验证失败。这时候需要额外配置smtp_tls_config来跳过验证,但生产环境不建议这么做,应该把 CA 证书加到信任链里。
第三个坑是邮件被当成垃圾邮件。告警邮件通常格式固定、发送频繁,容易被邮件网关拦截。解决办法是配置 SPF 和 DKIM 记录,或者用专业的邮件发送服务。
第四个坑是告警风暴。如果一个大范围故障导致几百个实例同时下线,邮件会瞬间塞满邮箱。这时候group_by和group_wait就派上用场了,合理配置能把几百封邮件合并成几封。
4.4 用 promtool 验证配置
改完告警规则后,别急着重启 Prometheus,先用 promtool 检查语法:
/opt/prometheus/promtool check rules /etc/prometheus/rules/*.yml这个命令会解析规则文件,报告语法错误和逻辑问题。我养成的习惯是每次改完规则都跑一遍,能避免很多低级错误。Prometheus 启动时也会检查,但启动失败会影响监控,不如提前验证。
5. PagerDuty 告警接入:让告警找到对的人
5.1 PagerDuty 解决了什么问题
邮件告警有个根本缺陷:它假设有人一直在看邮箱。但现实中,凌晨三点的告警邮件很可能第二天早上才被看到。PagerDuty 这类告警管理平台解决的就是"告警送达和响应"的问题。它支持电话、短信、推送等多种通知方式,还能配置值班表、告警升级策略,确保告警在指定时间内被正确的人响应。
接入 PagerDuty 的流程分两步:在 PagerDuty 侧创建服务并获取集成密钥,在 Alertmanager 侧配置对应的 receiver。
5.2 在 PagerDuty 侧创建服务
登录 PagerDuty 后,进入 Services 页面,创建一个新服务。在集成类型里选择 "Prometheus",系统会生成一个 Integration Key。这个 Key 是 Alertmanager 和 PagerDuty 之间的凭证,需要妥善保管。
创建服务时还要配置 Escalation Policy,也就是告警升级策略。比如:先通知值班工程师,15 分钟未响应则通知备份工程师,30 分钟未响应则通知团队负责人。这个策略根据团队规模来定,小团队可能只需要一级。
5.3 Alertmanager 侧的 PagerDuty 配置
在alertmanager.yml里添加 PagerDuty receiver:
receivers: - name: 'pagerduty-critical' pagerduty_configs: - service_key: 'your-pagerduty-integration-key' severity: 'critical' description: '{{ .CommonAnnotations.summary }}' details: instance: '{{ .CommonLabels.instance }}' description: '{{ .CommonAnnotations.description }}'然后在 route 里根据 severity 标签路由:
route: group_by: ['alertname'] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: 'email-notifications' routes: - match: severity: critical receiver: 'pagerduty-critical' continue: true - match: severity: warning receiver: 'email-notifications'continue: true这个配置值得说一下。默认情况下,告警匹配到第一个子路由后就停止继续匹配。加上continue: true后,告警会继续匹配后续路由。这样 critical 级别的告警既走 PagerDuty 也走邮件,双重保障。
5.4 告警分级与路由策略的设计
告警分级是整套体系里最需要动脑筋的部分。分得太粗,重要告警被淹没;分得太细,维护成本高。我的经验是按影响面来分:
| 级别 | 判定标准 | 通知方式 | 响应要求 |
|---|---|---|---|
| critical | 核心服务不可用,影响用户 | PagerDuty 加邮件 | 15分钟内响应 |
| warning | 指标异常但服务可用 | 邮件 | 当天处理 |
| info | 需要关注但不紧急 | 邮件或仪表盘 | 按计划处理 |
这个分级要跟团队达成共识,写进值班手册。否则每个人对"严重"的理解不一样,告警就失去了意义。
5.5 测试告警链路是否通畅
配置完成后,一定要测试整条链路。Alertmanager 提供了一个测试接口,可以手动发送一个告警:
curl -H "Content-Type: application/json" -d '[{ "labels": { "alertname": "TestAlert", "severity": "critical", "instance": "test-instance" }, "annotations": { "summary": "这是一条测试告警", "description": "用于验证告警链路是否正常" } }]' http://localhost:9093/api/v1/alerts发送后观察 PagerDuty 是否收到告警、是否按预期触发通知。如果没收到,检查 Alertmanager 日志,通常能看到具体的错误信息。常见问题包括 service_key 错误、网络不通、PagerDuty 侧的服务配置有误等。
注意:测试告警会真实触发通知,建议在团队知晓的情况下进行,避免半夜把值班同事吵醒。
6. 运维实践中的经验与避坑
6.1 监控体系自身的监控
这是个容易被忽略的点:你用来监控别人的系统,自己也需要被监控。Prometheus 如果挂了,所有告警都失效,但你可能浑然不知。所以需要一套"监控的监控"机制。
最简单的做法是用一个外部的健康检查服务,定期访问 Prometheus 和 Alertmanager 的健康端点。Prometheus 的健康端点是/-/healthy,Alertmanager 是/-/healthy。如果连续几次检查失败,就通过独立的渠道(比如另一个告警系统或直接发短信)通知。
另一个做法是部署两个 Prometheus 实例,互相监控对方。这样任何一个挂了,另一个都能发现。但要注意避免"脑裂"问题,两个实例的告警规则要协调好。
6.2 磁盘空间的管理
Prometheus 的数据增长速度和监控目标数量、采集频率、指标基数直接相关。一个中等规模的集群,每天可能产生几个 GB 的数据。如果磁盘满了,Prometheus 会停止写入,监控就断了。
管理磁盘空间的几个手段:第一,合理设置retention.time,不需要保留太久的数据;第二,控制指标基数,避免采集高基数标签(比如把用户 ID 作为标签);第三,定期清理不再监控的目标,减少无效数据。
可以用这个查询看看哪些指标的基数最高:
topk(10, count by (__name__)({__name__=~".+"}))如果发现某个指标的序列数异常高,就要检查它的标签设计是否合理。
6.3 告警规则的持续优化
告警规则不是写完就一劳永逸的。业务在变,告警规则也要跟着调整。我建议每个月花半小时 review 一下告警记录:哪些告警频繁触发但都是误报?哪些告警触发了但没人处理?哪些故障没有被告警覆盖?
误报多的规则要调整阈值或增加for时间。没人处理的告警要么是分级不对,要么是通知渠道不对。没被覆盖的故障要补充新规则。这个过程持续做,告警体系才会越来越精准。
6.4 版本升级的注意事项
Prometheus 和 Grafana 都在活跃迭代,定期升级能获得新功能和安全修复。但升级有风险,尤其是跨大版本。升级前要做的准备:备份数据、查看官方的 breaking changes 文档、在测试环境验证。
Prometheus 的升级相对平滑,大部分配置向后兼容。Grafana 的升级要注意插件兼容性,有些老插件在新版本上可能不工作。升级后要检查仪表盘是否正常显示、告警是否正常触发。
6.5 团队协作与文档化
监控体系是团队资产,不是个人玩具。配置变更要有记录,告警处理要有流程,新成员要能快速上手。我建议维护一份运维手册,内容包括:架构说明、部署步骤、常见问题处理、告警分级标准、值班流程。
文档不用写得多漂亮,关键是准确、及时更新。每次处理完一个故障,把排查过程和解决方法补充进去,日积月累就是一笔宝贵的财富。
这套 Prometheus 加 Grafana 的监控告警体系,我从最初的单机部署到现在管理几十个监控目标,中间踩过的坑不计其数。最大的体会是:工具本身不难,难的是持续运营。安装配置可能一两天就搞定了,但让告警真正有用、让团队真正依赖这套系统,需要几个月甚至更长时间的打磨。希望这篇文章能帮你少走一些弯路,把精力花在更有价值的事情上。