第二章:故障发现机制——监控体系搭建与告警设计
大家好,我是老赵。今天咱们聊聊故障发现机制。
说实话,很多团队出问题,不是没有监控,而是监控太“吵”了。告警邮件一天几百封,最后大家都麻木了。真正出大事时,反而没人看。
我个人习惯是:先搭骨架,再填血肉。骨架就是 Prometheus + Grafana,血肉就是日志和告警规则。今天我把这套方法论拆开讲。
2.1 监控体系搭建:Prometheus + Grafana
Prometheus 这东西,说白了就是一个时序数据库。它拉取数据,存起来,然后 Grafana 负责展示。我见过不少团队一上来就搞全链路监控,结果数据量太大,Prometheus 直接 OOM。
我的建议是:先监控核心指标。比如 CPU、内存、磁盘、网络,再加几个业务关键接口的 QPS 和延迟。够了。
2.1.1 架构图
下面这张图是我自己画的,你看一眼就明白整体流程了。
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"
2.2 日志采集与分析:ELK Stack
监控指标只能告诉你“系统挂了”,但日志能告诉你“为什么挂”。ELK 三件套——Elasticsearch、Logstash、Kibana,是业界标配。
我记得有一次线上告警说“接口超时”,我查了 Prometheus 指标,发现 CPU 不高、内存也不高。最后是去 Kibana 翻日志,才发现是数据库连接池满了。你看,指标和日志得配合着用。
2.2.1 日志采集流程
简单画个流程:
- Filebeat 采集应用日志文件
- Logstash 做过滤和格式化
- Elasticsearch 存储和索引
- 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}"
}
}
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%"
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']
2.5 实战经验总结
最后,我分享几个实战中踩过的坑:
- 监控盲区:只监控了应用,没监控中间件。比如 Redis 挂了,应用还在跑,但请求全超时。所以一定要把 Redis、MySQL、Nginx 都纳入监控。
- 日志丢失:Filebeat 采集日志时,如果磁盘 IO 高,可能会丢日志。建议加一个缓冲队列,或者用 Kafka 做中转。
- 告警疲劳:告警太多,人就会麻木。我建议每周复盘一次告警,把那些“永远不需要人工处理”的告警直接删掉。
嗯,今天就聊到这儿。监控体系不是一蹴而就的,需要持续迭代。你先把 Prometheus + Grafana 搭起来,再慢慢加日志和告警规则。别贪多,一步一步来。