ELK 与 Loki 日志平台
日志平台选型
| 方案 | 组件 | 存储 | 适合场景 |
|---|---|---|---|
| ELK Stack | Filebeat + Logstash + Elasticsearch + Kibana | ES 全文索引 | 业务日志分析、复杂查询、历史回溯 |
| Loki + Grafana | Promtail + Loki + Grafana | 低成本对象存储 | Kubernetes、指标与日志统一展示 |
| EFK | Filebeat/Fluentd + Elasticsearch + Kibana | ES 全文索引 | 替代 Logstash(更轻量) |
ELK Stack
架构
text
┌──────────┐
│ 应用服务 │ ← 日志生产者
└────┬─────┘
│ 输出日志文件
┌────┴─────┐
│ Filebeat │ ← 轻量日志采集(Go 编写)
└────┬─────┘
│ 发送日志
┌────┴─────┐
│ Logstash │ ← 日志处理(过滤/转换/结构化)
└────┬─────┘
│ 写入
┌────┴──────┐
│Elasticsearch│ ← 存储 + 索引
└────┬──────┘
│ 查询
┌────┴─────┐
│ Kibana │ ← 可视化
└──────────┘组件说明
| 组件 | 功能 | 资源占用 |
|---|---|---|
| Filebeat | 采集日志文件,轻量传输 | 极低(~10 MB 内存) |
| Logstash | 数据转换、过滤、结构化 | 较高(JVM,~256 MB) |
| Elasticsearch | 分布式存储、全文检索 | 较高 |
| Kibana | 数据可视化、日志分析 | 中等 |
Filebeat 配置示例
yaml
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/app/*.log
- /var/log/app/*-error.log
# 多行日志合并(如 Java 异常堆栈)
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
output.logstash:
hosts: ["192.168.1.100:5044"]Logstash 配置示例
ruby
# logstash.conf
input {
beats {
port => 5044
}
}
filter {
# 解析 JSON 日志
if [message] =~ /^{/ {
json {
source => "message"
}
}
# Grok 解析非结构化日志
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} \[%{DATA:thread}\] %{LOGLEVEL:level} %{DATA:logger} - %{GREEDYDATA:msg}" }
}
# 添加字段
mutate {
add_field => { "environment" => "%{[@metadata][env]}" }
add_tag => ["app_log"]
}
# 时间戳转换
date {
match => ["timestamp", "yyyy-MM-dd HH:mm:ss.SSS"]
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}Kibana 常用操作
创建索引模式:
text
Management → Stack Management → 索引模式
→ 创建索引模式: app-logs-*
→ 时间筛选字段: @timestamp常用查询:
text
# 搜索所有 ERROR 日志
level: ERROR
# 搜索特定用户
userId: 1001
# 搜索近 1 小时的 500 错误
status: 500 AND @timestamp >= now-1h
# Lucene 正则(包含异常堆栈)
message: /NullPointerException/
# KQL(Kibana Query Language)
level: ERROR and logger: com.example.OrderServiceLoki + Grafana
Loki 由 Grafana Labs 开发,核心设计理念:只为日志内容建立索引,元数据用 label 标记。
架构
text
┌──────────┐
│ 应用容器 │ ← 容器 stdout/stderr
└────┬─────┘
│
┌────┴─────┐
│ Promtail │ ← 日志采集(对标 Filebeat)
└────┬─────┘
│ push
┌────┴─────┐
│ Loki │ ← 日志存储(无全文索引)
└────┬─────┘
│ 查询
┌────┴─────┐
│ Grafana │ ← 统一仪表盘
└──────────┘与 ELK 的核心差异
| 特性 | ELK(Elasticsearch) | Loki |
|---|---|---|
| 索引策略 | 全文索引(对日志内容建索引) | 只对 label 建索引,内容不索引 |
| 存储成本 | 较高(索引膨胀 1-2 倍) | 极低(仅存储原始日志) |
| 查询性能 | 全文搜索快 | 日志内容搜索慢(需扫描) |
| 适用场景 | 需要全文搜索、聚合分析 | Kubernetes 容器日志、与指标统一展示 |
| 与 K8s 集成 | 一般 | 原生支持(自动发现 Pod label) |
| 运维复杂度 | 较高 | 低 |
Docker Compose 部署
yaml
version: '3'
services:
loki:
image: grafana/loki:2.9.0
ports:
- "3100:3100"
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:2.9.0
volumes:
- /var/log:/var/log
- ./promtail-config.yaml:/etc/promtail/config.yml
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=trueLoki 配置
yaml
# loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
storage_config:
filesystem:
directory: /loki/chunks
boltdb_shipper:
active_index_directory: /loki/index
cache_location: /loki/cache
compactor:
working_directory: /loki/compactor
limits_config:
max_query_series: 10000Promtail 配置
yaml
# promtail-config.yaml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets: [localhost]
labels:
job: varlogs
host: my-server
__path__: /var/log/*.log
- job_name: docker
docker_sd_configs:
- host: "unix:///var/run/docker.sock"
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'Grafana 查询
在 Grafana 数据源添加 Loki 后,使用 LogQL 查询:
logql
# 查询所有日志
{job="varlogs"}
# 按容器名和级别过滤
{container="order-service"} |= "ERROR"
# 正则匹配
{app="api-gateway"} |~ "TimeoutException|ConnectException"
# 统计每分钟错误数(与指标统一展示)
rate({container="api-gateway"} |= "ERROR"[5m])
# JSON 解析
{app="user-service"} | json | user_id="1001"日志平台选型建议
text
传统 Java 应用(非容器化)→ ELK Stack
- 需要全文搜索、复杂聚合查询
- 业务日志分析需求明确
Kubernetes 云原生环境 → Loki + Grafana
- 日志与 Prometheus 指标统一展示
- 低成本存储,自动发现 Pod
已有 ES 基础设施 → EFK(Fluentd 替代 Logstash)
- 更轻量,配置更简洁