600_Loki日志聚合
一句话概述:Grafana Loki 是轻量级日志聚合系统,被称为"日志界的 Prometheus"——只索引标签不索引日志内容,存储成本极低,通过 LogQL 查询语言搜索日志,与 Grafana 深度集成,是云原生时代 ELK 的轻量替代方案。
核心知识点表
| 概念 | 白话解释 |
|---|
| Loki | 日志存储和查询引擎,只索引标签(省存储) |
| Grafana Alloy | 日志采集器(替代已废弃的 Promtail),收集并发送日志到 Loki |
| LogQL | Loki 的查询语言,类似 PromQL 但用于日志 |
| Label | 标签,日志的元数据(如 job、namespace),Loki 用标签索引 |
| Stream | 日志流,同一组标签的日志集合 |
| Chunk | 数据块,日志的压缩存储单元 |
| Tenant | 租户,多租户隔离(不同团队的日志互不可见) |
安装配置
Docker Compose 部署(推荐)
# docker-compose.yml — Loki + Grafana Alloy + Grafana
services:
loki:
image: grafana/loki:3.7.1 # Loki v3.7
container_name: loki
ports:
- "3100:3100" # HTTP API 端口
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml # 配置文件
- loki-data:/loki # 数据持久化
command: -config.file=/etc/loki/local-config.yaml
alloy:
image: grafana/alloy:latest # Grafana Alloy(日志采集)
container_name: alloy
volumes:
- ./alloy-config.alloy:/etc/alloy/config.alloy # 配置文件
- /var/log:/var/log:ro # 挂载系统日志(只读)
- /var/lib/docker/containers:/var/lib/docker/containers:ro # Docker 日志
command: run /etc/alloy/config.alloy
depends_on:
- loki
grafana:
image: grafana/grafana:latest # Grafana 可视化
container_name: grafana
ports:
- "3000:3000" # Web UI
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin # 管理员密码
volumes:
- grafana-data:/var/lib/grafana
volumes:
loki-data:
grafana-data:
Loki 配置
# loki-config.yaml — Loki 基本配置
auth_enabled: false # 单租户模式(测试用)
server:
http_listen_port: 3100 # HTTP 端口
common:
path_prefix: /loki # 数据路径前缀
storage:
filesystem:
chunks_directory: /loki/chunks # 数据块目录
rules_directory: /loki/rules # 规则目录
replication_factor: 1 # 复制因子(单节点 =1)
ring:
kvstore:
store: inmemory # 内存存储(单节点)
schema_config:
configs:
- from: 2024-01-01 # 生效日期
store: tsdb # 使用 TSDB 存储
object_store: filesystem # 对象存储:本地文件系统
schema: v13 # Schema 版本
index:
prefix: index_ # 索引前缀
period: 24h # 索引周期
limits_config:
retention_period: 720h # 日志保留 30 天
Grafana Alloy 配置
// alloy-config.alloy — 日志采集配置
// 采集本地日志文件
local.file_match "logs" {
path_targets = [{
__path__ = "/var/log/*.log", // 日志文件路径
job = "system-logs", // 标签:job
}]
}
loki.source.file "local_files" {
targets = local.file_match.logs.targets // 引用上面的文件匹配
forward_to = [loki.write.default.receiver] // 转发到 Loki
}
// 采集 Docker 容器日志
discovery.docker "containers" {
host = "unix:///var/run/docker.sock" // Docker socket
}
loki.source.docker "docker_logs" {
host = "unix:///var/run/docker.sock"
targets = discovery.docker.containers.targets
forward_to = [loki.write.default.receiver]
}
// 发送到 Loki
loki.write "default" {
endpoint {
url = "http://loki:3100/loki/api/v1/push" // Loki 地址
}
}
docker compose up -d # 启动所有服务
# 在 Grafana 中添加 Loki 数据源:
# Configuration → Data Sources → Add → Loki
# URL: http://loki:3100
基本使用
LogQL 查询
# === 日志流选择器(选择哪些日志) ===
{job="system-logs"} # 选择 job=system-logs 的日志
{container="nginx"} # 选择 nginx 容器的日志
{namespace="production", app="web"} # 多标签组合
# === 过滤表达式(筛选日志内容) ===
{job="system-logs"} |= "error" # 包含 "error" 的日志
{job="system-logs"} != "debug" # 不包含 "debug" 的日志
{job="system-logs"} |~ "ERROR|WARN" # 正则匹配 ERROR 或 WARN
{job="system-logs"} !~ "health|ping" # 正则排除 health 或 ping
# === 管道操作(处理日志) ===
{container="nginx"}
| json # 解析 JSON 格式日志
| status >= 400 # 过滤 HTTP 状态码 >= 400
| line_format "{{.method}} {{.path}} {{.status}}" # 格式化输出
{container="app"}
| logfmt # 解析 logfmt 格式
| level="error" # 过滤 error 级别
| duration > 1s # 过滤耗时 > 1秒
# === 聚合查询(统计分析) ===
# 每 5 分钟的错误日志数量
rate({container="nginx"} |= "error" [5m])
# 每个容器的日志速率
sum by (container) (rate({namespace="production"}[5m]))
# 最近 1 小时的错误总数
count_over_time({job="app"} |= "ERROR" [1h])
# P99 响应时间(需要 JSON 解析)
quantile_over_time(0.99, {container="api"} | json | unwrap duration [5m]) by (path)
在 Grafana 中查看
# 1. 打开 Grafana → Explore
# 2. 选择 Loki 数据源
# 3. 输入 LogQL 查询
# 4. 切换视图:
# - Logs → 查看原始日志
# - Table → 表格视图
# - Graph → 日志量趋势图
# 创建 Dashboard 面板:
# Dashboard → Add Panel → 选择 Loki 数据源
# 使用 rate() 创建日志速率图
# 使用 count_over_time() 创建错误统计图
CLI 查询(logcli)
# 安装 logcli
# 从 Loki releases 下载 logcli 二进制
# 查询日志
export LOKI_ADDR=http://localhost:3100 # Loki 地址
logcli query '{job="system-logs"}' # 查询日志
logcli query '{job="system-logs"}' --limit=50 # 限制 50 条
logcli query '{job="system-logs"}' --since=1h # 最近 1 小时
logcli query '{job="system-logs"}' --from="2024-01-01T00:00:00Z" --to="2024-01-02T00:00:00Z" # 时间范围
# 实时查看(类似 tail -f)
logcli query '{job="system-logs"}' --tail # 实时日志流
# 列出标签
logcli labels # 列出所有标签
logcli labels job # 列出 job 标签的所有值
高级用法
Kubernetes 日志采集
# 在 K8s 中用 Helm 部署 Loki Stack
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki-stack \
--namespace monitoring \
--create-namespace \
--set grafana.enabled=true \ # 同时安装 Grafana
--set loki.persistence.enabled=true \ # 持久化存储
--set loki.persistence.size=50Gi # 存储大小
# 自动采集所有 Pod 日志,按 namespace/pod/container 标签分类
告警规则
# loki-rules.yaml — 基于日志的告警
groups:
- name: app-alerts # 规则组名
rules:
- alert: HighErrorRate # 告警名
expr: | # LogQL 表达式
rate({container="api"} |= "ERROR" [5m]) > 10
for: 5m # 持续 5 分钟
labels:
severity: critical # 严重级别
annotations:
summary: "API 服务错误率过高"
description: "最近 5 分钟 ERROR 日志超过 10 条/秒"
对象存储后端(生产推荐)
# loki-config.yaml — 使用 S3 存储
common:
storage:
s3:
endpoint: s3.amazonaws.com # S3 端点
bucketnames: loki-logs # S3 桶名
region: ap-southeast-1 # 区域
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
# S3 存储成本极低,适合长期保存日志
常见报错
| 报错信息 | 原因 | 解决方案 |
|---|
entry out of order | 日志时间戳乱序 | 检查时钟同步或启用 unordered_writes |
max streams limit | 标签组合过多 | 减少高基数标签(如 user_id) |
context deadline exceeded | 查询超时 | 缩小时间范围或优化 LogQL |
no logs found | 没有匹配的日志 | 检查标签名和采集器配置 |
rate limit exceeded | 推送速率超限 | 调整 limits_config |
速查表
# === LogQL 速查 ===
{label="value"} # 标签选择
|= "text" # 包含文本
!= "text" # 不包含文本
|~ "regex" # 正则匹配
| json # 解析 JSON
| logfmt # 解析 logfmt
| line_format "{{.field}}" # 格式化输出
rate({...}[5m]) # 每秒日志速率
count_over_time({...}[1h]) # 时间范围内总数
sum by (label) (rate({...}[5m])) # 按标签聚合
# === 关键端口 ===
# 3100 → Loki HTTP API
# 9096 → Loki gRPC
# === API 端点 ===
# POST /loki/api/v1/push → 推送日志
# GET /loki/api/v1/query → 查询日志
# GET /loki/api/v1/query_range → 范围查询
# GET /loki/api/v1/labels → 列出标签
# GET /ready → 就绪检查
同类对比
| 特性 | Loki | Elasticsearch | Splunk | ClickHouse |
|---|
| 索引方式 | 只索引标签 | 全文索引 | 全文索引 | 列式索引 |
| 存储成本 | 极低 | 高 | 很高 | 低 |
| 查询速度 | 中等 | 快 | 快 | 快 |
| 学习曲线 | 低 | 中 | 中 | 中 |
| Grafana 集成 | 原生 | 插件 | 自带 UI | 插件 |
| 资源需求 | 低 | 高 | 很高 | 中 |
| 适合场景 | 云原生日志 | 全文搜索 | 企业级 | 大数据分析 |
选型建议:云原生环境日志收集首选 Loki(轻量、成本低、Grafana 原生集成);需要全文搜索选 Elasticsearch(ELK Stack);大规模日志分析选 ClickHouse;不差钱选 Splunk。