日志采集工具(Filebeat):从架构到实战
日志采集是整个链路的第一步,也是最容易被低估的一步。我见过太多团队在 ELK 搭建好后才发现采集端丢数据、性能扛不住、配置混乱。说白了,采集工具选对了,后面的事就顺了。
今天咱们聊 Filebeat。它是 Elastic 官方出品的轻量级日志采集器,Go 语言写的,资源占用极低。我习惯把它比作「日志管道工」——不负责存储,不负责解析,只负责把日志从源头安全、高效地送到下游。
Filebeat 架构与原理
先看整体架构,我画了张图帮你快速建立认知。
Filebeat 内部有两个核心组件:Harvester 和 Spooler。
Harvester 负责读取日志文件。每个文件对应一个 Harvester,它打开文件句柄,按行读取新内容。嗯,这里要注意——如果文件被轮转(rotate),Harvester 会根据 inode 检测到变化,自动跟踪新文件。
Spooler 负责聚合和发送。Harvester 读到的日志不会立刻发出去,而是先放进 Spooler 的队列里。Spooler 攒够一批数据后,再批量发送到下游。这样做的好处很明显:减少网络连接次数,提高吞吐量。
关键设计理念:Filebeat 采用「至少一次」的投递语义。它会记录每个日志文件的读取偏移量(registry 文件),即使进程重启,也能从断点处继续读取,不会重复也不会遗漏。
Filebeat 安装与配置
安装 Filebeat 其实很简单。我习惯用 RPM 包部署,生产环境也推荐这种方式。
# 下载并安装(以 7.17.x 为例)
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.17.15-linux-x86_64.tar.gz
tar -xzf filebeat-7.17.15-linux-x86_64.tar.gz
cd filebeat-7.17.15-linux-x86_64/
核心配置文件是 filebeat.yml。我挑几个关键配置项说说。
| 配置项 | 说明 | 我的建议 |
|---|---|---|
filebeat.inputs |
定义日志采集源 | 每个 input 只采集一类日志,方便管理 |
filebeat.config.modules |
启用内置模块(如 Nginx、MySQL) | 能用模块就别手写配置 |
output.elasticsearch |
直接输出到 ES | 小规模场景可用,生产推荐走 Logstash |
output.logstash |
输出到 Logstash | 生产环境首选,方便做数据清洗 |
logging.level |
Filebeat 自身日志级别 | 调试时用 debug,正常用 info |
一个最简单的配置示例:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
service: nginx
env: production
output.elasticsearch:
hosts: ["http://localhost:9200"]
小技巧:启动前先用 ./filebeat test config 检查配置语法,用 ./filebeat test output 测试下游连通性。我每次改配置都会跑一遍,省得重启后才发现问题。
Filebeat 多文件采集
实际项目中,一台机器上往往有多个日志文件需要采集。比如 Nginx 访问日志、错误日志、应用业务日志。你想想看,如果每个日志都单独部署一个 Filebeat 进程,那得多浪费资源?
Filebeat 支持在一个实例中配置多个 input,每个 input 可以指定不同的路径和标签。
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
log_type: nginx_access
fields_under_root: true
- type: log
enabled: true
paths:
- /var/log/nginx/error.log
fields:
log_type: nginx_error
fields_under_root: true
- type: log
enabled: true
paths:
- /var/log/myapp/*.log
exclude_files: ['\.gz$']
multiline:
pattern: '^\d{4}-\d{2}-\d{2}'
negate: true
match: after
fields:
log_type: app_biz
fields_under_root: true
这里有个坑,我曾经踩过。多文件采集时,如果某个日志文件写入量特别大,会占满 Harvester 的处理能力,导致其他日志采集延迟。解决办法是给每个 input 设置 harvester_buffer_size 和 max_bytes 参数,限制单次读取量。
注意:多文件采集时,registry 文件会记录每个文件的读取位置。如果日志文件被删除或轮转,registry 中的记录不会自动清理。时间长了,registry 文件会越来越大。建议定期用 filebeat export registry 检查,必要时手动清理。
Filebeat 与 Logstash 集成
直接输出到 Elasticsearch 虽然简单,但生产环境我强烈建议中间加一层 Logstash。为什么?
- 数据清洗:Logstash 可以用 filter 插件做字段解析、格式转换、数据脱敏
- 缓冲能力:Logstash 支持持久化队列,即使 ES 挂了也不会丢数据
- 多路分发:一份日志可以同时发给 ES、Kafka、监控系统
Filebeat 端配置输出到 Logstash:
output.logstash:
hosts: ["192.168.1.10:5044", "192.168.1.11:5044"]
loadbalance: true
worker: 4
Logstash 端配置接收:
input {
beats {
port => 5044
host => "0.0.0.0"
ssl => true
ssl_certificate => "/etc/logstash/certs/logstash.crt"
ssl_key => "/etc/logstash/certs/logstash.key"
}
}
filter {
if [fields][log_type] == "nginx_access" {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
}
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "nginx-access-%{+YYYY.MM.dd}"
}
}
集成要点:
- Filebeat 和 Logstash 之间建议开启 SSL 加密,防止日志在传输中被截获
- Logstash 的
worker参数建议设置为 CPU 核心数,充分利用多核 - 如果日志量超过 10MB/s,考虑在中间加 Kafka 做缓冲层
我记得有一次线上事故,就是因为 Filebeat 直接连 ES,ES 集群 GC 停顿导致写入拒绝,Filebeat 的重试队列积压,最终 OOM 挂了。后来改成 Filebeat → Logstash → ES 的架构,Logstash 的持久化队列扛住了 ES 的抖动,再也没出过类似问题。
说白了,Filebeat 是轻骑兵,负责冲锋陷阵;Logstash 是后勤部,负责整理和分发。两者配合,才能构建一个稳定、可扩展的日志采集管道。