4、日志采集工具(Fluentd):架构、配置与实战调优

说到日志采集,很多人第一反应是 Filebeat 或者 Logstash。但我个人习惯,在需要处理复杂数据流、或者要对接多种输出目标时,首选 Fluentd。

为什么?因为它轻量、插件生态丰富,而且内存占用比 Logstash 低不少。我在一个日处理 10TB 日志的项目里,用 Fluentd 替代了 Logstash,机器成本直接降了 40%。

4.1 Fluentd 核心架构

Fluentd 的架构,说白了就是一条流水线:Input → Buffer → Output。但这条流水线里藏着不少门道。

核心组件一览:

  • Input:数据入口,监听文件、网络、HTTP 等来源
  • Buffer:内存或磁盘缓冲,防止数据丢失
  • Output:数据出口,写入 Kafka、ES、S3 等目标
  • Filter:可选的数据处理层,做解析、过滤、转换

嗯,这里要注意:Fluentd 的 Buffer 不是可选项,而是必选项。我曾经见过有人把 buffer 设得太小,结果流量一上来直接丢数据。

Fluentd 核心数据流架构 Input 插件 tail / http / tcp Filter 插件 grep / parser / record Buffer 内存 / 文件 Output 插件 Kafka / ES / S3 数据流方向:从左到右 1. Input 采集原始日志(文件、网络、容器 stdout) 2. Filter 做解析、过滤、字段处理 3. Buffer 暂存数据,防止下游抖动导致丢失 4. Output 批量写入目标系统

4.2 Input / Output 插件实战

Fluentd 的插件生态非常丰富。官方有 1000+ 插件,但常用的其实就那十来个。我挑几个最核心的讲讲。

4.2.1 Input 插件:从哪里拿数据

插件名称 适用场景 我踩过的坑
in_tail 监控文件尾部追加(最常用) 日志轮转时没配 rotate_wait,导致重复读取
in_http 接收 HTTP POST 请求 没限制 body 大小,被大请求打爆内存
in_forward 接收其他 Fluentd 实例转发 心跳超时设太短,频繁断连
in_syslog 接收 syslog 协议 端口冲突,跟 rsyslog 抢 514

举个例子,最常用的 in_tail 配置:

<source>
  @type tail
  path /var/log/app/*.log
  pos_file /var/log/fluentd/app.pos
  tag app.log
  <parse>
    @type json
  </parse>
  rotate_wait 5s
  read_from_head false
</source>

我的习惯:pos_file 一定要配。否则 Fluentd 重启后会从头读文件,重复数据能把你下游搞崩溃。我曾经因为这个被 DBA 骂过。

4.2.2 Output 插件:数据往哪送

Output 插件是 Fluentd 的重头戏。我重点说两个:out_kafka 和 out_elasticsearch。

插件 优势 注意事项
out_kafka 高吞吐、持久化、解耦 需要配好 buffer_chunk_limit 和 flush_interval
out_elasticsearch 直接写入 ES,适合实时检索 注意 bulk_message_size,太大容易超时
out_s3 归档冷数据,成本低 文件命名策略要规划好,否则查起来想哭

4.3 Fluentd 与 Kafka 集成

这是生产环境最常见的组合。Fluentd 做采集,Kafka 做缓冲和解耦,下游再对接实时计算或存储。

配置示例:

<match app.log>
  @type kafka2
  brokers kafka1:9092,kafka2:9092,kafka3:9092
  topic app_logs
  required_acks -1
  compression_codec gzip
  
  <buffer>
    @type file
    path /var/log/fluentd/buffer/kafka
    chunk_limit_size 8MB
    flush_interval 5s
    retry_max_times 10
    retry_wait 2s
  </buffer>
</match>

注意:Kafka 的 required_acks -1 意味着所有副本都确认才返回。这会降低吞吐,但保证不丢数据。如果追求性能,可以改成 1。

为什么会推荐用 file buffer 而不是 memory?

你想想看,如果 Kafka 挂了,memory buffer 里的数据就全丢了。file buffer 虽然慢一点,但安全。我在一个金融项目里吃过这个亏,Kafka 集群重启了 5 分钟,memory buffer 里的 2GB 日志直接蒸发。从那以后,生产环境我全部用 file buffer。

4.4 Fluentd 性能调优

调优这件事,说白了就是找瓶颈。Fluentd 的瓶颈通常出现在三个地方:CPU、内存、磁盘 I/O。

4.4.1 Buffer 参数调优

参数 默认值 建议值 说明
chunk_limit_size 8MB 16MB - 64MB 单次写入的数据块大小,越大吞吐越高,但内存占用也大
flush_interval 60s 5s - 30s 刷盘间隔,实时性要求高就设小点
retry_max_times 17 10 - 20 重试次数,太多会堆积数据
retry_wait 1s 2s - 5s 重试间隔,指数退避

4.4.2 多 Worker 并行

Fluentd 1.0 之后支持多 Worker。如果你的机器有多个 CPU 核心,别浪费:

<system>
  workers 4
</system>

<worker 0>
  <source>
    @type tail
    path /var/log/app1/*.log
    tag app1
  </source>
</worker>

<worker 1>
  <source>
    @type tail
    path /var/log/app2/*.log
    tag app2
  </source>
</worker>

避坑指南:我曾经把 workers 设成 8,但机器只有 4 核。结果上下文切换开销比干活还大,吞吐反而下降了。workers 数不要超过 CPU 核心数。

4.4.3 监控与排查

Fluentd 内置了监控 API,非常实用:

# 开启监控
<source>
  @type monitor_agent
  bind 0.0.0.0
  port 24220
</source>

# 查看状态
curl http://localhost:24220/api/plugins.json

返回的数据里,重点关注这几个字段:

  • buffer_queue_length:队列长度,持续增长说明下游处理不过来
  • retry_count:重试次数,太高说明输出有问题
  • flush_time_count:刷盘耗时,太长说明磁盘 I/O 是瓶颈

嗯,最后说一句:Fluentd 的调优没有银弹。每个场景的流量模型、日志格式、下游系统都不一样。我的做法是:先跑一周默认配置,看监控数据,再针对瓶颈做调整。别一上来就改参数,你都不知道改的是啥。