"本文主要讲解了fluentd的为什么选用fluentd作为核心组件,它的优势是什么"
1、前言
我是标题党,所谓佛无南北,架构没有好坏之分,只有是否合适的区别,比如常常被人诟病的单体架构,耦合性高,可扩展性低。事实上,特别对于有成本考虑的初创企业,单体架构常常是最佳选择,因为简单,它能快速帮助企业完成产品和市场的高度契合,但是当企业的用户规模扩大后,这样的架构往往又成为隐患。话又说回来了,没有一个可以适用于所有的产品和规模的完美架构,任何架构只能完成特定的一组目标,或者一系列的需求和条件。随着时间的推移,为了与时俱进,任何产品或者服务功能需要完善,架构也一样,那些在普通用户规模下的架构很少能在100倍规模下有效。
fluentd也一样,当存在多种多样数据源和存储目标时比较合适,因为它支持500+插件进行日志输入输出,特别是大多数数据源都是自定义的应用,你会发现fluentd和这些应用结合起来的能力比其它日志收集框架要简单有效。
2、性能
fluentd的性能已经在各个领域得到了证明,其最大的用户可以从50000+服务器中收集日志,每天处理5TB的数据,峰值时每秒可以处理5万行数据,可以在客户端和服务端分别部署,客户端收集日志发送到服务端(目前大多采用fluent-bit作为客户端)
3、架构
fluentd是一个开源的数据收集器,它统一了数据的收集和使用。它的架构有以下特点(看上图说话):
4、社区支持
fluentd目前由CNCF社区维护,大名鼎鼎的云原生计算基金会,云时代的操作系统Kubenetes就是由它发起和维护的。社区活跃,详情见下图:
5、安装使用
安装使用简单,支持多种安装方式,具体可以参考官网安装方式,最简单的方式就是直接通过镜像运行,使用方式,如下所示:
1. 拉取镜像
docker pull fluent/fluentd:v1.6-debian-1
2. 创建收集配置
# /tmp/fluentd.conf
<source>
@type http
port 9880
bind 0.0.0.0
</source>
<match **>
@type stdout
</match>
3. docker运行,启动fluentd
$ docker run -p 9880:9880 -v $(pwd)/tmp:/fluentd/etc -e FLUENTD_CONF=fluentd.conf fluent/fluentd:v1.6-debian-1
2019-08-21 00:30:37 +0000 [info]: parsing config file is succeeded path="/fluentd/etc/fluentd.conf"
2019-08-21 00:30:37 +0000 [info]: using configuration file: <ROOT>
<source>
@type http
port 9880
bind "0.0.0.0"
</source>
<match **>
@type stdout
</match>
</ROOT>
2019-08-21 00:30:37 +0000 [info]: starting fluentd-1.6.3 pid=6 ruby="2.6.3"
2019-08-21 00:30:37 +0000 [info]: spawn command to main: cmdline=["/usr/local/bin/ruby", "-Eascii-8bit:ascii-8bit", "/usr/local/bundle/bin/fluentd", "-c", "/fluentd/etc/fluentd.conf", "-p", "/fluentd/plugins", "--under-supervisor"]
2019-08-21 00:30:38 +0000 [info]: gem 'fluentd' version '1.6.3'
2019-08-21 00:30:38 +0000 [info]: adding match pattern="**" type="stdout"
2019-08-21 00:30:38 +0000 [info]: adding source type="http"
2019-08-21 00:30:38 +0000 [info]: #0 starting fluentd worker pid=13 ppid=6 worker=0
2019-08-21 00:30:38 +0000 [info]: #0 fluentd worker is now running worker=0
2019-08-21 00:30:38.332472611 +0000 fluent.info: {"worker":0,"message":"fluentd worker is now running worker=0"}
4. 发送HTTP请求
$ curl -X POST -d 'json={"json":"message"}' http://localhost:9880/sample.test
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
775a8e192f2b fluent/fluentd:v1.6-debian-1 "tini -- /bin/entryp…" About a minute ago Up About a minute 5140/tcp, 24224/tcp, 0.0.0.0:9880->9880/tcp tender_leakey
$ docker logs 775a8e192f2b | tail -n 1
2019-08-21 00:33:00.570707843 +0000 sample.test: {"json":"message"}
其它安装和使用方式可参照如下链接:
Kubernetes集群环境下fluentd日志收集方案介绍
6、线上实践
如上图所示,在各个节点上以DaemonSet方式部署fluent-bit,fluent-bit在各个节点上收集事件、日志等信息,收集完成后发送到fluentd进行统一汇总、过滤、存储处理。
示例:
fluentd指令配置信息:
<source>
@type forward
port 24224
</source>
# http://this.host:9880/myapp.access?json={"event":"data"}
<source>
@type http
port 9880
</source>
<match nginx*> #匹配有tag为mem的类型
@type stdout #匹配成功直接标准输出
</match>
# Match events tagged with "myapp.access" and
# store them to /var/log/fluent/access.%Y-%m-%d
# Of course, you can control how you partition your data
# with the time_slice_format option.
<match tbsm*>
@type file
path /home/logs/${tag}/${tag}
append true
<format>
@type single_value
message_key log
add_newline true
</format>
<buffer tag,time>
@type file
# timekey 5m 每隔5分钟形成一个日志文件
# timekey_wait 1m 生成等待时间1分钟
chunk_limit_size 50M
# 每隔1分钟写一次日志
flush_interval 1m
flush_at_shutdown true
flush_mode interval
</buffer>
</match>
以上能够满足把集群节点,各个服务的日志进行集中到fluentd节点上进行存储。目前上述指令配置能够把原来各个节点上的日志原封不动的集中到fluend所在服务器,当然你也可以对日志进行处理,比如json格式、添加时间戳、tag标签等。那么日志又是如何传递到fluentd服务呢?
如下所示fluent-bit配置:
[SERVICE]
Flush 1
Daemon ON
Log_Level debug
[INPUT]
Name tail
Path /home/logs/tbsms1/tbsms1.log
Db /tmp/tbsms1.db
Db.sync Full
Tag tbsms1
[INPUT]
Name tail
Path /home/logs/tbsms2/tbsms2.log
Db /tmp/tbsms2.db
Db.sync Full
Tag tbsms2
[INPUT]
Name tail
Path /home/logs/tbsms3/tbsms3.log
Db /tmp/tbsms3.db
Db.sync Full
Tag tbsms3
[INPUT]
Name tail
Path /home/logs/tbsms4/tbsms4.log
Db /tmp/tbsms4.db
Db.sync Full
Tag tbsms4
[INPUT]
Name tail
Path /home/logs/tbsms5/tbsms5.log
Db /tmp/tbsms5.db
Db.sync Full
Tag tbsms5
[OUTPUT]
Name forward
Match *
Host 12.18.1.6
Port 24224
如上所示就可以把各个服务所在日志路径下的日志信息发送到fluentd,当然,你可能会说,当我的服务出现问题的时候,我不仅会查看服务日志的信息,还会查看当前机器所在节点的内存、cpu等监控信息。fluent-bit也是支持的,具体可以参考:
轻量级日志收集转发 | fluent-bit外部插件详解(三)
7、问题总结
1. 如上示例所示,在使用的过程中,会发现缓存路径${tag}没有被替换掉,如下所示:
drwxr-xr-x 3 root root 4096 Feb 14 17:01 logs
drwxr-xr-x 4 root root 4096 Feb 14 17:41 ${tag}
但是当缓存中的数据刷新到file中之后,file中的数据以及tag是正常替换的。个人觉得这是fluentd的一个可以接受的bug。
2. fluent-bit日志收集过程中出现如下文件被跳过问题如何处理?
2020/01/20 11:37:55] [debug] [in_tail] file=/home/logs/server/server.2019-12-17.log read=32767 lines=0
[2020/01/20 11:37:55] [debug] [in_tail] file=/home/logs/server/server.2019-12-18.log read=32767 lines=0
[2020/01/20 11:37:55] [error] [in_tail] file=/home/logs/server/server.2019-12-16.log requires a larger buffer size, lines are too long. Skipping file.
[2020/01/20 11:37:55] [error] [in_tail] file=/home/logs/server/server.2019-12-17.log requires a larger buffer size, lines are too long. Skipping file.
添加Buffer_Chunk_Size和Buffer_Chunk_Size,其中Buffer_Chunk_Size默认是32Kb,如果一行数据的长度大于这个值,可能会出现如上错误,其中Buffer_Max_Size默认情况下跟Buffer_Chunk_Size保持一致。当然你也可以配置自动跳过过长数据行。
[INPUT]
Name tail
Path /home/logs/server/*.log
Db /tmp/ng.db
Db.sync Full
Tag nginx-log
Buffer_Chunk_Size 320KB
Buffer_Max_Size 520KB
3. 生成如下所示大量日志文件,而我只想每天生成一个文件。如何配置?
# append false
file.20140608.log_0
file.20140608.log_1
file.20140609.log_0
file.20140609.log_1
在fluentd配置文件中添加append true配置即可解决,按照指定时间生成,如下所示:
# append true
file.20140608.log
file.20140609.log
4. 如何把节点日志从各个节点转发到其中一台机器?
在服务端fluentd配置source,其中source: 数据源配置,可接受log-tail、http、tcp、udp等方式数据如下所示:
<source>
@type forward
bind "0.0.0.0"
port 24222
</source>
在fluent-bit客户端配置forward,如下所示:
[OUTPUT]
Name forward
Match *
Host 12.18.71.14
Port 24222
8、本文总结
本文主要简单介绍fluent-bit&fluentd优势以及在日志收集过程中的总结和心得。如果有用,可以关注、后台回复【pdf】获得详细文档。