结果导向 · 怎么选 · 为什么 · 生产上长啥样 · 有什么坑
轻、便宜、部署简单、一个面板同时看日志 + 监控指标。除非你需要全文搜索日志内容(见下表),否则没有理由选别的。
| 你的需求 | 选什么 | 一句话原因 |
|---|---|---|
| 中小团队日常排查(按服务/级别/时间查日志) | Loki + Grafana | 存储省 90%,Grafana 一个面板看日志+监控,部署简单 |
| 要像 Google 一样全文搜索日志内容(安全审计/合规) | ELK | ES 倒排索引全文搜索无敌,但存储贵 3-5 倍 |
| 上云了,不想自己运维 | 阿里云 SLS / 腾讯云 CLS | 零运维,按量付费,日志量大时账单贵 |
| K8s 环境 + 要全文搜索 | EFK(Fluentd 替代 Logstash) | Fluentd 比 Logstash 轻,适配容器 |
每个技术一句话说清楚,不用记原理,知道它是干啥的就够了。
| 技术 | 是什么 | 一句话定位 |
|---|---|---|
| Loki | 存日志的数据库 | 只给标签建索引,不索引日志内容 → 省存储 90%,按标签查秒回,全文搜内容慢 |
| Grafana | 可视化看板 | 啥数据源都能接(Loki/Prometheus/ES/MySQL...)→ 一个面板看日志+指标+链路 |
| Promtail | 日志采集器 | Loki 专属采集器,读日志文件打标签发给 Loki,轻量 |
| Elasticsearch (ES) | 搜索引擎 | 给每个词都建索引 → 全文搜索无敌,但存储膨胀 3-5 倍 |
| Kibana | ES 专属看板 | 只能连 ES,接不了别的数据源(这是它和 Grafana 的核心差距) |
| Logstash | 日志采集+处理器 | ELK 里的采集器,Java 写的吃内存(500MB+),现在基本被 Filebeat/Fluentd 替代 |
| Prometheus | 存监控指标的数据库 | 和 Loki 是同一公司(Grafana Labs),Grafana 接它看 CPU/内存/QPS 曲线 |
| SLS / CLS | 云厂商日志服务 | 阿里云/腾讯云托管,②③④⑤ 全包,不用自己部署 |
同样是存这条日志:
| ES(Elasticsearch) | Loki | |
|---|---|---|
| 建什么索引 | 给 level、service、NullPointerException、line、42 每个词都建 | 只给 level=error service=order 两个标签建,msg 内容压缩存 |
| 存储成本 | 1GB 日志 → 3-5GB(索引膨胀) | 1GB 日志 → ~0.1-0.3GB(只有标签索引) |
| 查"order 的 error 日志" | 秒回(标签有索引) | 秒回(标签有索引) |
| 查"含 NullPointerException 的日志" | 秒回(每个词都有索引) | 慢(得逐条扫描内容,查 24h 可能要 2 分钟) |
Grafana 是深色主题的网页应用。下面模拟一个排查线上 ERROR 的场景:左边选数据源,上面输入查询,下面出日志流。
{job="order-service"} |= "ERROR" — LogQL 语法,先按标签选服务,再过滤关键词上面只展示了"查日志",Grafana 实际上是个全能可视化平台。下面用实际界面展示它的主要能力:
| 能力 | 能做什么 | 对应数据源 | 类比 |
|---|---|---|---|
| 搜日志 | 按服务/级别/关键词/时间范围搜索日志 | Loki / ES | 像 Google 搜网页,但搜的是你的日志 |
| 看曲线 | CPU/内存/QPS/延迟等指标的实时曲线图 | Prometheus | 像股票行情图,但看的是你的服务器状态 |
| 链路追踪 | 一条请求从网关→订单→支付→DB 的完整调用链 | Tempo / Jaeger | 像快递物流跟踪,每一步耗时清清楚楚 |
| 告警通知 | 异常时自动发短信/电话/钉钉/企微 | 所有数据源 | 像医院的呼叫系统,病人出问题自动叫医生 |
| 画仪表盘 | 自由拼接面板,做自己的监控大屏 | 混合 | 像 Excel 图表,但数据是实时的、多来源的 |
| 事件标记 | 在图表上标注"发布/重启/扩容"等事件 | 手动或自动 | 在历史曲线上插旗子,方便事后复盘 |
| 搭配 | 是啥 | 为啥搭配 |
|---|---|---|
| Prometheus | 存监控指标(CPU/内存/QPS) | 同一生态,Grafana 一个面板同时看 Loki 日志 + Prometheus 指标。这是最常见组合 |
| Tempo / Jaeger | 链路追踪 | Grafana 生态,点 traceId 从日志跳到调用链 |
| Alertmanager | 告警通知 | Grafana 统一告警中心,日志+指标告警都走这里 |
| MinIO / S3 | 对象存储 | Loki 把日志压缩成块存对象存储,比 ES 便宜 10 倍 |
| 搭配 | 是啥 | 为啥搭配 |
|---|---|---|
| Filebeat | 轻量采集器 | 替代 Logstash 做采集(Logstash 太重),Go 写的几十 MB 内存 |
| Kafka | 消息队列 | 日志洪峰时缓冲(如大促),ES 写不过来先扔 Kafka |
| SkyWalking | 链路追踪 | ES 存日志 + SkyWalking 存调用链,traceId 串联 |
现象:用户反馈下单失败,监控显示 order-service 接口 5xx 错误率从 0.1% 飙到 23%。值班同学打开 Grafana。
Step 1 — 打开 Grafana Explore,选 Loki 数据源,输入查询
Step 2 — 点开一条 ERROR 日志,看到完整内容和标签(traceId)
Step 3 — 点击 "Jump to Trace",自动切到 Tempo 数据源看调用链
| 调用链 | api-gateway → order-service → payment-service → mysql | ||
| 15ms ✓ | 28ms ⚠️ | 3212ms ❌ | |
| 总耗时 | 3255ms (正常 ~100ms) | ||
现象:告警 order-service CPU 使用率持续 95%+。值班同学打开 Grafana 监控 Dashboard。
Dashboard 全貌:同一页面同时展示指标曲线 + 日志流 + 告警状态
现象:双 11 凌晨 00:00,日志量从 1GB/h 飙到 50GB/h,ES 写不过来,开始丢日志。
没有 Kafka 的架构(出问题的)
加上 Kafka 后的架构(扛住的)
现象:在 Grafana 输入 {job="order-service"} |= "NullPointerException",查最近 24 小时,转了 2 分钟才返回。
原因:Loki 只索引标签不索引内容,全文搜索 = 全量扫描,时间范围越大越慢。
解法:
{job="order-service", level="ERROR"} 再搜关键词error_type="NPE",直接按标签查教训:Loki 不是 ES,全文搜索是弱项。要么缩小范围,要么上 ES。
现象:开发把日志级别从 INFO 改成 DEBUG,日志量翻 10 倍。3 小时后 ES 磁盘 95% → 进入只读模式 → 所有日志写入失败。
原因:ES 默认 95% 磁盘水位后只读。没有磁盘告警 + 没有日志保留策略。
解法:紧急删旧索引 → 配 ILM 自动清理 7 天前索引 → 加磁盘告警 80% 预警 → 日志级别改回 INFO。
教训:ES 磁盘 = 生命线。必须配 ILM 自动清理 + 磁盘告警 + 日志级别管控。
现象:配了 50 条告警规则,ERROR > 10/分钟就告警。某次发布引入 bug,50 条同时触发,每 5 分钟重复一次,10 分钟收 200+ 条短信,手机卡死。
原因:告警没有去重、分组、抑制。
解法:同服务告警合并成一条 → P0 告警抑制同服务 P2/P3 → 同告警 15 分钟不重复 → 分级(P0 电话/P1 短信/P2 即时消息/P3 邮件)。
教训:告警不是越多越好。告警风暴比没告警更可怕 — 会淹没真正重要的告警。
tail -f + grep 够用趋势:越来越多团队从 Kibana 迁到 Grafana,因为统一面板是刚需。
ES 用 ILM 自动删,Loki 用 retention 配置。不要一直存,磁盘费钱。
值得:公司上云 + 不想自己运维 + 日志量中等 → 零运维省心。
不值得:日志量极大(TB/天,账单爆炸)+ 数据合规不能出机房(金融/政务)+ 需要深度定制。
成本对比:日均 100GB 日志,SLS 约 ¥9000/月;自建 Loki 3 台 4C8G 约 ¥1500/月。日志量小用云省心,量大自建便宜。
JSON 结构化日志 + traceId。传统文本日志:
2026-06-18 10:30:45 ERROR OrderService - NullPointerException at line 42
日志系统要解析这个得用 grok 正则(脆弱、耗 CPU)。
JSON 格式(推荐):
{"@timestamp":"2026-06-18T10:30:45","level":"ERROR","logger":"OrderService","traceId":"abc123","message":"NullPointerException at line 42"}
直接被索引为字段,搜索 level: "ERROR" 秒级返回。配置:logback + logstash-logback-encoder,traceId 通过 MDC 注入。