ELKF

ELKF 日志系统:Filebeat+ELK 的轻量日志采集方案详解

ELKF(Elasticsearch + Logstash + Kibana + Filebeat)是在传统 ELK 基础上引入 Filebeat 的增强方案。由于 Logstash(基于 JVM)资源消耗较高,不适合在海量应用节点上直接部署,而 Filebeat(轻量级 Go 语言工具)能以极低的 CPU / 内存占用实现日志采集,形成 “应用日志→Filebeat 采集→Logstash 处理→Elasticsearch 存储→Kibana 可视化” 的完整链路,成为分布式系统日志管理的主流架构。

ELKF 核心架构与组件分工

ELKF 的核心价值在于解耦日志采集与处理,通过 Filebeat 实现 “轻量采集”,Logstash 实现 “复杂处理”,两者协同解决传统 ELK 在大规模部署时的资源占用问题。

架构链路图

[应用服务器]                [中间件服务器]                [存储与可视化服务器]
  应用日志 → Filebeat采集 → Logstash过滤清洗 → Elasticsearch存储 → Kibana可视化

组件分工对比

组件 角色定位 核心优势 部署位置
Filebeat 日志采集器 轻量(<10MB 内存)、高可靠(断点续传) 应用服务器节点
Logstash 日志处理管道 支持 200 + 插件、复杂过滤(解析 / 脱敏 / 转换) 独立中间件集群
Elasticsearch 日志存储与检索引擎 分布式、实时索引、全文搜索 存储集群(3 + 节点)
Kibana 日志可视化平台 检索界面、仪表盘、告警配置 前端服务节点

Filebeat 核心配置与实战

Filebeat 是 ELKF 的 “入口”,负责从应用服务器采集日志并发送到 Logstash(或直接到 Elasticsearch)。其核心配置文件为filebeat.yml,需重点关注日志输入源(Inputs)输出目的地(Outputs)

1. 基础配置:采集文件日志并发送到 Logstash

# ============================== Filebeat Inputs ===============================
filebeat.inputs:
- type: log  # 输入类型:文件日志(其他类型:stdin、tcp、udp等)
  enabled: true  # 启用该输入配置
  paths:  # 日志文件路径(支持通配符,可配置多个)
    - /var/log/nginx/access.log  # Nginx访问日志
    - /opt/app/logs/*.log       # 自定义应用日志(如Java应用日志)
    - /home/user/app/*.log      # 其他路径日志
  exclude_lines: ['^#']  # 排除以#开头的注释行(可选)
  include_lines: ['ERROR', 'WARN']  # 仅采集包含ERROR/WARN的日志(可选,缩小范围)
  ignore_older: 72h  # 忽略72小时未修改的旧日志(避免采集历史冗余日志)
  scan_frequency: 10s  # 扫描日志文件变化的频率(默认10秒,可根据日志生成频率调整)
  harvester_buffer_size: 16384  # 读取日志的缓冲区大小(默认16KB,大日志可增大)
  
  # 自定义字段:用于区分不同应用/环境的日志(后续Logstash/Kibana可基于该字段筛选)
  fields:
    app: user-service  # 应用名称
    env: prod          # 环境(生产/测试)
  fields_under_root: false  # 自定义字段是否放在顶层(false表示放在fields子对象下)

  # 处理多行日志(如Java堆栈信息、异常日志)
  multiline:
    pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'  # 匹配日志开头的日期格式(如2024-08-23)
    negate: true  # 不匹配pattern的行(即非日期开头的行)
    what: previous  # 合并到上一行(解决堆栈日志被拆分为多行的问题)
    max_lines: 1000  # 单个多行日志的最大行数(避免内存溢出)
    timeout: 5s      # 多行日志合并超时时间

# ============================== Filebeat Outputs ==============================
output.logstash:
  hosts: ['192.168.1.100:5044']  # Logstash地址(格式:IP:端口,多节点用逗号分隔)
  worker: 2  # 发送日志的并发worker数量(建议等于CPU核心数的1/2)
  bulk_max_size: 2048  # 批量发送的最大日志条数(默认2048,大日志可减小)
  compression_level: 3  # 压缩级别(0-9,3为平衡性能与压缩率)

# ============================== Filebeat Logging ==============================
logging.level: info  # Filebeat自身日志级别(info/debug/warn,生产环境用info)
logging.to_files: true  # 输出到文件
logging.files:
  path: /var/log/filebeat/  # Filebeat日志路径
  name: filebeat.log
  rotateeverybytes: 10485760  # 日志滚动阈值(10MB)
  keepfiles: 7  # 保留7个滚动日志文件

2. 关键配置解析

(1)Inputs 核心参数
  • paths:日志路径是核心,支持通配符(匹配任意字符,*递归匹配子目录)。例如:
    • /opt/app/logs/**/*.log:采集logs目录及其所有子目录下的.log文件;
    • /var/log/nginx/access.log*:采集access.log及滚动文件(如access.log.1)。
  • multiline:解决 “多行日志拆分” 问题(如 Java 异常堆栈、JSON 日志跨行吗)。核心是通过pattern定义 “日志起始行规则”,将非起始行合并到上一行。
  • ignore_older:避免 Filebeat 启动时采集历史久远的日志(如服务器重启后,不采集 3 天前的旧日志),减少初始数据量。
