上两篇我们讲了指标(Prometheus/Grafana)和三支柱框架。这一篇补齐监控闭环的另外两块:集中式日志和告警。
想象一个场景:你有 10 台服务器,每台都在本地打日志。半夜出问题,你得一台台 SSH 上去翻日志,累得半死还找不到。更糟的是,没人告诉你”出问题了”,是用户先发现了。这一篇就是解决这两件事:把日志集中起来好查,让问题主动报警到人。
第一块:集中式日志(ELK / Loki)
单机 tail -f 在集群时代彻底失效。解决方案是日志集中化:所有服务的日志统一发到一个地方存储、检索。
最经典的方案是 ELK:
- E(Elasticsearch):搜索引擎,负责存日志、提供全文检索。
- L(Logstash):收集器,负责从各服务把日志拉来、清洗、转发。
- K(Kibana):界面,负责在网页上搜索、画图、看日志。
轻量替代是 Loki(Grafana 出品):思路和 ELK 类似,但存储更省,和 Prometheus/Grafana 生态天然一体,适合已经用 Grafana 的团队。
典型数据流:
应用打日志 → 采集器(Filebeat/agent) → 存储(ES/Loki) → 界面(Kibana/Grafana) 检索
实战中,应用打结构化 JSON 日志,采集器自动把每条日志带上 service、level、request_id 等字段。出问题时,你在界面搜 level:error AND service:order,一秒定位订单服务的所有错误,再按 request_id 串联一次请求的完整轨迹。
第二块:告警——让问题主动找你
光有仪表盘还不够:你不可能 24 小时盯着屏幕。告警(Alerting)的作用是:当指标或日志触发条件时,自动发消息(钉钉/飞书/邮件/电话)通知到人。
告警一般挂在监控系统上。比如 Prometheus 配 Alertmanager,定义规则:
groups:
- name: 示例告警
rules:
- alert: 错误率过高
expr: sum(rate(http_requests_total{status="500"}[5m])) / sum(rate(http_requests_total[5m])) > 0.01
for: 5m
labels:
severity: warning
annotations:
summary: "错误率超过 1% 已持续 5 分钟"
解释:
expr:PromQL 表达式,这里是”5xx 错误率占比超过 1%”。for: 5m:持续 5 分钟才报警,避免瞬间抖动误报(很重要,下面讲)。labels.severity:严重程度,用于决定通知渠道(warning 发群,critical 打电话)。- 触发后,Alertmanager 把告警推到钉钉/飞书/邮件。
SLO 与 SLI:告警该基于什么设
新手常犯的错:把所有指标都设告警,结果告警雪崩,大家麻木忽略(叫”告警疲劳”)。正确做法是先定义 SLO/SLI:
- SLI(Service Level Indicator,指标):衡量服务质量的真实指标,比如”请求成功率""P99 延迟”。
- SLO(Service Level Objective,目标):你承诺的服务水平,比如”成功率 ≥ 99.9%""P99 延迟 < 300ms”。
- 错误预算(Error Budget):允许的失误空间。99.9% 意味着一个月约 43 分钟不达标是可以接受的。
告警应围绕 SLO 设:当”错误预算”快烧完时才报警,而不是”每次小波动都叫”。这样既及时又不扰民。
告警设计的几条铁律
- 宁可少报,别滥报:每条告警都该”值得你爬起来处理”。无意义的告警最终会被忽略,真出事反而没人看。
- 加
for持续时间:避免瞬时抖动误报。CPU 飙一下就报警,半夜把你叫醒发现是定时任务,纯属折磨。 - 分级路由:warning 发群消息,critical 打电话/发短信。别所有告警一个级别。
- 告警要可行动:一条好告警应包含”是什么、在哪、怎么查”。只写”CPU 高”不如写”订单服务 CPU 95%,见 Grafana 面板 X”。
- 有告警就要有 runbook:接到告警该怎么做,写成文档。否则新手接到告警只会发呆。
常见坑位提醒
- 日志没结构化:纯文本日志在 ES 里只能全文搜,没法按字段过滤。尽早统一 JSON 日志格式。
- 采集器成为瓶颈:日志量巨大时,采集器(Logstash)可能跟不上。用轻量 Filebeat 做采集、必要时加队列缓冲。
- 告警阈值拍脑袋:“CPU > 80% 就报警”可能永远在响或从不响。基于历史数据和 SLO 定阈值。
- 只告警不治理:告警来了处理完就完事,不复盘根因,同样的问题反复报。建立”告警→处理→复盘→优化”闭环。
- 忘了日志保留期:ES 存全量日志很贵,设合理的保留周期(如 30 天热数据 + 归档),别无脑永久存。
小测验:看看你掌握了没
- 问题一:为什么需要集中式日志?答案:多机环境下逐台翻日志低效,集中化后才能跨服务按字段检索、按 request_id 串联。
- 问题二:告警为什么要加
for: 5m?答案:过滤瞬时抖动,避免误报造成告警疲劳。 - 问题三:SLO 和 SLI 的区别?答案:SLI 是真实质量指标,SLO 是你承诺的目标值,告警应围绕 SLO 设。
这一篇你该记住的
- 集中式日志:ELK(Elasticsearch+Logstash+Kibana)或轻量 Loki,把分散日志汇聚检索。
- 应用打结构化 JSON 日志,带
service/level/request_id,便于过滤与串联。 - 告警基于监控系统(如 Prometheus + Alertmanager),
expr定条件、for防抖、分级路由通知。 - 告警围绕 SLO/SLI 设计,用错误预算避免告警疲劳;铁律:少而可行动、有 runbook。
- 坑:日志非结构化难查、阈值拍脑袋、只告警不复盘。
学到这里,监控三件套(指标/日志/告警)你都齐了。但现代服务往往跑在容器和编排平台上——如何把应用弹性地部署、扩缩容、自愈?这就引出了我们的最后一个系列:云原生。