
1. 项目概述从零搭建一个可靠的监控告警系统最近在梳理手头的几个线上服务发现告警这块一直是个心病。之前用的脚本监控告警要么石沉大海要么半夜狂轰滥炸搞得人神经衰弱。痛定思痛决定把监控体系彻底升级用上业界标准的 Prometheus Alertmanager 组合拳核心目标就一个让该响的告警及时、清晰、准确地送到我眼前最好是直接进邮箱。这个项目就是在 CentOS 7 环境下完整部署一套 Prometheus 监控系统并配置其告警组件 Alertmanager实现将监控触发的告警通过邮件发送出来。听起来好像就是几个组件的安装和配置但真做起来从系统兼容性、组件间通信、配置语法到邮件服务的坑一个都少不了。我折腾了两天把关键步骤和踩过的坑都记下来了如果你也在为 CentOS 7 上的监控告警发愁这篇记录应该能帮你省下不少时间。2. 核心组件选型与架构设计思路2.1 为什么是 Prometheus Alertmanager在开源监控领域可选的方案不少比如 Zabbix、Nagios它们功能强大但相对重量级。我选择 Prometheus首要原因是它的设计哲学和我的场景高度匹配多维数据模型和灵活的查询语言PromQL。简单说它不把监控对象简单地看成一台主机或一个服务而是通过“指标名称”和一组“键值对标签”来唯一标识一个时间序列。比如同样是http_requests_total这个指标我可以给它打上methodPOST、endpoint/api/v1/users、instance192.168.1.10:9100等标签。这样当我想看所有 POST 请求的速率或者特定端点的错误率时用 PromQL 可以非常直观地聚合和计算告警规则也能写得非常精细。Alertmanager 则是专门处理告警的组件。Prometheus Server 只负责“产生”告警根据规则判断是否触发而告警的去重、分组、静默、路由以及通过不同渠道如邮件、钉钉、企业微信发送这些“后勤”工作都交给 Alertmanager。这种职责分离的设计很清晰也便于扩展。比如未来要加一个钉钉机器人告警只需要在 Alertmanager 配置里加一个 receiver完全不用动 Prometheus Server。2.2 整体数据流与组件职责在动手之前脑子里得先有张图知道数据是怎么跑的数据采集各种Exporter如 node_exporter 监控主机mysqld_exporter 监控 MySQL运行在被监控目标上暴露 HTTP 接口提供指标数据。数据抓取与存储Prometheus Server定期如每15秒去拉取Scrape这些 Exporter 的指标存入其内置的时序数据库中。告警规则评估Prometheus Server根据配置文件prometheus.yml中定义的rule_files周期性地评估告警规则。一旦规则条件满足如“5分钟内平均CPU使用率 80%”就会产生一个告警Alert并将其状态设置为PENDING。在持续满足条件一个周期后状态变为FIRING。告警推送状态为FIRING的告警会被 Prometheus Server 推送给配置好的Alertmanager集群通常是高可用部署。告警处理与发送Alertmanager接收到告警后会进行一系列处理比如将同一时间段、同一集群、同一类型的告警合并成一条通知分组抑制重复的告警去重然后根据配置的路由规则决定将这条通知发送给哪个“接收者”Receiver。我们的目标“邮件发送”就是在这里配置一个邮件类型的 Receiver。搞清楚这个流程后面配置的时候就知道每个文件、每个参数是在哪个环节起作用出了问题也知道该查哪一段日志。3. 系统环境准备与核心组件部署3.1 CentOS 7 基础环境调优虽然 CentOS 7 已经比较成熟但为了监控系统稳定运行有几项基础检查和建议配置需要做。首先确认系统版本cat /etc/redhat-release。我用的是一台干净的 CentOS 7.9 最小化安装系统。防火墙与 SELinux这是第一道坎。为了方便实验和初期部署我选择临时关闭防火墙并设置 SELinux 为宽容模式。生产环境请务必根据安全规范配置精细的防火墙规则。# 停止并禁用firewalld systemctl stop firewalld systemctl disable firewalld # 临时关闭SELinux重启后失效 setenforce 0 # 永久关闭编辑 /etc/selinux/config将 SELINUXenforcing 改为 SELINUXdisabled需重启注意生产环境不建议直接关闭 SELinux而是应为其配置正确的策略。例如为 Prometheus 等进程的二进制文件和数据目录设置合适的文件上下文标签。时间同步监控和告警严重依赖准确的时间戳。务必确保所有被监控节点以及 Prometheus 服务器时间同步。使用 NTP 或 Chronyyum install -y chrony systemctl start chronyd systemctl enable chronyd chronyc sources -v # 查看同步状态资源限制Prometheus 吃内存尤其是存储的数据量大了以后。编辑/etc/security/limits.conf为运行 Prometheus 的用户比如我们后面会创建的prometheus用户增加限制prometheus soft nofile 65536 prometheus hard nofile 65536 prometheus soft nproc 65536 prometheus hard nproc 655363.2 组件下载与安装我们主要需要三个组件Prometheus Server、Alertmanager 和 node_exporter用于监控本机。建议从官方 GitHub Release 页面下载最新稳定版。使用wget下载并解压到/usr/local目录下。# 创建统一的工作目录和用户 useradd --no-create-home --shell /bin/false prometheus mkdir -p /usr/local/prometheus /usr/local/alertmanager /usr/local/node_exporter # 下载 Prometheus (请替换为最新版本号例如 2.45.0) cd /tmp wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz tar -xzf prometheus-2.45.0.linux-amd64.tar.gz cp prometheus-2.45.0.linux-amd64/prometheus /usr/local/prometheus/ cp prometheus-2.45.0.linux-amd64/promtool /usr/local/prometheus/ cp -r prometheus-2.45.0.linux-amd64/consoles /usr/local/prometheus/ cp -r prometheus-2.45.0.linux-amd64/console_libraries /usr/local/prometheus/ # 下载 Alertmanager (例如 0.25.0) wget https://github.com/prometheus/alertmanager/releases/download/v0.25.0/alertmanager-0.25.0.linux-amd64.tar.gz tar -xzf alertmanager-0.25.0.linux-amd64.tar.gz cp alertmanager-0.25.0.linux-amd64/alertmanager /usr/local/alertmanager/ cp alertmanager-0.25.0.linux-amd64/amtool /usr/local/alertmanager/ # 下载 node_exporter (用于采集本机指标例如 1.6.0) wget https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz tar -xzf node_exporter-1.6.0.linux-amd64.tar.gz cp node_exporter-1.6.0.linux-amd64/node_exporter /usr/local/node_exporter/目录权限设置将相关目录的所有权赋予prometheus用户确保它有写入权限比如 Prometheus 的数据目录。chown -R prometheus:prometheus /usr/local/prometheus chown -R prometheus:prometheus /usr/local/alertmanager chown -R prometheus:prometheus /usr/local/node_exporter3.3 配置系统服务Systemd Unit File用 Systemd 来管理服务是最规范的方式便于启停、查看状态和设置开机自启。1. 配置 node_exporter 服务 创建文件/etc/systemd/system/node_exporter.service[Unit] DescriptionNode Exporter Wantsnetwork-online.target Afternetwork-online.target [Service] Userprometheus Groupprometheus Typesimple ExecStart/usr/local/node_exporter/node_exporter Restarton-failure [Install] WantedBymulti-user.target2. 配置 Prometheus 服务 创建文件/etc/systemd/system/prometheus.service。这里的关键是--config.file和--storage.tsdb.path参数。[Unit] DescriptionPrometheus Wantsnetwork-online.target Afternetwork-online.target [Service] Userprometheus Groupprometheus Typesimple ExecStart/usr/local/prometheus/prometheus \ --config.file/usr/local/prometheus/prometheus.yml \ --storage.tsdb.path/usr/local/prometheus/data \ --web.console.templates/usr/local/prometheus/consoles \ --web.console.libraries/usr/local/prometheus/console_libraries \ --web.listen-address0.0.0.0:9090 Restarton-failure [Install] WantedBymulti-user.target3. 配置 Alertmanager 服务 创建文件/etc/systemd/system/alertmanager.service。注意它的配置文件路径。[Unit] DescriptionAlertmanager Wantsnetwork-online.target Afternetwork-online.target [Service] Userprometheus Groupprometheus Typesimple ExecStart/usr/local/alertmanager/alertmanager \ --config.file/usr/local/alertmanager/alertmanager.yml \ --storage.path/usr/local/alertmanager/data \ --web.listen-address0.0.0.0:9093 Restarton-failure [Install] WantedBymulti-user.target创建好服务文件后执行systemctl daemon-reload重新加载 Systemd 配置。先别急着启动因为核心的配置文件我们还没写。4. 核心配置文件详解与实操配置文件是这套系统的灵魂写错了要么不工作要么乱告警。我们一步步来。4.1 编写 Prometheus 主配置文件 (prometheus.yml)这个文件定义了 Prometheus 抓谁、怎么抓、告警规则在哪以及告警发给谁。在/usr/local/prometheus/目录下创建或编辑prometheus.yml。# 全局配置 global: scrape_interval: 15s # 默认抓取间隔 evaluation_interval: 15s # 规则评估间隔 # 告警规则文件路径 rule_files: - rules/*.yml # 我们将告警规则统一放在rules目录下 # 告警管理器配置 alerting: alertmanagers: - static_configs: - targets: - localhost:9093 # Alertmanager 的服务地址和端口 # 抓取配置列表 scrape_configs: # 监控 Prometheus 自身 - job_name: prometheus static_configs: - targets: [localhost:9090] # 监控本机节点通过 node_exporter - job_name: node static_configs: - targets: [localhost:9100] # 可以添加额外的标签这些标签会附加到从这个job抓取的所有指标上 # labels: # env: prod关键点解析scrape_interval和evaluation_interval通常设置成一样比如 15s。太短会增加系统负担太长则告警不灵敏。rule_files支持通配符方便我们按业务或类型组织告警规则。alerting部分告诉 Prometheus产生的告警要推送到哪个 Alertmanager 实例。这里配置的是本机的 9093 端口。scrape_configs里每个job_name代表一类监控目标。targets是具体的 HTTP 端点地址。node_exporter默认监听 9100 端口。4.2 编写第一个告警规则文件告警规则定义了在什么条件下触发告警。我们在/usr/local/prometheus/rules/目录下创建一个文件比如host_monitor.yml。groups: - name: host_monitor rules: # 规则1实例存活告警 - alert: InstanceDown expr: up 0 for: 1m # 条件持续1分钟才触发避免网络抖动误报 labels: severity: critical annotations: summary: 实例 {{ $labels.instance }} 下线 description: {{ $labels.job }} 的实例 {{ $labels.instance }} 已经超过1分钟无法访问。 # 规则2CPU使用率过高告警 - alert: HighCpuUsage expr: (100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)) 80 for: 5m labels: severity: warning annotations: summary: 实例 {{ $labels.instance }} CPU使用率过高 description: 实例 {{ $labels.instance }} 的5分钟平均CPU使用率已超过80%当前值为 {{ $value }}%。 # 规则3内存使用率过高告警 - alert: HighMemoryUsage expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 85 for: 5m labels: severity: warning annotations: summary: 实例 {{ $labels.instance }} 内存使用率过高 description: 实例 {{ $labels.instance }} 的内存使用率已超过85%当前值为 {{ $value | printf \%.2f\ }}%。规则语法精讲alert告警名称在 Alertmanager 中用于分组和识别。exprPromQL 表达式这是核心。它必须返回一个布尔值或一组时间序列。当结果为真或非空时触发告警条件。例如up 0up指标为 0 表示抓取失败。for持续时间。条件必须持续满足该时间告警状态才会从PENDING变为FIRING。这是防止抖动误报的关键。labels为触发的告警附加额外的标签。这里我们添加了一个severity: critical/warning的标签后面在 Alertmanager 中可以根据这个标签路由告警比如 critical 发邮件钉钉warning 只发邮件。annotations告警的详细描述支持模板变量如{{ $labels.instance }}、{{ $value }}。summary是简短摘要description是详细描述这些内容会出现在告警通知里。实操心得for字段的时长设置需要权衡。对于“实例下线”这种需要快速响应的告警可以设短点如30s-1m。对于“CPU使用率”这种可能短暂波动的指标可以设长点如5m。生产环境需要根据业务敏感度和监控数据的噪声水平来调整。4.3 编写 Alertmanager 邮件发送配置 (alertmanager.yml)这是实现邮件告警的关键。编辑/usr/local/alertmanager/alertmanager.yml。这里以使用 QQ 邮箱的 SMTP 服务为例其他邮箱如 163、Gmail、企业邮箱配置类似主要是 SMTP 服务器地址和端口不同。global: # 全局发件人配置 smtp_smarthost: smtp.qq.com:587 # QQ邮箱的SMTP服务器和TLS端口 smtp_from: your-emailqq.com # 发件人邮箱 smtp_auth_username: your-emailqq.com # 通常是完整的邮箱地址 smtp_auth_password: your-authorization-code # 注意这里是授权码不是邮箱登录密码 smtp_require_tls: true # 启用TLS加密 # 路由树决定告警如何分发 route: group_by: [alertname, cluster, severity] # 按这些标签分组 group_wait: 30s # 同一分组内等待多久发送第一批告警为了分组 group_interval: 5m # 同一分组内两次发送通知的最小间隔 repeat_interval: 4h # 如果告警未解决重复发送通知的间隔 receiver: email_admin # 默认接收者 # 子路由可以实现更精细的路由规则 routes: - match: severity: critical receiver: email_admin # 可以继续嵌套 routes # 接收者定义 receivers: - name: email_admin email_configs: - to: adminyourcompany.com # 收件人邮箱 # 邮件标题模板 subject: 【Prometheus告警】{{ .GroupLabels.alertname }} - {{ .CommonLabels.severity | toUpper }} # 邮件正文模板HTML格式 html: | h3告警详情/h3 table border1 trtdb告警名称/b/tdtd{{ .GroupLabels.alertname }}/td/tr trtdb告警级别/b/tdtd{{ .CommonLabels.severity }}/td/tr trtdb故障实例/b/tdtd{{ .CommonLabels.instance }}/td/tr trtdb触发时间/b/tdtd{{ .StartsAt.Format 2006-01-02 15:04:05 UTC }}/td/tr trtdb告警摘要/b/tdtd{{ .CommonAnnotations.summary }}/td/tr /table br/ h4告警描述/h4 pre{{ .CommonAnnotations.description }}/pre br/ h4标签信息/h4 pre {{ range .CommonLabels.SortedPairs }}{{ .Name }} {{ .Value }} {{ end }} /pre br/ p请及时处理。/p # 可选的附加头部 headers: { Subject: 【Prometheus告警】{{ .GroupLabels.alertname }} } # 抑制规则可选用于减少重复告警 inhibit_rules: - source_match: severity: critical target_match: severity: warning equal: [alertname, cluster, instance]配置深度解析全局配置 (global)smtp_smarthostSMTP 服务器地址。这里是个大坑QQ邮箱使用 SSL 的端口是 465使用 STARTTLS 的端口是 587。我推荐用:587配合smtp_require_tls: true兼容性更好。如果使用:465则需要设置smtp_require_tls: false并启用smtp_ssl: true具体要看邮箱服务商的支持。smtp_auth_password千万注意这里填的不是你的邮箱密码而是邮箱服务商提供的“授权码”或“应用专用密码”。以 QQ 邮箱为例需要在“设置”-“账户”中开启 POP3/SMTP 服务然后生成一个授权码。路由配置 (route)group_by告警分组依据。将具有相同alertname,cluster,severity标签的告警合并成一条通知发送避免刷屏。group_wait分组等待时间。假设同一时刻有10条相同告警触发Alertmanager 会等待group_wait时间收集这期间同一分组的所有告警然后一起发出去。repeat_interval重复发送间隔。对于持续未恢复的告警每隔这个时间会重发一次通知提醒你问题还没解决。接收者配置 (receivers)email_configs可以配置多个收件人 (to)。subject和html使用了 Go 的模板语法。.GroupLabels、.CommonLabels、.CommonAnnotations、.StartsAt等都是可用的变量可以从触发的告警中提取信息动态生成邮件内容。我这里的 HTML 模板做了一个简单的表格让邮件内容更清晰。抑制规则 (inhibit_rules)可选但建议配置这个规则的意思是如果有一条severity: critical的告警触发那么所有具有相同alertname,cluster,instance标签的severity: warning告警将被抑制不发送。这非常有用比如当“主机宕机critical”时就没必要再接收“该主机CPU使用率高warning”的告警了。5. 服务启动、验证与告警测试5.1 启动所有服务并设置开机自启按顺序启动服务并检查状态和日志。# 启动 node_exporter systemctl start node_exporter systemctl enable node_exporter systemctl status node_exporter # 启动 Alertmanager systemctl start alertmanager systemctl enable alertmanager systemctl status alertmanager # 启动 Prometheus systemctl start prometheus systemctl enable prometheus systemctl status prometheus关键检查点systemctl status查看服务状态确保是active (running)。使用journalctl -u prometheus -f或tail -f /var/log/messages取决于系统日志配置实时查看日志排查启动错误。常见错误包括配置文件语法错误、端口被占用、目录权限不足。5.2 验证组件是否正常工作验证 node_exporter浏览器访问http://服务器IP:9100/metrics应该能看到大量的node_开头的指标文本。验证 Prometheus访问http://服务器IP:9090。点击Status - Targets应该能看到prometheus和node两个 job 的状态都是UP。点击Status - Rules应该能看到我们定义的host_monitor规则组。在 Graph 页面输入up并执行应该能看到值为1的曲线表示抓取成功。验证 Alertmanager访问http://服务器IP:9093。如果配置正确界面应该能正常打开。在Status页面可以看到当前的配置信息。5.3 手动触发告警测试邮件发送这是最激动人心的一步。我们模拟一个条件来触发告警。方法一停止 node_exporter 服务触发InstanceDown告警systemctl stop node_exporter等待大约1分钟我们在规则里设置了for: 1m然后刷新 Prometheus 的Alerts页面 (http://IP:9090/alerts)你应该会看到InstanceDown告警的状态从Inactive变为Pending再变为Firing。切换到 Alertmanager 的界面 (http://IP:9093)在Alerts标签页下应该能看到这条FIRING状态的告警。检查配置的收件人邮箱应该会收到一封告警邮件。邮件的标题和内容应该符合我们在alertmanager.yml中定义的模板。方法二制造高 CPU 负载触发HighCpuUsage告警 在服务器上运行一个消耗 CPU 的命令比如dd if/dev/zero of/dev/null # 运行多个来增加负载观察后记得用 kill 命令结束这些进程等待5分钟规则中for: 5m观察告警是否触发和邮件是否收到。测试完成后恢复服务systemctl start node_exporter # 并结束掉制造负载的进程例如 pkill -f dd if/dev/zero告警恢复后Alertmanager 也会发送一条“已解决”RESOLVED的通知邮件。6. 生产环境进阶配置与故障排查实录基础功能跑通只是第一步要用于生产环境还需要考虑更多。6.1 配置热重载与配置文件校验每次修改配置文件都重启服务太麻烦而且有中断风险。Prometheus 和 Alertmanager 都支持热重载Reload。Prometheus 热重载首先在prometheus.yml的global部分或启动参数中确保没有禁用 web API。发送 POST 请求到/-/reload端点curl -X POST http://localhost:9090/-/reload或者更安全的方式是在启动 Prometheus 时使用--web.enable-lifecycle参数然后使用curl -X POST http://localhost:9090/-/reload。注意生产环境谨慎开启此 API或做好访问控制。Alertmanager 热重载 类似发送请求到其/-/reload端点curl -X POST http://localhost:9093/-/reload配置文件语法校验 在应用配置前先用工具校验可以避免低级错误。# 校验 prometheus.yml /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml # 校验 alertmanager.yml /usr/local/alertmanager/amtool check-config /usr/local/alertmanager/alertmanager.yml6.2 邮件发送失败问题深度排查邮件发不出去是最常见的问题。按照以下链条逐一排查检查 Alertmanager 日志journalctl -u alertmanager -f或查看其数据目录下的日志文件。错误信息最直接。检查 SMTP 连接端口与加密确认smtp_smarthost的端口587或465和smtp_require_tls/smtp_ssl设置匹配你的邮箱服务商要求。587端口对应STARTTLS通常配smtp_require_tls: true465端口对应SSL通常配smtp_ssl: true且smtp_require_tls: false。这是最容易出错的地方。授权码100%确认smtp_auth_password填的是授权码不是登录密码。去邮箱设置里重新生成一个试试。发件人地址smtp_from和smtp_auth_username是否与生成授权码的邮箱完全一致网络连通性在服务器上使用telnet或nc命令测试是否能连接到 SMTP 服务器。telnet smtp.qq.com 587 # 或 nc -vz smtp.qq.com 587如果连接失败可能是服务器防火墙虽然我们关了或云服务商的安全组规则阻止了出站连接。查看 Alertmanager UI在 Alertmanager 的 Web 界面 (http://IP:9093)查看Status-Configuration确认你的配置已经正确加载。查看Alerts页面确认告警是否已经到达 Alertmanager 并处于FIRING状态。检查 Prometheus 告警规则在 Prometheus 的Alerts页面确认告警规则是否已触发 (FIRING)。如果没触发检查规则表达式和for时长。6.3 性能优化与数据保留策略Prometheus 数据保留默认数据保留15天。可以在 Prometheus 启动命令中通过--storage.tsdb.retention.time参数调整例如--storage.tsdb.retention.time30d保留30天。更长时间的数据建议使用远程存储方案如 Thanos、Cortex。告警分组与抑制合理设置group_by、group_wait、group_interval和repeat_interval能有效避免告警风暴提升体验。inhibit_rules更是减少干扰告警的利器。资源监控别忘了监控 Prometheus 和 Alertmanager 自己。可以为它们也配置job监控其内存使用量、抓取错误率等确保监控系统自身健康。6.4 高可用与扩展性考量对于核心业务监控系统本身也需要高可用。Prometheus 高可用可以运行两个完全相同的 Prometheus Server 实例同时抓取目标构成冗余。Alertmanager 集群Alertmanager 原生支持集群模式。启动多个实例在prometheus.yml的alerting部分配置所有实例的地址。集群内的 Alertmanager 会自动去重和同步告警状态确保通知只发一次。远程存储当数据量巨大或需要长期存储时可以配置 Prometheus 将数据远程写入到如 Thanos、M3DB、InfluxDB 等系统中。折腾完这一套看着告警邮件准确地飞入邮箱心里总算踏实了。这套组合的灵活性在于一旦基础打通后续要加监控项写新的 Exporter 和抓取配置、加告警规则写新的 PromQL、或者换通知渠道比如加个钉钉 Webhook都变得有章可循。最重要的经验就是配置文件语法要细心邮件服务商的 SMTP 配置端口、加密、授权码是最大的坑多试几次告警规则里的for字段和 Alertmanager 的路由、分组参数需要根据实际业务流量和告警敏感性反复调整才能达到既及时又不扰民的最佳状态。