一、前言

Fluentd 是一个开源的日志收集和传输工具,用于可靠地收集、传输和处理各种类型的 日志数据。它被设计成具有灵活性和可扩展性,可以在复杂的日志处理场景中进行配置和定制。

以下是 Fluentd 的主要特性和功能:

  1. 日志收集:Fluentd 可以从多种来源(如文件、网络、消息队列等)收集结构化和非结构化的日志数据。

  2. 数据转换和处理:Fluentd 具有强大的数据处理和转换能力。它可以根据需求对收 集到的日志数据进行解析、格式化、过滤、聚合和标记等操作。

  3. 数据路由和传输:Fluentd 支持将处理后的日志数据路由到不同的目的地。它提供 了丰富的输出插件,可以将数据发送到各种存储系统(如文件系统、数据库、消息

队列、Elasticsearch 等)或其他工具(如监控系统和处理流水线)进行进一步处理。

  1. 可扩展性:Fluentd 的架构设计允许在大规模和高负载环境下进行水平扩展。

  2. 插件生态系统:Fluentd 拥有广泛的插件生态系统,提供了各种丰富的输入、输出和过滤器插件。

  3. 可靠性和可恢复性:Fluentd 具有强大的容错和故障恢复机制。它支持数据缓冲、 重试、日志文件切割和轮转等特性,以确保日志数据的可靠传输和处理。

  4. 配置灵活性:Fluentd 的配置文件采用结构化的格式,允许您灵活地定义数据源、 转换规则、目的地和插件参数。

Day09-可观察性-ELK&Loki-图16

二、基于不同场景的安装配置

主要有2种方式:

  1. 手动安装:Fluentd 的配置和管理有更高级的要求,或者希望使用最新的稳定版 本,可以选择手动安装 Fluentd。手动安装涉及下载源代码并进行编译、安装和配置。这种方式需要更多的技术知识和时间,适合有经验的用户或特殊需求的情况。
  2. 容器化安装:由于 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 是一个开源的日志收集和传输工具,其事件生命周期可以简单概括为以下几个阶段:

  1. 输入(Input)阶段:在输入阶段,Fluentd 从各种来源(如文件、网络流、消息队列等)接收日志事件。
  2. 解析(Parse)阶段:在解析阶段, Fluentd 对输入的原始日志进行解析,将其转换为结构化的事件数据。

  3. 过滤(Filter)阶段:在过滤阶段,Fluentd 对解析后的事件数据进行筛选、处理和转 换。通过配置不同的过滤器插件,可以实现日志的筛选、修改、标记、丰富等操作。

  4. 缓冲(Buffer)阶段:在缓冲阶段,Fluentd 将经过解析和过滤的事件数据缓存起来, 以便进行批量传输或更高效的处理。
  5. 输出(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> 标签块里的过滤器,如果标签块里面没有定义过滤器则就不会过滤日志了。