3. 日志采集技术:Filebeat、Logstash、Fluentd 选型与实战

日志采集,说白了就是“把机器上的日志搬到平台里去”。但搬法不同,坑也完全不同。我在不同项目里把这几个工具都用了一遍,有些经验值得分享。

3.1 Filebeat:轻量级搬运工

Filebeat 是 Elastic 生态里的“轻量级选手”。它能干啥?读文件,发数据。别的花活它不干。

核心定位:日志采集的“最后一公里”Agent。

我个人习惯,每台服务器只装 Filebeat。因为它的内存占用通常不到 20MB,CPU 也几乎没影响。你想想看,线上几百台机器,如果每个都装个 Logstash,那资源开销就直接起飞了。

Filebeat 的工作流很简单:

  1. 监听日志文件的变化(类似 tail -f)
  2. 从文件里读一行,打包成 event
  3. 发送到 Elasticsearch 或 Logstash

配置起来也很直白:

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
  multiline.pattern: '^\d{4}-\d{2}-\d{2}'
  multiline.negate: true
  multiline.match: after

output.elasticsearch:
  hosts: ["http://elasticsearch:9200"]
  index: "app-logs-%{+yyyy.MM.dd}"

小技巧:多行日志(比如 Java 的堆栈信息)一定要用 multiline 配置合并。不然一条报错会被拆成几十条记录,根本没法查。

我曾经遇到过一个问题:日志路径配错了,Filebeat 启动也没报错,但就是不发数据。后来一排查,原来是路径里带了通配符,但实际文件不匹配。所以启动后一定要盯一下 filebeat status 的输出。

3.2 Logstash:数据加工厂

Logstash 就不一样了。它不是“搬运工”,是“加工厂”。它的核心能力是:接收数据、解析数据、转换数据、输出数据。

但代价也明显:重。我在一个项目里,Logstash 配了几个 filter 之后,JVM 堆内存直接吃了 1.5GB。如果不是必须做复杂处理,我建议不要直接用 Logstash 做采集。

来,看个完整配置:

input {
  beats {
    port => 5044
  }
}

filter {
  grok {
    match => { "message" => "%{COMBINEDAPACHELOG}" }
  }

  date {
    match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
    target => "@timestamp"
  }

  mutate {
    convert => ["response", "integer"]
    convert => ["bytes", "integer"]
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "apache-logs-%{+yyyy.MM}"
  }
}

这里重点说说 grok。说白了就是用正则从日志里提取字段。比如上面那个 %{COMBINEDAPACHELOG},能直接把一行 Apache 日志拆出 IP、时间、请求路径、状态码、大小等十几个字段。省去自己写正则的麻烦。

注意:grok 模式虽然方便,但性能开销很大。如果每秒几万条日志,每条都用复杂的 grok 解析,CPU 吃满是很正常的事。我的经验是,在前端 Filebeat 里尽量做简单处理,让 Logstash 只做核心解析。

3.3 Fluentd:跨语言的通用管道

Fluentd 是 CNCF 的项目。它和 Logstash 很像,但设计理念不同。Fluentd 更强调“插件化”和“生态中立”。说白了,它不挑食:什么语言写的日志都能接,什么存储后端都能送。

它的配置也是基于“Input → Buffer → Output”的三段式:

# fluentd 示例配置

  @type tail
  path /var/log/nginx/access.log
  format apache2
  tag nginx.access



  @type record_transformer
  <record>
    service ${tag}
  </record>



  @type elasticsearch
  host elasticsearch
  port 9200
  logstash_format true

Fluentd 的一个好处是 buffer 机制很成熟。你想想看,如果 Elasticsearch 挂了,数据总得有个地方暂存。Fluentd 可以写到磁盘,等 ES 恢复后再重发。

关键对比点:Logstash 强在解析能力(grok),Fluentd 强在稳定性(buffer)。Filebeat 强在轻量。

3.4 三款工具的选型对比

我把这三个工具的核心差异整理成一个表格。你在选型时可以对着看:

维度 Filebeat Logstash Fluentd
定位 轻量 Agent,只采集 数据加工管道,重处理 通用数据采集 + 转发
配置格式 YAML,简洁 自定义 DSL,灵活 自定义 DSL,易读
资源消耗 极低(20MB 内存) 较高(500MB+ 常见) 中等(100-200MB)
插件生态 较少,主要对接 ES 丰富,适合 ES 生态 非常丰富,支持多后端
数据处理能力 弱(仅支持简单字段操作) 强(grok、mutate、date 等) 中(filter 插件,但不如 Logstash 强大)
可靠性 中等(无内置 buffer) 中等(依赖 ES 输出插件) 高(内置 file buffer)
适用场景 小规模、纯日志搬运 复杂日志解析、ETL 多数据源、多云架构

3.5 我的选型建议

  1. 就一条:如果你在跑 Elastic Stack,最佳组合是 Filebeat + Logstash。
  2. 如果不想多维护一个 Logstash,或者日志格式简单,可以 Filebeat 直连 Elasticsearch。
  3. 如果你的架构里既有 ES 又有 Kafka 或 S3,那 Fluentd 是最好的选择。它的 buffer 和转发能力很扎实。

避坑指南:我曾经在线上环境直接用 Logstash 做采集 Agent,结果日志量一大,Logstash 内存飙到 2GB 以上,直接触发 OOM。从那以后我就定了个规矩:采集只用 Filebeat,处理只用 Logstash/Fluentd,职责边界必须清晰。

日志采集技术选型框架 应用日志 系统日志 容器日志 Filebeat Logstash Fluentd 数据缓冲 / 过滤 Elasticsearch / Kafka / S3 三选一,按需组合

这张图其实就说明了我的核心观点:采集用 Filebeat,处理用 Logstash 或 Fluentd。不要试图让一个工具干所有事,最后样样不精。