(2)Outputs 核心参数
  • hosts:Logstash 的 “Beats 输入” 端口(默认 5044,需在 Logstash 中启用beats输入插件);
  • bulk_max_size:批量发送大小直接影响性能 —— 过小会增加网络请求次数,过大可能导致 Logstash 处理超时,需根据日志大小调整(如单条日志 1KB,2048 条约 2MB,适合大多数场景)。

3. Filebeat 启动与验证

# 1. 检查配置文件语法(避免配置错误)
filebeat test config -c /etc/filebeat/filebeat.yml

# 2. 测试输出连接(验证能否连接到Logstash)
filebeat test output -c /etc/filebeat/filebeat.yml

# 3. 启动Filebeat(后台运行,生产环境建议用systemd管理)
# 方式1:直接后台运行
filebeat -e -c /etc/filebeat/filebeat.yml &

# 方式2:systemd启动(推荐,支持开机自启)
systemctl enable filebeat  # 开机自启
systemctl start filebeat   # 启动
systemctl status filebeat  # 查看状态

# 4. 验证日志采集(查看Filebeat日志,确认无报错)
tail -f /var/log/filebeat/filebeat.log

Logstash 配置:接收 Filebeat 数据并处理

Logstash 需配置 “Beats 输入” 接收 Filebeat 发送的日志,再通过 Filter 进行清洗,最终输出到 Elasticsearch。以下是 ELKF 场景的典型配置(logstash-filebeat.conf):

# ============================== Input ===============================
input {
  # 启用Beats输入,监听5044端口(与Filebeat的output.logstash.hosts对应)
  beats {
    port => 5044
    codec => json  # Filebeat默认以JSON格式发送数据,此处需匹配
  }
}

# ============================== Filter ===============================
filter {
  # 1. 解析Filebeat的自定义字段(如app、env)
  if [fields][app] == "user-service" {  # 仅处理user-service的日志
    # 2. 解析非结构化日志(以Java应用日志为例,格式:[2024-08-23 10:30:00] [ERROR] [traceId:123] 报错信息)
    grok {
      match => { 
        "message" => "\[%{TIMESTAMP_ISO8601:log_time}\] \[%{LOGLEVEL:log_level}\] \[traceId:%{DATA:trace_id}\] %{GREEDYDATA:log_content}" 
      }
      remove_field => ["message"]  # 解析后删除原始message字段,减少存储
      add_field => { "service" => "%{[fields][app]}" }  # 提取fields.app到顶层字段service
    }

    # 3. 转换时间字段(将log_time转为Elasticsearch的@timestamp,用于时间筛选)
    date {
      match => ["log_time", "yyyy-MM-dd HH:mm:ss"]
      target => "@timestamp"
      remove_field => ["log_time"]  # 转换后删除原log_time
    }

    # 4. 日志脱敏(如隐藏手机号)
    mutate {
      gsub => [
        "log_content", "1[3-9]\d{9}", "****"  # 将手机号替换为****
      ]
    }
  }

  # 其他应用的日志处理(可新增if分支)
  if [fields][app] == "order-service" {
    # ... 类似解析逻辑
  }
}

# ============================== Output ===============================
output {
  # 输出到Elasticsearch,按应用+日期创建索引(便于管理)
  elasticsearch {
    hosts => ["192.168.1.101:9200", "192.168.1.102:9200"]  # Elasticsearch集群地址
    index => "%{[fields][app]}-log-%{+YYYY.MM.dd}"  # 索引名:应用名-日志-日期(如user-service-log-2024.08.23)
    user => "elastic"  # Elasticsearch用户名(若启用安全认证)
    password => "Elastic@123"
  }

  # 调试用:输出到控制台(生产环境可注释)
  stdout { codec => rubydebug }
}

