3. 日志采集技术:Filebeat、Logstash、Fluentd 选型与实战
日志采集,说白了就是“把机器上的日志搬到平台里去”。但搬法不同,坑也完全不同。我在不同项目里把这几个工具都用了一遍,有些经验值得分享。
3.1 Filebeat:轻量级搬运工
Filebeat 是 Elastic 生态里的“轻量级选手”。它能干啥?读文件,发数据。别的花活它不干。
核心定位:日志采集的“最后一公里”Agent。
我个人习惯,每台服务器只装 Filebeat。因为它的内存占用通常不到 20MB,CPU 也几乎没影响。你想想看,线上几百台机器,如果每个都装个 Logstash,那资源开销就直接起飞了。
Filebeat 的工作流很简单:
- 监听日志文件的变化(类似
tail -f) - 从文件里读一行,打包成 event
- 发送到 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 我的选型建议
- 就一条:如果你在跑 Elastic Stack,最佳组合是 Filebeat + Logstash。
- 如果不想多维护一个 Logstash,或者日志格式简单,可以 Filebeat 直连 Elasticsearch。
- 如果你的架构里既有 ES 又有 Kafka 或 S3,那 Fluentd 是最好的选择。它的 buffer 和转发能力很扎实。
避坑指南:我曾经在线上环境直接用 Logstash 做采集 Agent,结果日志量一大,Logstash 内存飙到 2GB 以上,直接触发 OOM。从那以后我就定了个规矩:采集只用 Filebeat,处理只用 Logstash/Fluentd,职责边界必须清晰。
这张图其实就说明了我的核心观点:采集用 Filebeat,处理用 Logstash 或 Fluentd。不要试图让一个工具干所有事,最后样样不精。