一、前言¶
Fluentd 是一个开源的日志收集和传输工具,用于可靠地收集、传输和处理各种类型的 日志数据。它被设计成具有灵活性和可扩展性,可以在复杂的日志处理场景中进行配置和定制。
以下是 Fluentd 的主要特性和功能:
-
日志收集:Fluentd 可以从多种来源(如文件、网络、消息队列等)收集结构化和非结构化的日志数据。
-
数据转换和处理:Fluentd 具有强大的数据处理和转换能力。它可以根据需求对收 集到的日志数据进行解析、格式化、过滤、聚合和标记等操作。
-
数据路由和传输:Fluentd 支持将处理后的日志数据路由到不同的目的地。它提供 了丰富的输出插件,可以将数据发送到各种存储系统(如文件系统、数据库、消息
队列、Elasticsearch 等)或其他工具(如监控系统和处理流水线)进行进一步处理。
-
可扩展性:Fluentd 的架构设计允许在大规模和高负载环境下进行水平扩展。
-
插件生态系统:Fluentd 拥有广泛的插件生态系统,提供了各种丰富的输入、输出和过滤器插件。
-
可靠性和可恢复性:Fluentd 具有强大的容错和故障恢复机制。它支持数据缓冲、 重试、日志文件切割和轮转等特性,以确保日志数据的可靠传输和处理。
-
配置灵活性:Fluentd 的配置文件采用结构化的格式,允许您灵活地定义数据源、 转换规则、目的地和插件参数。

