🔄 背景与目标

这台 HP 服务器的个人 DevOps 平台已经搭了大半,监控底座是必须先稳的环节。我用 Docker Compose 部署了 Prometheus + Grafana 监控体系,node_exporter 探针、告警规则全都配好,本以为顺风顺水,结果一关探针就傻眼:告警在页面亮着,日志也在刷,就是收不到邮件。

于是干脆沉下心,从「从零安装部署」到「全链路踩坑排查」,把整条链路从头捋一遍,目标很简单:关掉探针就报警、恢复服务就通知,邮件稳稳收到。


🛠️ 第一步:从零搭建 Prometheus + Alertmanager 监控环境

1. 环境准备

  • 宿主机:Ubuntu 22.04,已安装 Docker + Docker Compose
  • 项目目录:~/myapp/project/01-monitor
  • 核心组件:Prometheus 3.10.0、Alertmanager、node_exporter

2. 核心配置文件编写

(1)docker-compose.yml(一键编排所有服务)

yaml

version: '3.8'

networks:
  monitor-net:
    driver: bridge

services:
  prometheus:
    image: prom/prometheus:v3.10.0
    container_name: prometheus
    volumes:
      - ./prometheus:/etc/prometheus
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.enable-lifecycle'
    ports:
      - "9090:9090"
    networks:
      - monitor-net
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    volumes:
      - ./alertmanager:/etc/alertmanager
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
    ports:
      - "9093:9093"
    networks:
      - monitor-net
    restart: unless-stopped

  node_exporter:
    image: prom/node-exporter:latest
    container_name: node_exporter
    ports:
      - "9100:9100"
    networks:
      - monitor-net
    restart: unless-stopped

volumes:
  prometheus_data:
(2)prometheus/prometheus.yml(Prometheus 主配置)

yaml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
  - static_configs:
    - targets:
      - alertmanager:9093  # 服务名通信,无需硬编码IP

rule_files:
  - "/etc/prometheus/alerts.yml"  # 加载告警规则

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node_exporter'
    static_configs:
      - targets: ['node_exporter:9100']
(3)prometheus/alerts.yml(核心告警规则)

yaml

groups:
- name: host_rules
  rules:
  - alert: 服务器宕机
    expr: up == 0
    for: 30s  # 持续30秒异常才触发,避免误报
    labels:
      severity: critical
    annotations:
      summary: "实例宕机 {{ $labels.instance }}"
      description: "监控不到该机器"
(4)alertmanager/alertmanager.yml(最终生效版,踩坑后修正)

yaml

global:
  resolve_timeout: 5m
  # QQ邮箱正确配置:587端口 + STARTTLS
  smtp_smarthost: 'smtp.qq.com:587'
  smtp_from: '111116091@qq.com'
  smtp_auth_username: '1111091@qq.com'
  smtp_auth_password: 'xxxxxx'  # QQ邮箱授权码,非登录密码
  smtp_require_tls: true

route:
  group_by: ['alertname']
  group_wait: 5s       # 组内告警快速通知
  group_interval: 10s  # 重复告警间隔
  repeat_interval: 1m  # 告警重复发送间隔
  receiver: 'email-only'

receivers:
- name: 'email-only'
  email_configs:
  - to: '91116091@qq.com,142217@qq.com'
    send_resolved: true  # 告警恢复时发送通知

templates:
- '/etc/alertmanager/templates/*.tmpl'

3. 一键启动所有服务

bash

运行

# 进入项目目录
cd ~/myapp/project/01-monitor

# 后台启动所有服务
docker-compose up -d

# 验证服务状态,确保全部正常运行
docker-compose ps


🛠️ 第二步:核心问题排查 —— 告警链路通,但通知发不出来

安装完本以为万事大吉,结果手动停止 node_exporter 触发告警,却始终收不到邮件,前后踩了好几个典型坑:

  • 服务名解析正常,却被 wget 错误提示带偏,死磕网络
  • QQ 邮箱 SMTP 端口与 TLS 模式不匹配,底层直接发不出去
  • 抑制规则默默吞掉告警,日志有但收件箱没有
  • 企业微信 WebHook 格式不兼容,多渠道反而互相干扰

