【实战】使用 ELK 搭建 Spring Boot Docker 容器日志监控系统

@【TOC】

使用 ELK 搭建 Spring Boot Docker 容器日志监控系统

ELK (Elasticsearch + Logstash + Kibana) 是一套完整的日志收集、存储和可视化解决方案。下面详细介绍如何在 Docker 环境中为 Spring Boot 应用搭建 ELK 日志系统。

一、系统架构

复制代码
Spring Boot App (Docker) → Logstash → Elasticsearch → Kibana (可视化)

二、详细搭建步骤

1. 准备 Spring Boot 应用

1.1 修改日志输出格式

application.propertiesapplication.yml 中配置 JSON 格式日志输出:

properties 复制代码
# 使用 JSON 格式输出日志,便于 Logstash 解析
logging.pattern.console={"@timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}","level":"%level","service":"${spring.application.name}","pid":"%pid","thread":"%thread","class":"%logger{40}","message":"%message","stack_trace":"%exception{10}"}%n
1.2 创建 Dockerfile
dockerfile 复制代码
FROM openjdk:17-jdk-slim
VOLUME /tmp
COPY target/your-app.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

2. 配置 ELK 环境

2.1 创建 docker-compose.yml
yaml 复制代码
version: '3.8'

services:


  # Elasticsearch 服务 netstat -tulnp | grep -E ':(9200|5002|5601)\s'
  elasticsearch:
    restart: always
    container_name: elasticsearch
    image: docker.elastic.co/elasticsearch/elasticsearch:8.7.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
    ports:
      - "9200:9200"
    volumes:
      - ./elasticsearch/data:/usr/share/elasticsearch/data
    deploy:
      resources:
        limits:
          cpus: '1'  # 限制最多使用 1 个 CPU 核心
          memory: 10G  # 限制内存为 10G

  # Logstash 服务
  logstash:
    restart: always
    container_name: logstash
    image: docker.elastic.co/logstash/logstash:8.7.0
    volumes:
      - ./logstash-config:/usr/share/logstash/pipeline/
    ports:
      - "5002:5000"
    environment:
      - LS_JAVA_OPTS=-Xms512m -Xmx512m
    depends_on:
      - elasticsearch
    deploy:
      resources:
        limits:
          cpus: '0.5'  # 限制最多使用 0.5 个 CPU 核心
          memory: 4G  # 限制内存为 4G

  # Kibana 服务
  kibana:
    restart: always
    container_name: kibana
    image: docker.elastic.co/kibana/kibana:8.7.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
    deploy:
      resources:
        limits:
          cpus: '0.5'  # 限制最多使用 0.5 个 CPU 核心
          memory: 4G  # 限制内存为 4G

networks:
  default:
    external:
      name:  networkname # 需要自己新建一个 network
2.2 创建 Logstash 配置文件

在项目根目录创建 logstash-config 文件夹,然后创建 logstash.conf

conf 复制代码
input {
  tcp {
    port => 5000
    codec => json_lines
  }
}

filter {
  # 如果日志中有堆栈跟踪信息,进行特殊处理
  if [stack_trace] {
    mutate {
      gsub => [
        "stack_trace", "\n", "\\n",
        "stack_trace", "\t", "\\t"
      ]
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "spring-logs-%{+YYYY.MM.dd}"
  }
  
  # 可选:同时输出到控制台便于调试
  stdout {
    codec => rubydebug
  }
}
2.3 修改 Spring Boot 日志输出到 Logstash

logback-spring.xml 中添加 Logstash 输出:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    
    <springProperty scope="context" name="appName" source="spring.application.name"/>
    
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>logstash:5000</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="LOGSTASH"/>
    </root>
</configuration>

3. 构建并启动服务

3.1 构建 Spring Boot 应用镜像
bash 复制代码
mvn clean package
docker-compose build app
3.2 启动所有服务
bash 复制代码
docker-compose up -d

4. 配置 Kibana

  1. 访问 Kibana: http://localhost:5601
  2. 首次访问可能需要配置默认索引模式:
    • 进入 "Management" → "Stack Management"
    • 选择 "Index Patterns" → "Create index pattern"
    • 输入 spring-logs-* 作为模式
    • 选择 @timestamp 作为时间字段
    • 点击 "Create index pattern"

5. 查看日志

  1. 进入 Kibana 的 "Discover" 页面
  2. 选择 spring-logs-* 索引模式
  3. 可以看到所有收集到的 Spring Boot 日志

三、高级配置

1. 日志数据保留策略

在 Elasticsearch 中配置 ILM (Index Lifecycle Management) 自动管理日志索引:

conf 复制代码
# 修改 logstash.conf 的 output 部分
output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "spring-logs-%{+YYYY.MM.dd}"
    ilm_enabled => true
    ilm_policy => "spring-logs-policy"
  }
}

然后在 Kibana 中创建 ILM 策略:

  1. 进入 "Management" → "Stack Management" → "Index Lifecycle Policies"
  2. 创建名为 spring-logs-policy 的策略
  3. 设置热阶段 7 天,删除阶段 30 天

2. 添加日志字段过滤

在 Logstash 配置中添加更多过滤规则:

conf 复制代码
filter {
  # 解析 JSON 消息
  if [message] {
    json {
      source => "message"
      target => "message_json"
    }
  }
  
  # 添加 Docker 容器信息
  mutate {
    add_field => {
      "[docker][container_id]" => "%{host}"
      "[docker][container_name]" => "%{container_name}"
    }
  }
}

3. 安全配置

为 ELK 添加基础认证:

  1. 修改 docker-compose.yml 中 Elasticsearch 的环境变量:
yaml 复制代码
environment:
  - discovery.type=single-node
  - xpack.security.enabled=true
  - ELASTIC_PASSWORD=yourpassword
  1. 更新 Logstash 配置:
conf 复制代码
output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    user => "elastic"
    password => "yourpassword"
    index => "spring-logs-%{+YYYY.MM.dd}"
  }
}

四、故障排查

  1. Logstash 无法连接 Elasticsearch:

    • 检查网络是否联通: docker-compose exec logstash curl elasticsearch:9200
    • 查看 Logstash 日志: docker-compose logs logstash
  2. Kibana 无法显示数据:

    • 检查索引是否存在: curl http://localhost:9200/_cat/indices?v
    • 确认数据正在流入: curl http://localhost:9200/spring-logs-*/_count
  3. 日志量过大导致性能问题:

    • 增加 Elasticsearch 堆内存
    • 调整 Logstash 的批量写入参数
    • 考虑使用 Filebeat 替代 Logstash 的直接 TCP 输入

五、生产环境建议

  1. 使用 Filebeat 替代直接 TCP 输入:

    • Filebeat 更轻量级,资源消耗更少
    • 支持断点续传,更可靠
  2. 多节点 Elasticsearch 集群:

    • 至少 3 个节点保证高可用
    • 配置专用主节点和数据节点
  3. 监控 ELK 自身健康状态:

    • 使用 Elasticsearch 的监控功能
    • 设置告警规则

通过以上步骤,您已经成功搭建了一个完整的 ELK 日志监控系统,可以实时查看和分析 Spring Boot 应用的日志数据。