Linux 服务日志聚合与可观测性进阶:ELK + Loki + OpenTelemetry 实战
一、可观测性三大支柱与架构演进
三大支柱:
- Logs(日志):事件记录(ELK / Loki)
- Metrics(指标):量化数据(Prometheus,已在第六篇详述)
- Traces(链路追踪):请求全链路(OpenTelemetry + Jaeger/Tempo)
演进路线:
- 现代:Loki(日志) + Prometheus(指标) + Tempo(追踪) + Grafana 统一视图
- 云原生:OpenTelemetry 统一采集 + 后端可插拔
与 Systemd 集成:通过 journald → Filebeat / Promtail 实现无缝采集。
二、ELK Stack 生产级部署实战
1. 架构规划
- Elasticsearch:数据存储与检索(建议 3 节点集群)
- Logstash / Filebeat:日志采集与处理
2. Elasticsearch 核心配置(elasticsearch.yml)
cluster.name:prod-logs
node.name:es-01
network.host:0.0.0.0
http.port:9200
discovery.seed_hosts:["es-01","es-02","es-03"]
cluster.initial_master_nodes:["es-01"]
# 生产资源建议
indices.memory.index_buffer_size:30%
thread_pool.write.size:8
xpack.security.enabled:true
3. Filebeat 采集 Systemd 日志(filebeat.yml)
filebeat.inputs:
-type:journald
id:systemd-journal
enabled:true
tags:["systemd"]
-type:log
paths:
-/var/log/nginx/*.log
-/var/log/mysql/*.log
fields:
service:nginx
output.elasticsearch:
hosts:["http://es-01:9200"]
username:elastic
password:StrongPass123!
setup.kibana:
host:"http://kibana:5601"
4. Logstash Pipeline 示例
input {
beats { port => 5044 }
}
filter {
grok { match => { "message" => "%{COMBINEDAPACHELOG}" } }
date { match => [ "timestamp", "ISO8601" ] }
mutate { add_field => { "env" => "production" } }
}
output {
elasticsearch {
hosts => ["http://es:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
}
5. Kibana 仪表盘
- 推荐仪表盘:Nginx Access Log、Error Rate、Service Health
生产部署建议:
- 使用 Helm 在 Kubernetes 中部署,或 Ansible 批量部署
- ILM(Index Lifecycle Management):热-温-冷-删除策略(热 7 天、温 30 天、冷归档)
三、Grafana Loki 轻量日志方案(推荐中小规模)
Loki 是 Grafana 推出的日志聚合系统,采用“标签索引 + 对象存储”架构,资源消耗远低于 ELK。
1. Loki 配置(loki.yaml)
auth_enabled:false
server:
http_listen_port:3100
common:
ring:
kvstore:
store:inmemory
storage:
filesystem:
directory:/data/loki
schema_config:
configs:
-from:"2024-01-01"
store:boltdb-shipper
object_store:filesystem
schema:v12
index:
prefix:index_
period:24h
2. Promtail(采集端)配置
clients:
-url:http://loki:3100/loki/api/v1/push
scrape_configs:
-job_name:systemd
journal:
max_age:12h
labels:
job:systemd
relabel_configs:
-source_labels:['__journal_systemd_unit']
target_label:unit
-job_name:nginx
static_configs:
-targets:['localhost']
labels:
job:nginx
__path__:/var/log/nginx/access.log
优势对比 ELK:
四、OpenTelemetry 全链路追踪实战
OpenTelemetry(OTel)是 CNCF 标准,提供统一 API 采集日志、指标、追踪。
1. 应用侧接入(以 Java 为例)
# application.properties
opentelemetry.exporter.otlp.endpoint=http://otel-collector:4317
opentelemetry.service.name=order-service
2. OpenTelemetry Collector 配置
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
attributes:
actions:
-key:env
value:production
action:insert
exporters:
otlp:
endpoint:tempo:4317
elasticsearch:
endpoints:["http://es:9200"]
service:
pipelines:
traces:
receivers:[otlp]
processors:[batch]
exporters:[otlp]
logs:
receivers:[otlp]
exporters:[elasticsearch]
3. 后端存储
- Traces:Grafana Tempo(推荐)或 Jaeger
- 与 Loki 结合实现 Trace ID 关联日志
五、生产环境可观测性最佳实践
- 主机:Filebeat / Promtail + node_exporter
- 容器:Promtail sidecar 或 OTel Operator
- JSON 格式 + 统一字段(trace_id、span_id、service.name、level、env)
- Grafana Alerting 同时监控 Metrics + Logs
- 使用 Explore 模式关联 Trace → Log → Metric
- 敏感字段脱敏(Logstash / OTel Processor)
六、迁移与集成实战
从 journald 到 Loki/ELK:
# Promtail 采集 journald
journald_labels:
- _SYSTEMD_UNIT
与 Systemd 服务集成: 在服务单元文件中强制:
[Service]
StandardOutput=journal
StandardError=journal
容器化采集:
- Podman:使用
podman logs 驱动或 Promtail - Kubernetes:DaemonSet 部署 Promtail / OTel Agent
七、常见可观测性故障排查案例
案例1:日志量暴增导致存储爆满 解决:增加 RateLimit、采样、优化 LogQL 查询、清理老索引。
案例2:Trace ID 关联失败 解决:确保所有服务统一传播 Baggage 和 Context。
案例3:Loki 查询慢 优化:增加查询前端缓存、合理标签基数、预聚合。
案例4:ELK 集群脑裂 解决:配置 discovery.zen.minimum_master_nodes、专用 master 节点。
案例5:OpenTelemetry 采集性能开销大 解决:异步批量导出、调整采样率、使用轻量 Exporter。