第2章:日志采集技术选型 — Filebeat vs Fluentd vs Logstash
日志采集是整个监控体系的起点。起点选错了,后面再折腾也白搭。
我见过不少团队,一上来就上 Logstash,结果内存吃紧、CPU 飙高,最后不得不推倒重来。也见过用 Filebeat 跑得很欢,但遇到复杂解析需求时,又得再套一层 Fluentd。说白了,没有银弹,只有最合适的组合。
2.1 三大采集器横向对比
先看一张对比表,心里有个底:
| 特性 | Filebeat | Fluentd | Logstash |
|---|---|---|---|
| 开发语言 | Go | Ruby + C | JRuby (JVM) |
| 资源占用 | 极低(~10MB) | 低(~50MB) | 高(~500MB+) |
| 吞吐量 | 高(10万+ 事件/秒) | 中高(5-10万 事件/秒) | 中(受JVM限制) |
| 插件生态 | 有限(主要面向ES) | 丰富(1000+ 插件) | 丰富(200+ 插件) |
| 数据缓冲 | 内置内存/磁盘缓冲 | 内置缓冲 + 插件扩展 | 依赖队列 + 持久化 |
| 部署复杂度 | 极简(单二进制) | 简单(gem安装) | 复杂(依赖JVM) |
| 适用场景 | 轻量采集 + 转发 | 多源采集 + 路由 | 复杂处理 + 清洗 |
我个人习惯这样选型:
- Filebeat:纯采集转发,不做复杂处理。适合边缘节点、K8s Sidecar 模式。
- Fluentd:需要多源接入、标签路由、中间处理。适合中大型集群。
- Logstash:需要深度解析、数据清洗、格式转换。适合中心化处理层。
核心原则:采集层尽量轻,处理层尽量重。别把脏活累活都堆在采集端。
2.2 采集器部署架构
部署架构决定了你的运维成本和扩展能力。我见过三种主流模式:
2.2.1 直连模式(小规模)
每个节点部署 Filebeat,直接发送到 Elasticsearch 或 Kafka。简单粗暴,适合几十台机器的场景。
# 架构示意
App Log → Filebeat → Elasticsearch
嗯,这里要注意:一旦节点数超过 100,ES 的写入压力会陡增。我曾经踩过这个坑,Filebeat 默认的 bulk 大小是 1MB,并发一高,ES 直接拒绝连接。
2.2.2 缓冲模式(中规模)
引入 Kafka 或 Redis 作为缓冲层。采集器只管收,消费者慢慢处理。
# 架构示意
App Log → Filebeat → Kafka → Logstash → Elasticsearch
为什么加 Kafka?说白了,就是为了解耦。采集端和消费端可以独立扩缩容。我在一个日处理 10TB 日志的项目里,就是靠 Kafka 扛住了流量洪峰。
小技巧:Filebeat 的 output.kafka 支持压缩,建议开启 gzip 压缩,能省 60% 的网络带宽。
2.2.3 多层聚合模式(大规模)
边缘节点用 Filebeat 采集,汇聚到 Fluentd 做标签路由,再转发到 Logstash 做深度处理。
# 架构示意
Node1: Filebeat → Fluentd (聚合层) → Kafka
Node2: Filebeat → Fluentd (聚合层) → Kafka
Kafka → Logstash → Elasticsearch
这种架构的好处是:每一层职责单一。Filebeat 只管采集,Fluentd 只管路由,Logstash 只管处理。出了问题,定位也快。
2.3 日志源接入方式
日志源五花八门,但接入方式就那么几种。我重点讲三个最常见的:
2.3.1 文件接入
最传统的方式。Filebeat 的 input.log 模块,Fluentd 的 in_tail 插件,Logstash 的 file 输入插件,都能搞定。
# Filebeat 配置示例
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
你想想看,多行日志(比如 Java 异常栈)怎么处理?上面这个配置就是答案:按时间戳开头合并多行。
避坑指南:我曾经遇到过 Filebeat 读取日志文件时,因为日志轮转(logrotate)导致文件句柄丢失。解决办法是开启 close_inactive: 5m 和 clean_removed: true,让 Filebeat 自动清理过期文件句柄。
2.3.2 TCP/UDP 接入
适合接收远程日志,比如网络设备、第三方系统。Fluentd 的 in_tcp 和 Logstash 的 tcp 输入插件是主力。
# Fluentd TCP 接入配置
<source>
@type tcp
port 5140
bind 0.0.0.0
tag syslog
<parse>
@type syslog
</parse>
</source>
注意:TCP 接入要小心连接数。我曾经在生产环境开了一个 TCP 端口,结果被几百台设备同时连接,Fluentd 直接 OOM。后来加了 client_max_connections 限制才稳住。
2.3.3 Kubernetes 容器日志接入
K8s 环境下的日志采集,是现在最主流的需求。我推荐两种方式:
- DaemonSet 模式:每个节点部署一个采集器,读取宿主机上的容器日志文件。Filebeat 和 Fluentd 都支持。
- Sidecar 模式:每个 Pod 里挂一个采集容器,专门负责日志转发。适合需要独立配置的场景。
# Fluentd DaemonSet 配置(关键部分)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
template:
spec:
containers:
- name: fluentd
image: fluent/fluentd:v1.16
volumeMounts:
- name: varlog
mountPath: /var/log
- name: dockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: varlog
hostPath:
path: /var/log
- name: dockercontainers
hostPath:
path: /var/lib/docker/containers
我个人更倾向 DaemonSet 模式。为什么?因为 Sidecar 模式会浪费资源——每个 Pod 多一个容器,1000 个 Pod 就多 1000 个采集进程。而 DaemonSet 只跟节点数挂钩,成本可控。
总结一下:
- 小规模、轻量需求 → Filebeat
- 多源、路由需求 → Fluentd
- 复杂处理、清洗需求 → Logstash
- K8s 环境 → DaemonSet + Filebeat/Fluentd
好了,日志采集这块就聊到这儿。下一章我们聊聊日志传输的可靠性保障——说白了,就是怎么保证日志不丢、不重、不乱序。到时候见。