ELKF 与传统 ELK 的核心差异

对比维度 传统 ELK(无 Filebeat) ELKF(Filebeat+ELK)
采集层资源占用 高(Logstash 需 JVM,内存 > 512MB) 极低(Filebeat<10MB 内存,CPU<5%)
部署规模 适合小规模节点(<50 个应用节点) 支持大规模集群(上千个应用节点)
采集可靠性 无断点续传(Logstash 重启后重采全量) 支持断点续传(记录文件读取位置)
日志类型支持 依赖 Logstash 插件 原生支持文件、TCP、UDP、容器日志等
复杂度 低(单组件采集 + 处理) 中(多组件协同,但配置模板化)

ELKF 最佳实践

1. Filebeat 部署建议

  • 每节点部署一个 Filebeat:直接在应用服务器上安装,避免跨节点采集导致的网络延迟;
  • 使用 systemd 管理进程:确保 Filebeat 异常退出后自动重启,提高可靠性;
  • 分环境配置:开发 / 测试 / 生产环境使用不同的filebeat.yml,通过fields.env区分日志来源。

2. Logstash 性能优化

  • 控制 worker 数量:通过pipeline.workers: 4(建议等于 CPU 核心数)调整并发处理线程;
  • 批量处理pipeline.batch.size: 1000(批量处理日志条数,平衡吞吐量与延迟);
  • 过滤无用日志:在 Filebeat 层通过include_lines/exclude_lines过滤,减少 Logstash 处理压力。

3. Elasticsearch 索引管理

  • 按应用 + 日期拆分索引:如user-service-log-2024.08.23,便于按应用筛选和生命周期管理;
  • 启用 ILM(索引生命周期):设置 “热→温→冷→删除” 策略(如热数据保留 7 天,冷数据保留 30 天,30 天后自动删除);
  • 合理设置分片:每个索引分片数 = 节点数(如 3 节点集群,分片数 = 3),每个分片大小不超过 50GB。

4. 日志链路追踪

  • 在 Filebeat 自定义字段中添加trace_id(若应用支持分布式追踪),或通过 Logstash 解析日志中的traceId字段;
  • 在 Kibana 中通过trace_id筛选,实现 “单请求全链路日志” 查询,快速定位分布式问题。

常见问题与解决方案

1. Filebeat 采集不到日志

  • 检查路径权限:Filebeat 运行用户(如 root)是否有日志文件的读权限(chmod 644 /opt/app/logs/*.log);
  • 查看 ignore_older 配置:若日志超过ignore_older时间(如 72h),Filebeat 会忽略,需调整该参数;
  • 检查 multiline 配置:若pattern不匹配日志起始行,会导致日志无法正确合并,需根据实际日志格式调整正则。

2. Logstash 接收不到 Filebeat 数据

  • 检查网络连通性:应用服务器能否 ping 通 Logstash 节点,且 5044 端口未被防火墙拦截(telnet 192.168.1.100 5044);
  • 验证 Logstash 输入配置:确保beats输入的port与 Filebeat 的output.logstash.hosts一致;
  • 查看 Logstash 日志tail -f /var/log/logstash/logstash-plain.log,排查是否有连接报错。

3. Kibana 中看不到日志

  • 检查 Elasticsearch 索引:通过curl http://192.168.1.101:9200/_cat/indices确认索引是否创建;
  • 创建 Kibana 索引模式:在 Kibana“Stack Management→索引模式” 中,创建匹配索引(如user-service-log-*),并指定时间字段@timestamp
  • 时间范围筛选:Kibana 默认筛选 “最近 15 分钟” 日志,若日志时间不在该范围,需调整时间筛选条件。

总结

ELKF 通过引入 Filebeat 解决了传统 ELK 在大规模部署时的资源占用问题,形成 “轻量采集→复杂处理→分布式存储→可视化分析” 的企业级日志方案。核心要点:

  1. Filebeat 配置需聚焦 “日志路径” 和 “多行处理”,确保采集可靠;
  2. Logstash 需通过beats输入接收数据,重点做好日志解析与脱敏;
  3. 索引管理和性能优化是 ELKF 稳定运行的关键,需结合 ILM 和分片策略;
  4. 利用自定义字段(如appenvtrace_id)提升日志筛选与链路追踪能力。

ELKF 不仅适用于中小型应用,也能支撑大规模分布式系统的日志管理需求,是企业级日志平台的首选架构之一