ELK(Elasticsearch + Logstash + Kibana + Filebeat)采集方案
一、准备条件
已安装:Docker ≥ 20.x、Docker Compose 插件(
docker compose命令)本机一个日志目录(示例:
/abs/path/to/logs)。里边有你的 Logback JSON 文件,如:logback-demo.json.log(行级 JSON,包含message/level/timestamp/traceId/...字段)
如果你用的是我上一条给的 Spring Boot + Logback 配置,只要确定它的 JSON 日志落在这个目录即可。
二、目录结构(复制即可)
在任意空文件夹(例如 elk-stack/)里创建如下结构与文件:
elk-stack/
├─ docker-compose.yml
├─ .env
├─ logstash/
│ └─ pipeline/
│ └─ logstash.conf
└─ filebeat/
└─ filebeat.yml
三、.env(版本与路径)
把
HOST_LOG_DIR改成你 日志目录的绝对路径(很重要)
# Elasticsearch / Kibana / Logstash 统一版本 STACK_VERSION=8.12.2# ES 堆大小(本机内存够可以调大) ES_JAVA_OPTS=-Xms1g -Xmx1g# Kibana 映射的端口 KIBANA_PORT=5601# Logstash 映射的端口(Beats 输入) LOGSTASH_BEATS_PORT=5044# 你的日志目录(绝对路径) HOST_LOG_DIR=/abs/path/to/logs
四、docker-compose.yml(核心编排,一键启动)
version: "3.9"services:elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}container_name: esenvironment:- discovery.type=single-node- xpack.security.enabled=false # 本地演示禁用安全,生产请开启- ES_JAVA_OPTS=${ES_JAVA_OPTS}ulimits:memlock:soft: -1hard: -1ports:- "9200:9200"volumes:- esdata:/usr/share/elasticsearch/datakibana:image: docker.elastic.co/kibana/kibana:${STACK_VERSION}container_name: kibanadepends_on:- elasticsearchenvironment:- ELASTICSEARCH_HOSTS=http://elasticsearch:9200- XPACK_SECURITY_ENABLED=falseports:- "${KIBANA_PORT}:5601"logstash:image: docker.elastic.co/logstash/logstash:${STACK_VERSION}container_name: logstashdepends_on:- elasticsearchports:- "${LOGSTASH_BEATS_PORT}:5044"volumes:- ./logstash/pipeline:/usr/share/logstash/pipeline:rofilebeat:image: docker.elastic.co/beats/filebeat:${STACK_VERSION}container_name: filebeatuser: rootdepends_on:- logstashvolumes:# 你的日志目录挂载到容器内 /logs- ${HOST_LOG_DIR}:/logs:ro# Filebeat 配置- ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro# 容器读取宿主机文件需要访问 docker 的 meta(可选)- /var/lib/docker/containers:/var/lib/docker/containers:ro- /var/run/docker.sock:/var/run/docker.sock:rocommand: ["--strict.perms=false"]volumes:esdata:五、Logstash Pipeline(解析 JSON 并写 ES)
input {beats {port => 5044codec => "json" # Filebeat 已经传 JSON,这里再保险}
}filter {# 如果你的 JSON 在 message 字段里而不是最外层,请用 json 过滤器解开:# json { source => "message" }# 规范化时间戳(如果有 @timestamp 就跳过)if !("@timestamp" in [@metadata]) and [timestamp] {date {match => ["timestamp", "ISO8601", "yyyy-MM-dd HH:mm:ss,SSS", "UNIX_MS"]target => "@timestamp"remove_field => ["timestamp"]}}# 统一字段名与类型(可按你的日志做适配)mutate {rename => { "level" => "log.level" }rename => { "logger" => "log.logger" }rename => { "thread" => "process.thread.name" }# 保留示例字段:traceId/spanId/app/env/message}# 简单去除无用字段示例mutate {remove_field => ["host", "agent", "ecs", "log.flags"]}
}output {elasticsearch {hosts => ["http://elasticsearch:9200"]index => "app-logs-%{+YYYY.MM.dd}"# 模板/ILM 可后续加,这里先简单跑通}# 便于调试stdout { codec => rubydebug }
}
六、Filebeat(采集你的 JSON 文件并输送到 Logstash)
filebeat.inputs:- type: filestreamid: app-json-logsenabled: truepaths:- /logs/*.json.log- /logs/**/*.json.logparsers:- ndjson:# 如果你的日志每行就是 JSON(logback JSON Encoder),开启 ndjsonoverwrite_keys: trueadd_error_key: true# 如果你的 JSON 行里 time 字段叫 "timestamp",这里可以映射到 @timestamp# 但我们在 Logstash 里做了统一处理,这里可以不配ignore_older: 72hclose_inactive: 5moutput.logstash:hosts: ["logstash:5044"]# 关闭 elastic-agent 管理
features:# 禁用云、k8s自动发现等高级特性(本地演示用)monitoring.enabled: false说明
如果你的日志不是每行一个 JSON(比如普通文本),也能采,不过建议把 Logback 输出改为 JSON,更利于结构化检索。
如果你已有 Filebeat 生产配置,可直接把
output指到本 Logstash。
七、启动(一步到位)
cd elk-stack docker compose pull docker compose up -d 健康检查:
# ES
curl http://localhost:9200
# Kibana(浏览器打开)
# http://localhost:5601确认 Filebeat、Logstash 日志:
docker logs -f filebeat docker logs -f logstash 看到 Filebeat 发现文件、Logstash 输出“elasticsearch output succeeded”之类即 OK。
八、产生日志(两种方式)
你的应用:确保它把 JSON 日志写到
.env里的HOST_LOG_DIR目录。
例如 Spring Boot 示例,执行后访问接口触发日志:
curl "http://localhost:8080/api/hello?name=Alice" curl "http://localhost:8080/api/hello?name=oops"2.快速模拟器(可选):临时生成一些 JSON 行用来验证采集。
# 在 HOST_LOG_DIR 下生成文件并持续写入
mkdir -p /abs/path/to/logs
bash -c 'while true; do \echo "{\"level\":\"INFO\",\"logger\":\"demo.producer\",\"thread\":\"main\",\"message\":\"hello\",\"app\":\"demo\",\"traceId\":\""$(uuidgen | tr -d - | cut -c1-16)"\",\"env\":\"dev\",\"timestamp\":\""$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")"\"}"; \sleep 1; \
done >> /abs/path/to/logs/demo.json.log'九、在 Kibana 里看日志
打开浏览器:
http://localhost:5601左侧 Discover → 创建 Data View:
Name:
app-logsIndex pattern:
app-logs-*Timestamp field:选择
@timestamp
保存后即可看到实时入库的日志。
常用查询(KQL)示例:
log.level: "ERROR"app: "logback-demo"traceId: "abcd1234*"
十、常见问题排查
Kibana 看不到索引:确认 Logstash 是否在往
app-logs-*写入(看容器日志 / curl 索引)curl "http://localhost:9200/_cat/indices?v"Filebeat 无法读取:确认本机日志目录是绝对路径并已挂载到容器
/logs,文件权限可读。时间乱序:确保你的 JSON 带有正确的 UTC 时间,或让 Logstash
date过滤器按格式解析。
