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: es
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false   # 本地演示禁用安全,生产请开启
      - ES_JAVA_OPTS=${ES_JAVA_OPTS}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - "9200:9200"
    volumes:
      - esdata:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
    container_name: kibana
    depends_on:
      - elasticsearch
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - XPACK_SECURITY_ENABLED=false
    ports:
      - "${KIBANA_PORT}:5601"

  logstash:
    image: docker.elastic.co/logstash/logstash:${STACK_VERSION}
    container_name: logstash
    depends_on:
      - elasticsearch
    ports:
      - "${LOGSTASH_BEATS_PORT}:5044"
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline:ro

  filebeat:
    image: docker.elastic.co/beats/filebeat:${STACK_VERSION}
    container_name: filebeat
    user: root
    depends_on:
      - logstash
    volumes:
      # 你的日志目录挂载到容器内 /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:ro
    command: ["--strict.perms=false"]

volumes:
  esdata:

五、Logstash Pipeline(解析 JSON 并写 ES)

html 复制代码
input {
  beats {
    port => 5044
    codec => "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)

html 复制代码
filebeat.inputs:
  - type: filestream
    id: app-json-logs
    enabled: true
    paths:
      - /logs/*.json.log
      - /logs/**/*.json.log
    parsers:
      - ndjson:
          # 如果你的日志每行就是 JSON(logback JSON Encoder),开启 ndjson
          overwrite_keys: true
          add_error_key: true
          # 如果你的 JSON 行里 time 字段叫 "timestamp",这里可以映射到 @timestamp
          # 但我们在 Logstash 里做了统一处理,这里可以不配
    ignore_older: 72h
    close_inactive: 5m

output.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
健康检查:
html 复制代码
# 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。

八、产生日志(两种方式)

  1. 你的应用 :确保它把 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 下生成文件并持续写入

html 复制代码
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 里看日志

  1. 打开浏览器:http://localhost:5601

  2. 左侧 Discover → 创建 Data View

    • Nameapp-logs

    • Index patternapp-logs-*

    • Timestamp field :选择 @timestamp

  3. 保存后即可看到实时入库的日志。

  4. 常用查询(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 过滤器按格式解析。

复制代码
相关推荐
侠客行03175 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪5 小时前
深入浅出LangChain4J
java·langchain·llm
老毛肚7 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎7 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
Yvonne爱编码7 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚8 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂8 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
fuquxiaoguang8 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
琹箐8 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
__WanG8 小时前
JavaTuples 库分析
java