ELK 日志分析平台搭建:Elasticsearch + Logstash + Kibana 实战
ELK Stack(Elasticsearch + Logstash + Kibana)是企业日志分析的黄金标准:Elasticsearch 负责存储与全文检索,Logstash 负责过滤、转换和结构化日志,Kibana 负责搜索、可视化和看板,再加上轻量的 Filebeat 做采集端,就组成了一条从"日志产生"到"可视化分析"的完整链路。
什么时候需要 ELK
如果你的日志目前靠 grep 和 tail 就能应付,那暂时不需要 ELK。当出现下面任一情况时,值得引入:多个应用或机器上的日志需要集中搜索;需要按错误类型、耗时、来源做聚合统计;业务侧(运维、客服、研发)要自助查日志,而不是每次都找后端要;要基于日志做告警(比如错误日志激增)。
反之,单机、日志量小、"只要看得到就行"的场景,用 服务器日志监控 或 Loki 这类轻方案更划算。ELK 的代价主要在资源:一套最小集群至少需要 4-8GB 内存,日志量上来后 ES 节点还需要独立规划磁盘 IO。
一、架构设计
日志源 → Filebeat → Logstash → Elasticsearch → Kibana
| | | | |
应用日志 轻量采集 过滤/转换 存储/索引 可视化
二、Docker Compose 部署
version: '3'
services:
elasticsearch:
image: elasticsearch:8.12.0
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
logstash:
image: logstash:8.12.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch
kibana:
image: kibana:8.12.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch
volumes:
es-data:
资源与初始化注意事项
- 单节点测试环境给 ES 分配 1-2GB 堆内存(
ES_JAVA_OPTS),不要超过物理内存一半; - Linux 下需要调高
vm.max_map_count,否则 ES 启动会报max virtual memory areas vm.max_map_count [65530] is too low,执行sysctl -w vm.max_map_count=262144; - 首次启动后 ES 会生成安全证书,Kibana 默认连接
http://elasticsearch:9200,若开启安全认证需要在环境变量里配置账号密码。
三、Logstash 配置
input {
beats {
port => 5044
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
}
四、Filebeat 配置
filebeat.inputs:
- type: log
paths:
- /var/log/nginx/access.log
fields:
app: nginx
env: production
output.logstash:
hosts: ["logstash:5044"]
验证与排错
配置完成后按下面顺序验证整条链路:
- 检查 Filebeat 是否在读取文件:
filebeat test output,确认能连上 Logstash 的 5044 端口; - 查看 Logstash 日志确认没有 grok 解析报错:
docker logs logstash; - 确认索引已生成:
curl http://localhost:9200/_cat/indices?v,应能看到logs-2026.xx.xx之类的索引; - 在 Kibana 里创建 Index Pattern(如
logs-*),到 Discover 里搜一条已知的访问日志验证字段解析是否正确。
常见坑:grok 模式不匹配导致日志进不了 ES(会看到 _grokparsefailure 标签);时间字段没解析对,导致日志按接收时间而非日志时间排序。先在 Logstash 里用一行真实日志调好 grok,再批量接入。
五、关键功能
| 功能 | 说明 |
|---|---|
| 全文搜索 | 快速定位日志 |
| 聚合分析 | 统计错误率、响应时间 |
| 可视化 | 仪表盘展示趋势 |
| 告警 | 基于查询的告警规则 |
| 权限 | RBAC 多租户 |
一个真实排错案例
某业务线每天接入约 5GB 访问日志,某天凌晨告警系统发现 502 从平时的 0.2% 冲到 8%。值班人员在 Kibana Discover 里用 status:502 锁定 30 分钟窗口,再用 terms 按 upstream_addr 分组,发现 90% 的 502 都集中在同一台后端 IP。进一步看该节点的响应时间曲线,确认是数据库连接池耗尽导致。整个定位过程不到 10 分钟——如果还靠 grep 逐台机器翻日志,光找文件就得花掉半小时。这类"从现象到根因"的检索路径,正是 ELK 相比普通日志文件最大的价值。更进阶的告警与可视化组合见 Prometheus + Grafana 基础监控。
Kibana 使用要点
Kibana 最常用的三个能力是 Discover(全文检索)、Visualize(图表)和 Dashboard(看板)。一个典型场景:凌晨发现 502 变多,在 Discover 里搜 status:502 配合时间范围缩小窗口,再用 terms 聚合按 upstream 分组,就能定位到是哪台后端在出错。更复杂的查询可以切到 KQL,例如 response_time > 3000 and status >= 500。
最佳实践
- 索引按天分片(
logs-%{+YYYY.MM.dd}),配合 ILM(索引生命周期管理)自动淘汰过期索引,避免磁盘被日志占满; - 日志量大时优先考虑 Filebeat → Kafka → Logstash 的缓冲架构,防止日志洪峰压垮 Logstash;
- 敏感字段(手机号、身份证号)在 Logstash 里做脱敏或剔除后再入 ES;
- 保留期按需求定:审计类日志通常留 180 天,普通访问日志 30 天足够。
常见问题
ES 内存到底怎么给? 官方建议堆内存不超过物理内存一半,且不超过 30-31GB(超过后压缩指针失效、收益下降)。日志型负载大堆不如多分片。
Logstash 吃内存严重怎么办? 先确认 pipeline 里有没有 java 或 ruby 过滤器(这两类最耗内存),并适当调大 pipeline.batch.size 换取吞吐。
单节点够用吗? 单节点适合日志量在每日几 GB 以内的场景;超出后建议拆成三节点 ES,并把 Kibana 与 Logstash 独立部署。
和 Loki 怎么选? Loki 以廉价存储换取查询能力,适合"只要搜得到"的场景;ELK 适合需要聚合分析、复杂查询和图表多样的场景。参见 Loki 日志聚合 对比。
日志里有中文乱码怎么办? 检查两处:一是 Filebeat 的 filebeat.inputs 是否声明 encoding: utf-8,二是 Logstash 输出到 ES 前字段编码是否被转换。多数情况是采集端读文件时用了错误的默认编码。
参考:Elastic 官方文档 — https://www.elastic.co/guide/index.html ;Filebeat 参考 — https://www.elastic.co/guide/en/beats/filebeat/current/index.html