背景和概述
tail 是 Fluent Bit 中最常用的输入插件之一,负责从本地文本文件持续读取日志消息。它可以监视一个或多个文件,把日志发送给 Fluent Bit 后续的过滤、解析和输出流程,也可以继续转发到 Fluentd 或其他后端系统。
这篇入门教程用一个可运行示例说明 Fluent Bit tail 插件的标准配置。读完后,你应该能回答三个问题:
- 如何用
Path指定要采集的日志文件。 Read_from_head什么时候需要开启,开启后有什么重复采集风险。- 为什么生产配置里通常要配合
DB保存文件偏移量。
在本博客系列中,我们将介绍一个用例,其中 tail 插件用于从日志文件获取数据并发送到 Fluent Bit。使用 Fluent Bit 从各种系统收集事件数据并将其发送到 Fluentd 或其他应用程序是很常见的。由于 Fluent Bit 快速且轻量级,因此可以较低成本地从不同来源收集事件;Fluentd 则更适合在后端聚合多个输入、处理数据并路由到不同输出。

在本博客中,作为用例的开始,我们将使用 tail 插件和标准配置文件运行 Fluent Bit。后续文章会继续介绍日志解析和多行日志等进阶配置。
Fluentbit 实验环境
- 操作系统:CentOS8
- Fluent Bit 版本:v2.0.6
- 硬件规格:2CPU,2GB内存
我们假设您已经在计算机上下载了 Fluent Bit 备用。如果您尚未安装 Fluent Bit,请自行下载安装。
Fluentbit 标准配置模式
本实验中描述的场景基于以下目录结构:
/fluentbit : root directory
|--- conf
|--- custom_parsers.conf
|--- Lab01
|-- (Lab01 configuration files)
|-- sample
|-- (Sample log files for exercise)
|--- log
|--- buffer
这是一个 tail 插件配置。理解这个配置时,重点看三个参数:
- Path:通过使用通用通配符指定一个或多个日志文件。也允许用逗号分隔。
- Read_from_head:对于开始时新发现的文件(没有保存偏移位置的),从文件的头部而不是尾部读取内容。
- DB:指定数据库文件来跟踪受监视的文件和偏移量。
[INPUT]
Name tail
Tag syslog
Path /var/log/messages
Read_from_head true
DB /fluentbit/tail_syslog.db
Storage.type filesystem
在上面的示例中,配置了 Read_from_head 和 DB 选项。
如果您想读取文件中已经存在的日志消息,建议使用 Read_from_head true。默认情况下,Read_from_head 为 false,这意味着 Fluent Bit 不会读取 Path 指定文件中的历史内容,只读取发现文件之后新增的日志。
需要注意的是,如果只开启 Read_from_head true,Fluent Bit 重启后可能再次从文件头读取,造成重复采集。为了避免这种情况,建议同时配置 DB 保存偏移信息。配置 DB 后,Fluent Bit 会在指定数据库文件中记录已读取到的位置,重启后继续从上次位置读取。
测试 tail
常见用例之一是读取 Linux 操作系统日志。 RHEL/CentOS 将其日志存储在:/var/log/messages。在本练习中,我们使用示例 Linux 日志:“sample/sample01_linux_messages.txt”。
下面是一个示例 Linux 日志,以及一个读取日志并在 stdout 中显示的示例配置。在 tail 部分,我们继续使用 Read_from_head 和 DB 选项。
sample01_linux_messages.txt 内容如下:
Oct 27 16:14:31 fluent01 systemd[1]: Started dnf makecache.
Oct 27 16:20:29 fluent01 systemd[1]: Starting system activity accounting tool...
Oct 27 16:20:29 fluent01 systemd[1]: Started system activity accounting tool.
Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.280967 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/cpu,cpuacct/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/cpu,cpuacct/system.slice/sysstat-collect.service: no such file or directory
Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.281027 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/blkio/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/blkio/system.slice/sysstat-collect.service: no such file or directory
Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.281048 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/memory/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/memory/system.slice/sysstat-collect.service: no such file or directory
下面是 Fluent Bit 完整配置文件。在 INPUT 部分,Path 要指向 sample01_linux_messages.txt 文件:
[SERVICE]
## General settings
Flush 5
Log_Level Info
Daemon off
Log_File /fluentbit/log/fluentbit.log
Parsers_File /fluentbit/conf/custom_parsers.conf
## Buffering and Storage
Storage.path /fluentbit/buffer/
Storage.sync normal
Storage.checksum Off
Storage.backlog.mem_limit 5M
Storage.metrics On
## Monitoring (if required)
HTTP_Server true
HTTP_Listen 0.0.0.0
HTTP_Port 2020
Health_Check On
HC_Errors_Count 5
HC_Retry_Failure_Count 5
HC_Period 60
[INPUT]
Name tail
Tag linux.messages
Path /fluentbit/conf/Lab01/sample/sample01_linux_messages.txt
Storage.type filesystem
Read_from_head true
DB /fluentbit/tail_linux_messages.db
[OUTPUT]
Name stdout
Match linux.messages
让我们运行 Fluent Bit 并检查其行为!
$ fluent-bit -c sample01_flb_tail_standard.conf
Fluent Bit v2.0.6
* Copyright (C) 2015-2022 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io
一段时间后,您还可以在 stdout 中看到输出消息。
[0] linux.messages: [1677106496.274148557, {"log"=>"Oct 27 16:14:31 fluent01 systemd[1]: Started dnf makecache."}]
[1] linux.messages: [1677106496.274161493, {"log"=>"Oct 27 16:20:29 fluent01 systemd[1]: Starting system activity accounting tool..."}]
[2] linux.messages: [1677106496.274162041, {"log"=>"Oct 27 16:20:29 fluent01 systemd[1]: Started system activity accounting tool."}]
[3] linux.messages: [1677106496.274162423, {"log"=>"Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.280967 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/cpu,cpuacct/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/cpu,cpuacct/system.slice/sysstat-collect.service: no such file or directory"}]
[4] linux.messages: [1677106496.274163003, {"log"=>"Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.281027 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/blkio/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/blkio/system.slice/sysstat-collect.service: no such file or directory"}]
[5] linux.messages: [1677106496.274163394, {"log"=>"Oct 27 16:40:29 fluent01 kubelet[896]: W1027 16:40:29.281048 896 watcher.go:95] Error while processing event ("/sys/fs/cgroup/memory/system.slice/sysstat-collect.service": 0x40000100 == IN_CREATE|IN_ISDIR): inotify_add_watch /sys/fs/cgroup/memory/system.slice/sysstat-collect.service: no such file or directory"}]
- 从输出中可以看到,默认情况下整个日志消息都嵌套在
log键下,因为配置中没有解析器定义。将纯文本解析为 JSON 将在另一篇博客中介绍。 - 此外,Fluent Bit 生成的时间戳与原始消息中的时间戳不同。时间戳调整将在另一篇博客中介绍。
DB 文件创建于 /fluencebit/tail_linux_messages.db。您可以通过以下步骤检查 db 文件内部,以防万一。
$ sqlite3 /fluentbit/tail_linux_messages.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> SELECT * FROM in_tail_files;
1|/fluentbit/conf/Lab01/sample/sample01_linux_messages.txt|1172|2322445|1677106496|0
从 SQLite DB 中查询,可以看到 Fluent Bit 为该文件保存了关键偏移信息:
- File ID(由 tail 插件生成):1
- 文件名:/fluencebit/conf/Lab01/sample/sample01_linux_messages.txt
- Offset 偏移量:1172
- inode: 2322445
- 创建时间:1677106496
要结束 sqlite3 命令,请按“ctrl”+“d”。然后让我们停止 Fluent Bit 并重新开始。在第一次运行时,Fluent Bit 已经读取了日志文件中的 5 行,并将偏移量信息存储在 DB 文件中。我们期望 Fluent Bit 不会再次读取这 5 行。
$ fluent-bit -c sample01_flb_tail_standard.conf
Fluent Bit v2.0.6
* Copyright (C) 2015-2022 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io
如果一切正常,标准输出中不会显示任何消息。这意味着 Fluent Bit 第二次启动时没有重复读取相同日志行,因为 DB 文件已经记录了从何处继续读取。
配置检查清单
把 tail 插件用于生产日志采集前,建议至少检查这几项:
| 检查项 | 作用 | 本文示例 |
|---|---|---|
Path |
指定被采集的一个或多个日志文件 | /fluentbit/conf/Lab01/sample/sample01_linux_messages.txt |
Read_from_head |
控制首次发现文件时是否读取历史内容 | true |
DB |
保存文件偏移量,避免重启后重复采集 | /fluentbit/tail_linux_messages.db |
Storage.type |
指定输入插件使用的存储类型 | filesystem |
OUTPUT |
验证日志是否被读取和输出 | stdout |
FAQ
Q1:为什么开启 Read_from_head 后还要配置 DB?
A:Read_from_head 解决的是“首次发现文件时是否读取历史日志”的问题;DB 解决的是“重启后从哪里继续读取”的问题。二者配合使用,才能既读取已有日志,又降低重复采集风险。
Q2:为什么输出里只有 log 字段?
A:本文示例没有配置解析器,所以 Fluent Bit 会把整行原始日志放在 log 字段下。后续如果需要提取时间、主机名、进程名和消息正文,需要配置 Parser。
Q3:如何确认 DB 偏移记录已经生效?
A:可以用 sqlite3 查询 DB 文件中的 in_tail_files 表。本文示例中可以看到文件名、偏移量、inode 和创建时间;第二次启动后 stdout 没有重复输出,也说明偏移记录生效。
总结
本文完成了 Fluent Bit tail 插件的第一个练习:从一个 Linux 日志样例读取内容,并输出到 stdout。这个练习的关键不在于配置多复杂,而在于建立稳定采集日志的基本模型:用 Path 找到文件,用 Read_from_head 控制历史日志读取,用 DB 保存偏移量,用 stdout 验证采集结果。
掌握这套基础配置后,就可以继续学习如何用 Parser 把纯文本日志解析成结构化字段,以及如何处理多行日志。欢迎关注后续博客。
原文:https://fluentd.ctc-america.com/blog/tail-in-fluent-bit-standard-configuration
