Grafana Loki
特点
Grafana Loki 是为云原生设计的日志聚合系统,设计理念「Like Prometheus, but for logs」。
| 特性 | 说明 |
|---|---|
| 仅索引标签 | 不对日志内容全文索引,存储成本极低 |
| 标签驱动 | 与 Prometheus 相同的标签体系 |
| 对象存储 | 支持 S3/GCS/MinIO 做后端存储 |
| 多租户 | 原生支持 tenant ID 隔离 |
| Grafana 集成 | 无缝集成 Grafana 面板和告警 |
与 Elasticsearch 的关键区别
Loki 不索引日志内容,查询时是 grep 式扫描。如果需要高频全文搜索复杂字段,ES 更合适;如果主要按服务/Pod 标签过滤后查看日志,Loki 足够且成本低 10x。
架构
| 组件 | 职责 |
|---|---|
| Promtail / Alloy | 日志采集 agent,发现并标记日志 |
| Distributor | 接收日志、校验、分发到 Ingester |
| Ingester | 内存缓冲、压缩,批量写入存储 |
| Querier | 查询引擎,合并存储和 Ingester 数据 |
部署
Helm 安装 Loki Stack
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki-stack \
--set promtail.enabled=true \
--set grafana.enabled=true \
--namespace logging --create-namespace
单体模式配置(小规模)
loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 30d
S3 后端(生产环境)
loki-s3.yaml
common:
storage:
s3:
endpoint: s3.amazonaws.com
bucketnames: loki-logs
region: ap-southeast-1
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
LogQL 查询
基础语法
# 按标签过滤
{namespace="production", app="order-service"}
# 文本匹配
{app="order-service"} |= "error" # 包含 error
{app="order-service"} != "healthcheck" # 不包含
{app="order-service"} |~ "timeout|refused" # 正则
# JSON 解析 + 字段过滤
{app="order-service"} | json | level="ERROR" | duration > 1000
# 管道操作
{app="order-service"}
| json
| level="ERROR"
| line_format "{{.timestamp}} [{{.level}}] {{.message}}"
聚合查询
# 每分钟错误数
count_over_time({app="order-service"} |= "ERROR" [1m])
# 各服务错误率 Top 5
topk(5, sum by(app)(rate({namespace="production"} |= "ERROR" [5m])))
# P99 响应时间(JSON 日志中提取 duration 字段)
quantile_over_time(0.99, {app="api"} | json | unwrap duration [5m]) by (endpoint)
Promtail 配置
promtail-config.yaml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# K8s Pod 日志自动发现
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
target_label: app
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
pipeline_stages:
# JSON 日志提取 level 作为标签
- json:
expressions:
level: level
- labels:
level:
# 丢弃 DEBUG 日志
- match:
selector: '{level="DEBUG"}'
action: drop
常见面试问题
Q1: Loki 为什么比 ES 成本低?
答案:
Loki 只索引标签(如 app=order-service),不索引日志内容。日志文本以压缩块(gzip/snappy)存储在对象存储(S3)。查询时通过标签筛选出相关块,再在块内 grep 搜索。相比 ES 的全文倒排索引,存储占用低 5-10 倍。代价是复杂全文搜索性能不如 ES。
Q2: 什么场景选 ELK,什么场景选 Loki?
答案:
| 场景 | 推荐 |
|---|---|
| 安全审计、全文搜索 | ELK |
| 已有 ES 集群和运维经验 | ELK |
| K8s 云原生环境 | Loki |
| 成本敏感 | Loki |
| 已有 Grafana + Prometheus 栈 | Loki |