日志聚合:ELK/Loki 思路与结构化日志
服务一多,日志散落在成百上千个容器里,排查问题变成“登录十台机器 grep”。日志聚合把分散日志集中采集、统一检索;配合链路追踪字段,才能“一条 traceId 串起整条调用链”。本章讲聚合思路、结构化日志与 ELK/Loki 两种典型方案。
先做对一件事:结构化日志
聚合的前提是日志可被机器解析。别再打一堆拼接字符串,统一输出 JSON 结构化日志,字段名固定,采集与检索才有意义。
<!-- logback-spring.xml 片段:JSON 输出 + 关键字段 -->
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"app":"order-service"}</customFields>
</encoder>
</appender>
推荐字段(统一命名规范):
{
"timestamp": "2025-06-01T10:00:00.123Z",
"level": "WARN",
"app": "order-service",
"instance": "10.0.1.11:8080",
"traceId": "a1b2c3d4e5f6",
"spanId": "x1y2z3",
"message": "扣减库存失败,走降级",
"userId": 10086,
"costMs": 321
}
规范建议:时间统一 UTC/带时区、traceId/spanId/环境/实例必带、业务上下文(订单号、用户号)作为独立字段而非拼进 message、禁止打印明文口令与敏感数据。
方案一:ELK/EFK
经典组合 Elasticsearch + Logstash + Kibana(采集端常用 Filebeat):
服务容器日志(stdout)
│
▼
Filebeat(轻量采集,逐行/按 JSON 解析)
│
▼
Logstash(可选:清洗、过滤、转换)
│
▼
Elasticsearch(存储 + 倒排索引)
│
▼
Kibana(检索、看板、告警)
- 优点:全文检索强、生态成熟、Kibana 可视化与告警完善。
- 缺点:ES 集群资源占用高,日志量大时成本可观。
- 适用:检索条件复杂、需要长期留存分析、预算充足。
方案二:Loki + Grafana
Grafana Loki 走“标签索引 + 原文存储”路线,采集端为 Promtail,展示复用 Grafana:
容器日志 --> Promtail(打标签) --> Loki(按标签索引)
│
▼
Grafana(LogQL 检索 + 看板,可与指标同屏)
- 优点:轻量、成本低,与 Prometheus 指标体系天然打通(指标与日志同一界面关联)。
- 缺点:全文检索能力弱于 ES,复杂分析不如 ELK 灵活。
- 适用:以“查原文、关联指标”为主的中等规模集群。
选型不必纠结:追求检索与分析能力选 ELK,追求轻量与指标联动选 Loki;两者都要求“结构化 + 打标签”先行。
采集与落地的通用要点
- 日志只写 stdout:容器/编排平台统一接管输出,采集器从 stdout 收集,禁止应用自己写文件(多副本下文件管理是灾难)。
- 按服务/环境打标签:检索第一刀切 namespace/环境/服务,第二刀切 traceId/时间。
- 保留策略分级:近期热数据全量留存,老数据压缩或按服务裁剪,避免成本失控。
- 敏感信息脱敏:日志输出前对手机号、令牌等做掩码,采集链路启用传输加密。
- 与应用监控联动:日志只是“事后的现场”,要与指标告警配合——先由指标触发告警,再由日志定位根因。
小结
日志聚合三件事:应用侧输出结构化 JSON(带 traceId/业务字段)、采集侧统一入湖并打标签、检索侧按环境-服务-链路 ID 收敛。ELK 强在检索分析,Loki 强在轻量联动;先统一日志规范,再选平台,工具永远排在规范后面。