第二章:故障发现机制——监控体系搭建与告警设计

大家好,我是老赵。今天咱们聊聊故障发现机制。

说实话,很多团队出问题,不是没有监控,而是监控太“吵”了。告警邮件一天几百封,最后大家都麻木了。真正出大事时,反而没人看。

我个人习惯是:先搭骨架,再填血肉。骨架就是 Prometheus + Grafana,血肉就是日志和告警规则。今天我把这套方法论拆开讲。

2.1 监控体系搭建:Prometheus + Grafana

Prometheus 这东西,说白了就是一个时序数据库。它拉取数据,存起来,然后 Grafana 负责展示。我见过不少团队一上来就搞全链路监控,结果数据量太大,Prometheus 直接 OOM。

我的建议是:先监控核心指标。比如 CPU、内存、磁盘、网络,再加几个业务关键接口的 QPS 和延迟。够了。

2.1.1 架构图

下面这张图是我自己画的,你看一眼就明白整体流程了。

Prometheus + Grafana 监控体系架构 应用实例 1 应用实例 2 应用实例 3 Exporter Prometheus Server (拉取 / 存储 / 告警) Alertmanager Grafana 钉钉 / 邮件 图例: 被监控应用 Exporter Prometheus Alertmanager Grafana

2.1.2 快速部署示例

我一般用 Docker Compose 快速搭一套。你直接复制下面这个文件就行。

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123

  alertmanager:
    image: prom/alertmanager:latest
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    ports:
      - "9093:9093"
小提示:Grafana 默认用户名是 admin,密码也是 admin。第一次登录会让你改密码。我习惯改成 admin123,方便测试,但生产环境千万别这么干。

2.2 日志采集与分析:ELK Stack

监控指标只能告诉你“系统挂了”,但日志能告诉你“为什么挂”。ELK 三件套——Elasticsearch、Logstash、Kibana,是业界标配。

我记得有一次线上告警说“接口超时”,我查了 Prometheus 指标,发现 CPU 不高、内存也不高。最后是去 Kibana 翻日志,才发现是数据库连接池满了。你看,指标和日志得配合着用。

2.2.1 日志采集流程

简单画个流程:

  1. Filebeat 采集应用日志文件
  2. Logstash 做过滤和格式化
  3. Elasticsearch 存储和索引
  4. Kibana 展示和搜索

你想想看,如果没有 Logstash 做过滤,原始日志里全是 DEBUG 信息,你搜个错误得翻半天。所以过滤规则一定要写好。

2.2.2 Logstash 配置示例

input {
  beats {
    port => 5044
  }
}

filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message}" }
  }
  date {
    match => [ "timestamp", "ISO8601" ]
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "app-logs-%{+YYYY.MM.dd}"
  }
}
注意:grok 正则写不好,日志解析会失败。我曾经因为一个空格没匹配上,导致一整天的日志都没索引进去。建议先在 Kibana 的 Grok Debugger 里测试。

2.3 告警规则设计

告警规则是监控的灵魂。规则写得好,半夜少被叫醒。我总结了几条核心原则:

  • 少而精:只对真正影响业务的问题告警
  • 分级别:P0(致命)、P1(严重)、P2(警告)
  • 有阈值:不要用固定值,用百分比或动态阈值

2.3.1 Prometheus 告警规则示例

groups:
  - name: example-alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "实例 {{ $labels.instance }} CPU 使用率超过 80%"
          description: "当前值: {{ $value }}%"

      - alert: HighMemoryUsage
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "实例 {{ $labels.instance }} 内存使用率超过 90%"
关键点:for 参数很重要。比如 CPU 飙高 5 分钟才告警,避免瞬时抖动导致误报。我见过有人设 for: 0m,结果一天收到 200 条告警,全是假的。

2.4 告警收敛与降噪

告警收敛,说白了就是别让同一个问题重复报警。降噪,就是过滤掉那些无关紧要的噪音。

我曾经遇到过一个场景:一台机器磁盘满了,结果触发了 20 条告警——磁盘告警、日志写不进去告警、应用报错告警……全是同一个根因。这就是典型的“告警风暴”。

2.4.1 收敛策略

策略 说明 实现方式
分组 相同实例的告警合并 Alertmanager 的 group_by
抑制 高优先级告警抑制低优先级 Alertmanager 的 inhibit_rules
静默 已知问题暂时不告警 Alertmanager 的 silences
聚合 相同告警内容合并为一条 Prometheus 的 alertmanager 配置

2.4.2 Alertmanager 配置示例

route:
  group_by: ['instance', 'alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'default-receiver'

receivers:
  - name: 'default-receiver'
    webhook_configs:
      - url: 'http://webhook.dingtalk.com/send'
        send_resolved: true

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['instance']
避坑指南:我曾经把 repeat_interval 设成 5 分钟,结果半夜每 5 分钟收到一条告警,一晚上没睡好。建议设成 4 小时以上,除非问题升级。

2.5 实战经验总结

最后,我分享几个实战中踩过的坑:

  • 监控盲区:只监控了应用,没监控中间件。比如 Redis 挂了,应用还在跑,但请求全超时。所以一定要把 Redis、MySQL、Nginx 都纳入监控。
  • 日志丢失:Filebeat 采集日志时,如果磁盘 IO 高,可能会丢日志。建议加一个缓冲队列,或者用 Kafka 做中转。
  • 告警疲劳:告警太多,人就会麻木。我建议每周复盘一次告警,把那些“永远不需要人工处理”的告警直接删掉。

嗯,今天就聊到这儿。监控体系不是一蹴而就的,需要持续迭代。你先把 Prometheus + Grafana 搭起来,再慢慢加日志和告警规则。别贪多,一步一步来。


专注资料整理