文章

日志体系 Loki 与 ELK 对比

日志体系:Loki 与 ELK 对比

一句话:日志是”离散事件记录”,回答”刚才到底发生了什么”。两种主流模型——索引型(ELK)标签型(Loki)——本质是”在全文建倒排索引”vs”只给日志流打少量标签、靠对象存储堆原文”的成本取舍。

两种模型的根本差异

维度ELK(Elasticsearch)Loki(Grafana)
索引策略每条日志的每个字段建倒排索引不索引内容,只对少量 Label(如 namespace/pod)建索引
存储索引 + 原始文档(贵的 SSD/热存)压缩后的日志块存对象存储(S3),极便宜
查询任意字段全文检索(强大)先按 Label 过滤,再对块内做 grep 式查询
成本高(索引占大头)低(对象存储 + 无字段索引)
适用需要复杂字段检索/审计K8s 环境、与 Prometheus 标签体系对齐
查询语言KQL / LuceneLogQL

选型直觉:如果你的日志查询习惯是”先按服务/命名空间缩小范围,再看具体内容”——这正是 K8s 场景——Loki 成本只有 ELK 的 1/10~1/5。ELK 适合”我要在任意字段里搜一个订单号”的强检索需求。

采集层:Fluent Bit / Vector / Promtail

graph LR
    C[容器 stdout] --> FB[Fluent Bit / Vector]
    FB --> L[Loki]
    FB --> ES[Elasticsearch]
采集器特点
Fluent Bit轻量(C 写)、K8s DaemonSet 标配、低资源
VectorRust 写、管线强、可做 transform/路由
PromtailLoki 原生、自动加 K8s Label(逐渐被 Grafana Alloy 取代)
Grafana AlloyOTel 原生、同时收 metrics/logs/traces,取代 Promtail

Loki 架构

graph TD
    ING[Ingester] --> S3[(对象存储: chunks)]
    DIS[Distributor] --> ING
    Q[Querier] --> S3
    DIS --> Q
    COMP[Compactor] --> S3
  • Distributor:接收、校验、按流哈希分发给 Ingester
  • Ingester:内存攒批、建索引、flush 到对象存储
  • Querier:查时先读索引定位块,再拉块过滤
  • Compactor:合并小块、降成本

LogQL 速查

# 基础:按标签过滤
{namespace="prod", container="api"} 

# 行过滤(正则)
{namespace="prod"} |= "error" != "timeout"

# 计数-rate
count_over_time({container="api"}[5m])

# 提取标签并聚合(类似 PromQL)
sum by (status) (count_over_time({container="api"} | json | status_code >= 500 [5m]))

与 Traces 关联

现代日志最佳实践:在日志里带上 trace_id,Grafana 数据链接一键从日志跳到对应 trace(Tempo/Jaeger)。这把 Logs 和 Traces 两个信号缝起来——你 Cilium Hubble 的 flow 日志也可带 trace 关联。

常见反模式

  1. 用日志做指标:不该用 count_over_time 长期算 QPS,那是 Metrics 的活(Prometheus 更便宜)
  2. Label 高基数:Loki 的 Label 同样怕 user_id 这种爆炸维度
  3. 不采样不轮转:日志无限增长,必须配 retention + 级别采样
  4. 敏感信息落日志:token/密码进日志是合规事故(和你 Security 的密钥管理相关)

关联知识

参考资源

学习时间

内容日期状态
日志体系 Loki/ELK2026-07-24完成:两模型差异、采集器、Loki 架构、LogQL、关联、反模式

状态

  • 索引型 vs 标签型
  • 采集器对比
  • Loki 架构
  • LogQL
  • 与 Trace 关联 + 反模式