二、基于不同场景的安装配置¶
主要有2种方式:
- 手动安装:Fluentd 的配置和管理有更高级的要求,或者希望使用最新的稳定版 本,可以选择手动安装 Fluentd。手动安装涉及下载源代码并进行编译、安装和配置。这种方式需要更多的技术知识和时间,适合有经验的用户或特殊需求的情况。
- 容器化安装:由于 Fluentd 被广泛用于容器环境中,可以选择使用容器化技术(如 Docker)来安装和运行 Fluentd。这种方式使得在不同的云平台、开发环境和生产 环境中部署和管理 Fluentd 变得更加方便和可重复。
2.1 手动安装Fluentd¶
环境配置优化:
- 设置 NTP
- 增加文件描述符的最大数量
- 优化网络内核参数
设置 NTP
强烈建议你在节点上设置 NTP 守护进程(例如时间戳,这对于所有生产服务至关重要。
增加文件描述符的最大数量
我们可以使用 ulimit -n 命令查看现有配置:
$ ulimit -n
65535
如果你的控制台显示1024,那是不够的。请将以下几行添加到
/etc/security/limits.conf 文件并重启机器:
root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
如果使用 systemd 下运行 fluentd,也可以使用选项 LimitNOFILE=65536 进行配置,如果你使用的是 td-agent 包,则默认会设置该值。
优化网络内核参数
对于具有许多 Fluentd 实例的高负载环境,可以将以下配置添加到 /etc/sysctl.conf 文件中:
net.core.somaxconn = 1024
net.core.netdev_max_backlog = 5000
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_wmem = 4096 12582912 16777216
net.ipv4.tcp_rmem = 4096 12582912 16777216
net.ipv4.tcp_max_syn_backlog = 8096
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240 65535
使用 sysctl -p 命令或重新启动节点使更改生效。
一键安装Fluentd
$ curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh
通过 systemctl 来管理 td-agent 服务:
$ systemctl start td-agent && systemctl status td-agent
测试验证
td-agent 启动后通过下面的命令来发送一条日志:
$ netstat -lntp |grep 8888
tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN 7157/ruby
$ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
发送后查看 td-agent 的日志,正常会收到如下所示的日志信息:
$ tail -n 1 /var/log/td-agent/td-agent.log'
2023-07-06 18:58:53.800889847 +0800 debug.test: {"json":"message"}
2.2 Docker安装Fluentd¶
使用Docker方式在不同的云平台、开发环境和生产环境中部署和管理 Fluentd 变得更加方便和可重复;
[root@master01 ~]# mkdir fluentd && cd fluentd
# 创建用于保存 fluentd 的配置文件 etc 目录和保存日志的 logs 目录
[root@master01 fluentd]# mkdir -p etc logs
# 添加一个简单的配置文件
[root@master01 fluentd]# vim etc/fluentd_basic.conf
# Fluentd 数据源配置,使用 HTTP 输入
<source>
@type http
port 8888
bind 0.0.0.0
</source>
# Fluentd 匹配规则,匹配所有以 test.basic 开头的标签
<match test.basic>
@type stdout
</match>
Fluentd 的启动
[root@master01 fluentd]#
docker run \
-itd \
-p 8888:8888 \
--rm \
-v $(pwd)/etc:/fluentd/etc \
-v $(pwd)/logs:/fluentd/logs \
fluent/fluentd:v1.14-1 \
-c /fluentd/etc/fluentd_basic.conf
将 etc 目录和 logs 目录挂载到容器中;
- -c:参数指定 Fluentd 的配置文件;
- -v:参数是用于设置 Fluentd 开启 verbose 模式,便于查看 Fluentd 的日志方便调试;
测试验证
[root@master01 fluentd]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c28561396da fluent/fluentd:v1.14-1 "tini -- /bin/entryp…" About a minute ago Up About a minute 5140/tcp, 24224/tcp, 0.0.0.0:8888->8888/tcp, :::8888->8888/tcp elegant_yalow
# 查看日志
[root@master01 fluentd]# docker logs -f 4c28561396da
正常会看到如下所示的输出信息:
fluentd -c /fluentd/etc/fluentd_basic.conf
2025-04-15 07:50:19 +0000 [info]: parsing config file is succeeded path="/fluentd/etc/fluentd_basic.conf"
2025-04-15 07:50:19 +0000 [info]: gem 'fluentd' version '1.14.6'
2025-04-15 07:50:19 +0000 [info]: using configuration file: <ROOT>
<source>
@type http
port 8888
bind "0.0.0.0"
</source>
<match test.basic>
@type stdout
</match>
</ROOT>
2025-04-15 07:50:19 +0000 [info]: starting fluentd-1.14.6 pid=7 ruby="2.7.6"
2025-04-15 07:50:19 +0000 [info]: spawn command to main: cmdline=["/usr/bin/ruby", "-Eascii-8bit:ascii-8bit", "/usr/bin/fluentd", "-c", "/fluentd/etc/fluentd_basic.conf", "--plugin", "/fluentd/plugins", "--under-supervisor"]
2025-04-15 07:50:19 +0000 [info]: adding match pattern="test.basic" type="stdout"
2025-04-15 07:50:19 +0000 [info]: adding source type="http"
2025-04-15 07:50:19 +0000 [info]: #0 starting fluentd worker pid=16 ppid=7 worker=0
2025-04-15 07:50:19 +0000 [info]: #0 fluentd worker is now running worker=0
启动后我们同样可以发送一条日志到 Fluentd 来验证我们的配置:
[root@master01 ~]# curl -iX POST -d 'json={"action":"login","user":100}' http://localhost:8888/test.basic
# 回显信息
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: Keep-Alive
Content-Length: 0
发送后正常会在 Fluentd 中查看到如下所示的一条信息:
2025-04-15 07:55:36.046784267 +0000 test.basic: {"action":"login","user":100}
三、事件管理¶
3.1 事件生命周期¶
Fluentd 是一个开源的日志收集和传输工具,其事件生命周期可以简单概括为以下几个阶段:
- 输入(Input)阶段:在输入阶段,Fluentd 从各种来源(如文件、网络流、消息队列等)接收日志事件。
-
解析(Parse)阶段:在解析阶段, Fluentd 对输入的原始日志进行解析,将其转换为结构化的事件数据。
-
过滤(Filter)阶段:在过滤阶段,Fluentd 对解析后的事件数据进行筛选、处理和转 换。通过配置不同的过滤器插件,可以实现日志的筛选、修改、标记、丰富等操作。
- 缓冲(Buffer)阶段:在缓冲阶段,Fluentd 将经过解析和过滤的事件数据缓存起来, 以便进行批量传输或更高效的处理。
- 输出(Output)阶段:在输出阶段,Fluentd 将经过解析、过滤和缓冲的事件数据发送 到目标存储、消息队列、日志分析工具或其他目的地。
3.2 事件内容¶
Fluentd 的事件主要由下面三部分组成:
- 标签(Tag):标签是 Fluentd 用于对事件进行分类和路由的关键标识。它是一个字 符串,可以用来表示事件的来源、类型、应用程序等信息。通过配置不同的标签, 您可以将事件路由到相应的输出插件或处理流程中。
- 时间(Time):时间是 Fluentd 事件的一个重要属性,表示事件生成或发生的时间 戳。时间戳可以是 Unix 时间戳(秒级或毫秒级),也可以是 ISO 8601 格式的字符 串。时间戳信息通常用于日志的排序、分析和时间窗口的计算。
- 记录(Record):记录是 Fluentd 事件中的数据部分,它是一个结构化的键值对或 JSON 对象。记录包含了事件所携带的具体数据,可以是应用日志、系统指标、传感 器数据等各种形式的信息。在 Fluentd 的输入、解析、过滤和输出阶段,记录将被处理、转换和传输。
所有的输入插件都需要解析原始日志,生成满足上面结构的事件字段,比如一条 Apache 的访问日志:
192.168.0.1 - - [8/Jul/2023:12:00:00 +0800] "GET / HTTP/1.1" 200 777
在通过 in_tail 输入插件处理后,会得到如下所示的输出结果:
tag: apache.access # 通过配置文件指定
time: 1362020400 # 8/Jul/2023:12:00:00 +0800
record: {"user": "-", "method": "GET", "code": 200, "size": 777,
"host": "192.168.0.1", "path": "/"}
当 Fluentd 收到一条事件后会经过一系列的处理流程:
- 修改事件的相关字段
- 过滤掉一些不需要的事件
- 路由事件输出到不同的地方
四、过滤器Filter¶
Filter 用于定义一个事件是该被接受或是被过滤掉,接下来我们创建一个新的配置文件新增过滤器。
[root@master01 ~]# cd fluentd/
[root@master01 fluentd]# cat etc/fluentd_filter.conf
<source>
@type http
port 8888
bind 0.0.0.0
</source>
<filter test.logs>
@type grep
<exclude>
key action
pattern ^logout$
</exclude>
</filter>
<match test.logs>
@type stdout
</match>
在该配置文件中我们新增了一个 filter 模块,使用 grep 插件,exclude 部分表示要过滤 掉的日志配置,这里我们配置的是 action 这个 key 匹配 ^logout$ 的时候进行过滤,就是直接过滤掉 logout 日志事件。
使用新的配置文件,重新启动fluentd:
# 停掉之前启动的容器
[root@master01 fluentd]# docker stop 4c28561396da
# 新启动一个容器
[root@master01 fluentd]#
docker run \
-itd \
-p 8888:8888 \
--rm \
-v $(pwd)/etc:/fluentd/etc \
-v $(pwd)/logs:/fluentd/logs \
fluent/fluentd:v1.14-1 \
-c /fluentd/etc/fluentd_filter.conf
# 查看容器日志信息
[root@master01 fluentd]# docker logs -f 5259f326104b
重新向 Fluentd 提交两条日志数据:
[root@master01 ~]# curl -X POST -d 'json={"action":"login","user":2}' http://localhost:8888/test.logs
[root@master01 ~]# curl -X POST -d 'json={"action":"logout","user":2}' http://localhost:8888/test.logs
正常这个时候 Fluentd 只会收到第一条日志数据, logout 这条事件被过滤掉了:
2025-04-15 08:24:47.315331018 +0000 test.logs: {"action":"login","user":2}
五、标识符 Labels¶
Fluentd 的处理流程:根据在配置文件中的定义从上到下依次执行。
假如在配置文件中定义了多个输入源,不同的输入源需要使用不同的 Filters 过滤器的时候,如果还按照顺序执行的方式,配置文件就会变得非常复杂。
为了解决这个问题,Fluentd 中提供了一种标识符 Labels 的方式,可以为不同的输入源 指定不同的处理流程。
如下所示创建一个新的配置文件 fluentd_labels.conf:
[root@master01 ~]# cd fluentd/
[root@master01 fluentd]# vim etc/fluentd_labels.conf
<source>
@type http
port 8888
bind 0.0.0.0
@label @TEST
</source>
<filter test.logs>
@type grep
<exclude>
key action
pattern ^login$
</exclude>
</filter>
<label @TEST>
<filter test.logs>
@type grep
<exclude>
key action
pattern ^logout$
</exclude>
</filter>
<match test.logs>
@type stdout
</match>
</label>
首先我们在输入源中给日志源定义了一个标签 @label @TEST,然后先定义了一个 filter过滤掉 login 事件,然后在一个 label 模块里面过滤了 logout 事件。
现在我们使用该配置重新启动 Fluentd:
# 停掉之前启动的容器
[root@master01 fluentd]# docker stop 203e65c64807
# 新启动一个容器
[root@master01 fluentd]#
docker run \
-itd \
-p 8888:8888 \
--rm \
-v $(pwd)/etc:/fluentd/etc \
-v $(pwd)/logs:/fluentd/logs \
fluent/fluentd:v1.14-1 \
-c /fluentd/etc/fluentd_labels.conf
然后重新向 Fluentd 提交两条日志数据:
[root@master01 ~]# curl -X POST -d 'json={"action":"login","user":2}' http://localhost:8888/test.logs
[root@master01 ~]# curl -X POST -d 'json={"action":"logout","user":2}' http://localhost:8888/test.logs
正常 Fluentd 中会输出一条日志记录:
2025-04-15 08:29:09.802951036 +0000 test.logs: {"action":"login","user":2}
这是因为我们为输入日志设置了 @TEST 的标签,因此跳过中间设置的一些过滤器,只运行了 <label @TEST>...\</lable> 标签块里的过滤器,如果标签块里面没有定义过滤器则就不会过滤日志了。