全程一步步排雷,最终把整条链路彻底跑通。

步骤 1:确认网络与服务发现真的正常

先看 Prometheus → Alertmanager 服务发现页面,直接显示 alertmanager:9093 已上线,说明服务名解析正常、网络互通。之前用 wget alertmanager:9093bad address,纯属 Prometheus 镜像内工具的兼容性问题,不要用工具判断监控链路,要看页面状态!

步骤 2:修复 QQ 邮箱 SMTP 配置(最关键根因)

一开始用的错误配置:

yaml

smtp_smarthost: 'smtp.qq.com:465'
smtp_require_tls: true

这俩根本不兼容:

  • 465 是隐式 TLS,连接建立时直接加密,不支持 STARTTLS 命令
  • 587 才是显式 TLS(STARTTLS),和 smtp_require_tls: true 配置项完美匹配

直接改成 587 端口后,邮件底层链路瞬间通了。

步骤 3:删掉抑制规则,别让告警被吃掉

原来的抑制规则:

yaml

inhibit_rules:
- source_match:
    severity: 'critical'
  target_match:
    severity: 'warning'
  equal: ['alertname','instance']

意思是:同一个实例出现 critical 严重告警时,所有 warning 警告告警全部被抑制、不发送。测试阶段直接注释掉,保证所有告警都能正常发出,排查时不再被 “吞告警” 坑。

步骤 4:只保留邮件,去掉企业微信干扰

先把企业微信 WebHook 全删掉,只跑邮件通知,少一个渠道就少一个报错可能,排障效率直接拉满。

步骤 5:重启 Alertmanager 生效配置

bash

运行

docker restart alertmanager

✅ 第三步:最终验证 —— 一关探针,邮件立刻到

1. 手动触发宕机告警

bash

运行

docker stop node_exporter

2. 观察 Prometheus 页面状态

  • 先变成 PENDING(等待 30s,符合 for: 30s 规则)
  • 30s 后自动变成 FIRING(真正触发告警)

3. 查看日志确认链路

bash

运行

# 查看Prometheus日志,确认告警推送至Alertmanager
docker logs --tail 20 prometheus

# 查看Alertmanager日志,确认接收告警、发送邮件
docker logs --tail 20 alertmanager

能清晰看到:告警已触发、已发送至 Alertmanager、已发送邮件,全链路无异常。

4. 查收邮箱

告警邮件稳稳收到! 包含告警级别、实例信息、描述等完整内容。

5. 恢复探针,验证恢复通知

bash

运行

docker start node_exporter

等待 1 分钟后,告警恢复邮件也正常收到,整条链路:采集 → 告警 → 通知 → 恢复,彻底闭环。


⚠️ 避坑总结(干货直接拿走)

  1. 不要用 wget/curl 判断 Prometheus 链路服务发现页面才是标准答案,工具报错不代表服务不通,别被误导死磕网络。

  2. QQ 邮箱一定用 587 + STARTTLS465 会直接静默失败,不报错、不发送、很难排查,是最容易踩的坑。

  3. 测试阶段先关掉 inhibit_rules它会悄悄吞掉 warning 告警,排查时会让你怀疑人生,生产环境按需再开。

  4. 多渠道通知先别一起上先跑通一个,再加第二个,不然错在哪都不知道,排查效率极低。

  5. PENDING 不是故障那是 for: 30s 在等待,等一等就会自动转为 FIRING,无需手动干预。


🚀 下一步计划

监控底座已经稳了,接下来继续往上堆:

  • 接入企业微信机器人告警,实现邮件 + 微信双渠道通知
  • 完善 CPU、内存、磁盘使用率等多维度告警规则
  • 做一套统一的告警模板,优化通知样式
  • 接入 Grafana 面板,做成完整可视化监控体系

 关注我

持续更新《人生底稿》成长史 &《技术底稿》实战干货一起踏实成长,不焦虑、不内卷。

 📚 系列导航:

 【人生底稿 01】|农村少年(1995–2005)

 【技术底稿】01:37岁老码农,用4台机器搭了套个人DevOps平台

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