Fluentd搭建日志收集服务


Posted in Servers onSeptember 23, 2022

引言

公司需要搭建一个日志收集服务器,用于将公司的项目日志汇总到一台服务器上面,方便查看和减轻各项目服务器压力。但是由于目前资源不够充足,所以放弃使用ELK、EFK。最后在调研尝试过Linux自带的Syslog和fluentd之后,Linux自带的Syslog虽然更简单,但是汇总的数据中会有乱码的情况(怀疑是Appender问题),并且将日志信息组合成Json格式比较麻烦,因此选择使用fluentd来做日志收集。

1. 搭建环境准备工作

选用fluentd来做日志收集选择使用源码来进行安装,并且需要安装一些依赖的插件,如Ruby等,下面依次介绍需要安装的组件。

1.1 安装ruby

下载ruby压缩包 ruby-2.6.5.tar.gz,版本:2.6.5,并解压

tar -zxvf ruby-2.6.5.tar.gz
cd ruby-2.6.5

安装ruby,安装需要gcc

yum install -y gcc
./configure prefix=/export/source/ruby
make && make install

安装完成后修改系统配置文件 /etc/profile,在最后添加ruby目录并加到path中

export RUBY_HOME=/export/source/ruby
export PATH=$PATH:$JAVA_HOME/bin:$RUBY_HOME/bin

验证是否安装成功

[root@localhost ruby-2.6.5]# ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]

显示ruby版本号,安装成功

1.2 获取fluentd源码

从github上拉取fluentd源码,github地址:fluentd

git clone https://github.com/fluent/fluentd.git
cd fluentd

1.3 修改gem源

先查看当前默认源

gem source
*** CURRENT SOURCES ***
https://rubygems.org/

移除默认源

gem sources -r https://rubygems.org/

添加源,目前可用的有ruby-china的源,添加ruby-china源

gem sources -a https://gems.ruby-china.com
https://gems.ruby-china.com added to sources
# 查看当前源
gem source
*** CURRENT SOURCES ***
https://gems.ruby-china.com

更新缓存

gem sources -u

1.4 安装Bundle

gem install bundler

等待提示安装成功

1.5 构建fluentd

进入fluentd文件夹后,构建项目

[root@localhost fluentd]# bundle install
Fetching gem...
...
Bundle complete! 11 Gemfile dependencies, 37 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
[root@localhost fluentd]# bundle exec rake build
fluentd 1.7.3 built to pkg/fluentd-1.7.3.gem.
[root@localhost fluentd]# gem install pkg/fluentd-1.7.3.gem
Successfully installed fluentd-1.7.3
Parsing documentation for fluentd-1.7.3
Installing ri documentation for fluentd-1.7.3
Done installing documentation for fluentd after 3 seconds
1 gem installed

安装完成

1.6 运行fluentd

[root@localhost fluentd]# fluentd --setup ./fluent
[root@localhost fluentd]# fluentd -c ./fluent/fluent.conf -vv &

最后在控制台显示fluentd读取的配置文件信息并且打印相关日志。至此日志收集服务器所需要的fluentd已经搭建完成,接下来就是配置fluentd以完成日记收集功能。

2. 安装过程遇到的问题

2.1 安装bundler没有zlib包

ERROR: Loading command: install (LoadError)
 cannot load such file -- zlib
ERROR: While executing gem ... (NoMethodError)
    undefined method `invoke_with_build_args' for nil:NilClass

解决方案 安装zlib-devel

yum -y install zlib-devel

进入ruby源码文件夹,安装ruby自身提供的zlib包ruby-2.5.1/ext/zlib

cd ruby-2.6.5/ext/zlib
ruby ./extconf.rb
make
make install

在make时会报错

make: *** No rule to make target `/include/ruby.h', needed by `zlib.o'.  Stop.

修改目录中Makefile文件

zlib.o: $(top_srcdir)/include/ruby.h

改成

zlib.o: ../../include/ruby.h

到这里就可以make成功了。

2.2 没有openssl

错误描述:cannot load such file -- openssl

/export/source/ruby/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- openssl (LoadError)
	29: from /export/source/ruby/bin/gem:21:in `<main>'
	28: from /export/source/ruby/lib/ruby/2.6.0/rubygems/gem_runner.rb:59:in `run'
	27: from /export/source/ruby/lib/ruby/2.6.0/rubygems/command_manager.rb:148:in `run'
	26: from /export/source/ruby/lib/ruby/2.6.0/rubygems/command_manager.rb:178:in `process_args'
...
/export/source/ruby/lib/ruby/2.6.0/rubygems/request.rb:84:in `rescue in configure_connection_for_https': Unable to require openssl, install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources (Gem::Exception)
	22: from /export/source/ruby/bin/gem:21:in `<main>'
	21: from /export/source/ruby/lib/ruby/2.6.0/rubygems/gem_runner.rb:59:in `run'
	20: from /export/source/ruby/lib/ruby/2.6.0/rubygems/command_manager.rb:148:in `run'
	19: from /export/source/ruby/lib/ruby/2.6.0/rubygems/command_manager.rb:178:in `process_args'
	...

解决方案

yum install openssl-devel -y

在ruby自身提供的额外文件夹中ruby-2.6.5/ext/openssl,执行ruby ./extconf.rb,再make

ruby ./extconf.rb
make
make install

make时出错

make: *** No rule to make target `/include/ruby.h', needed by `ossl.o'.  Stop.

修改Makefile文件,在文件顶部添加top_srcdir = ../..

3. 完成需求及修改配置

在上一节中完成了在日志服务器上单间fluentd,该日志收集服务器有五个需求,通过修改fluentd等配置文件来完成相关的需求。

需求1 日志存放路径应用+日期划分

修改配置文件,在 模块中添加path属性,如果需要将匹配相同的tag输出到不同文件中则需要将 的@type设置为copy,然后再 块中添加 块并在 中添加path属性。

在path属性中可以读取过滤的tag,tag的格式为logback配置文件中的.,因此可以将应用名设定在logback配置文件中,然后再fluentd.conf中进行读取。在path中通过${tag}占位符读取客户端发送的tag,tag属性可以根据.切分为数组,例如tag为test.demo时,tag[0]表示test,tag[1]表示demo。对于时间的配置可直接在path路径中设置,并且在buffer块加上time及timekey配置,配置文件如下:

<store>
    @type file
    @id   demo
    path         /data/log/${tag[3]}/${tag[4]}/%Y-%m-%d/${tag[4]}
    symlink_path /data/tmp/${tag[3]}_${tag[4]}_data.log
    append      false
    time_slice_wait   10m
    time_slice_format %Y%m%d
    <buffer tag, time>
      flush_mode                interval
      flush_interval            30s
      chunk_limit_size          5MB
      timekey                   1d
    </buffer>
  </store>

最后得到的目录如下

├── [  21]  dab
│   └── [  56]  logdemo
│       ├── [4.0K]  2019-10-14
│       │   ├── [3.2M]  logdemo.20191014_0.log
│       │   ├── [3.2M]  logdemo.20191014_1.log
│       │   ├── [3.5M]  logdemo.20191014_2.log
│       │   ├── [3.9M]  logdemo.20191014_3.log
│       │   ├── [4.3M]  logdemo.20191014_4.log
│       │   ├── [4.2M]  logdemo.20191014_5.log
├── [  27]  sms
│   └── [  62]  opapplication
│       ├── [ 114]  2019-10-14
│       │   ├── [2.5M]  opapplication.20191014_0.log
│       │   ├── [4.3M]  opapplication.20191014_1.log

需求2 存放日志文件按文件大小进行切分

修改配置文件,在match块中添加buffer块配置,配置内容如下

<match level.com.zhy.**>
    @type file
    @id   demo
    path         /data/log/${tag[3]}/${tag[4]}/%Y-%m-%d/${tag[5]}/${tag[4]}_${tag[5]}
    symlink_path /data/tmp/${tag[3]}_${tag[4]}_data.log
    # 不追加日志文件
    append      false
    <buffer tag, time>
      # 刷新模式
      flush_mode                interval    
      # 刷新周期
      flush_interval            10s
      # 块大小限制
      chunk_limit_size          5MB
      timekey                   1d
    </buffer>
  </store>
</match>

将buffer刷新模式修改为interval按固定时间间隔刷新,并且设置刷新的周期以及不追加文件。这样当buffer有内容时,每过10s将日志文件保存一次,或者当buffer块达到5MB就立即存一次,保证每个日志文件的大小都保证在5MB以内。生成的日志目录结构如下:

.
├── [  21]  dab
│   └── [  56]  logdemo
│       ├── [4.0K]  2019-10-14
│       │   ├── [3.2M]  logdemo.20191014_0.log
│       │   ├── [1.7M]  logdemo.20191014_10.log
│       │   ├── [1.9M]  logdemo.20191014_11.log
│       │   ├── [3.2M]  logdemo.20191014_1.log
│       │   ├── [3.5M]  logdemo.20191014_2.log
│       │   ├── [3.9M]  logdemo.20191014_3.log
│       │   ├── [4.3M]  logdemo.20191014_4.log
│       │   ├── [4.2M]  logdemo.20191014_5.log
│       │   ├── [4.5M]  logdemo.20191014_6.log
│       │   ├── [4.8M]  logdemo.20191014_7.log
│       │   ├── [4.8M]  logdemo.20191014_8.log

需求3 按照日志等级划分日志

为方便查看各类等级日志的情况,需要在目录中添加日志等级并将相应的日志放入。在不修改客户端tag情况下,在fluentd服务端重新生成tag以包含日志等级,此时需要 rewrite_tag_filter 插件来完成重置tag。在使用插件前需要安装该插件

[root@localhost fluentd]$ fluent-gem install fluent-plugin-rewrite-tag-filter
Fetching fluent-plugin-rewrite-tag-filter-2.2.0.gem
Fetching fluent-config-regexp-type-1.0.0.gem
Successfully installed fluent-config-regexp-type-1.0.0
Successfully installed fluent-plugin-rewrite-tag-filter-2.2.0
Parsing documentation for fluent-config-regexp-type-1.0.0
Installing ri documentation for fluent-config-regexp-type-1.0.0
Parsing documentation for fluent-plugin-rewrite-tag-filter-2.2.0
Installing ri documentation for fluent-plugin-rewrite-tag-filter-2.2.0
Done installing documentation for fluent-config-regexp-type, fluent-plugin-rewrite-tag-filter after 0 seconds
2 gems installed

然后在fluent.conf配置文件中配置

<match com.zhy.**>
  @type rewrite_tag_filter
  <rule>
    key msg
    pattern ^\[(\w+)\]
    tag level.${tag}.$1
  </rule>
</match>

原来的输入日志格式如下

2019-10-14 14:44:09.000000000 +0800 com.zhy.sms.opapplication: {"msg":"[ERROR] 这是error日志...error\r\n","level":"ERROR","logger":"com.sk.controller.LogController","thread":"pool-3-thread-397","message":"这是error日志...error"}

在日志信息中msg、level对应的值都包含日志等级,因此可以从键msg、level中选出日志等级来组成新的tag,这里选则提取msg对应的value中的日志等级。配置文件中的pattern属性所写正则表达式就是用来匹配msg中[]中的值的,然后再tag上将取出来的日志等级通过$1放到原来tag的最后面。

注意:如果match上的匹配规则和修改后的tag能够对应,则会一直进行匹配,从而导致修改tag失败,如下

<match com.zhy.**>
  @type rewrite_tag_filter
  <rule>
    key msg
    pattern ^\[(\w+)\]
    tag ${tag}.$1
  </rule>
</match>

此时修改后的tag仍然是以com.zhy开头,所以会导致修改失败,所以在新的tag前加上level前缀,level可自定义

<match com.zhy.**>
  @type rewrite_tag_filter
  <rule>
    key msg
    pattern ^\[(\w+)\]
    tag level.${tag}.$1
  </rule>
</match>

需求4 将目录通过nginx映射出去

在nginx配置文件中增加server配置,在server中添加root属性,设置映射到服务器根目录下的/data目录中,location属性分为两步第一步开启文件浏览,第二步设置在浏览器文本格式显示文件内容

location     /log {
    autoindex  on;
}

通过autoindex来开启文件浏览功能,配置客户端浏览路径为/log

location    ^/log/.*\.log$  {
    add_header Content-Type  text/plain;
}

首先通过正则表达式匹配浏览路径,匹配规则以/log开头并且以.log结尾的文件,然后设置Content-Type为text/plain,在浏览器便可直接浏览日志内容,如果不设置将会弹出下载窗口进行下载,并且需要清理浏览器的缓存

server {
        listen       8002;
        autoindex_exact_size off;
        charset utf-8;
        autoindex_localtime on;
        root         /data;
        location     /log {
                autoindex       on;
        }
        location    ^/log/.*\.log$  {
                add_header Content-Type         text/plain;
        }
    }

需求5 生成一个定大小的日志文件,并能够即时查看日志

需求是希望能够在项目文件夹下生成一个日志文件,与前面的日志文件不同的是该日志是显示当前日志内容,并且大小固定。由于fluentd的append生成的文件虽然能够追加到一个文件中,但是不能够固定大小,日志大小会无限膨胀。通过查阅资料,最后选择使用linux自带的日志转存工具 logrotate 来实现这需求。

由于目前linux都会自带logrotate,所以不需要安装,比较便捷。并且logrotate在github的更新还是比较活跃的。github地址:logrotate

1.修改配置

在使用logrotate之前,先修改fluentd配置,使其在每个项目中生成一个对应的即时日志文件。在 match 块中添加一个 store 块。

<store>
    @type file
    @id   ImmediateLog
    path         /data/log/${tag[3]}/${tag[4]}/${tag[4]}_immediate
    append    true
    <buffer tag>
        path                      /data/tmp/${tag[3]}/${tag[4]}/${tag[4]}_immediate
        flush_mode                interval
        flush_interval            5s
    </buffer>
</store>

配置中主要是在对应项目文件夹下生成一个名为 appname_immediate.log 的日志文件,并且该日志文件用append追加内容,选择以5s为周期性刷新,由于是即时日志文件,所以刷新频率高。之所以不用immediate模式是因为考虑的服务器负载,如果立即刷新的话可能会造成负载较高,所以选用延迟几秒来追加日志内容

然后修改logrotate配置文件,器配置文件在 /etc/logrotate.conf 中,但是在该配置文件中不方便管理,因此可以自己写一个配置文件,保存到 /etc/logrotate.d 目录中,在该目录中已经保存有几个自带的logrotate配置。这里我们新建一个配置文件,命名 applog ,并在文件中添加配置项:

/data/log/*/*/*_immediate.log {
     daily             # 每天运行
     rotate 3          # 转存文件最多三个
     size 10M          # 当待转存文件大于10MB时才转存
     compress          # 压缩转存文件
     copytruncate      # 复制转存文件并且清空原文件
 }

logrotate配置文件中第一行表示在配置转存文件的路径,这里转存的是在/data/log目录下的所有以_immediate.log结尾的文件,路径配置可以使用通配符。其余配置见注释,这里主要的作用时每天转存一次日志文件,当文件大小超过10MB时转存,并且进行压缩,转存文件最多存在3个。其余配置参考官网:logrotate配置详解

在完成配置后,可以通过命令查看配置文件是否正确

# -d:debug模式,校验配置文件
logrotate -d /etc/logrotate.conf

运行后会在控制台显示所读取配置文件、转存信息等。如果想看实际效果,将命令中的-d变为-f强制执行。运行-f命令后会在应用对应的immediate.log目录中生成一个以日期结尾的压缩文件,并且原来的日志文件被清空。这时logrotate配置完成。

2.logrotate执行时间

logrotate是通过cron定时任务执行的,查看cron配置文件可以看到定时任务的执行时间,CentOS使用的是anacron,配置文件在 /etc/anacrontab 中

# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

配置文件中 START_HOURS_RANGE=3-22 表示定时任务开始时间,默认是在3点到22点之间, RANDOM_DELAY=45 表示启动任务后的最大随机延迟时间,默认最大延迟45分钟执行。最后三行是对于不同的定时任务配置,在cron.daily行就是定义每天的定时任务执行方式,每天一次,并且强制延迟5分钟执行,所以默认配置一般会在凌晨三点过执行。

在这里修改START_HOURS_RANGE、RANDOM_DELAY以及cron.daily的delay,可以自定义每日定时任务的执行时间。

4. 遇到的问题

问题描述

在所有都配置好后,使用 logrotate -d 不报错,手动执行 logrotate -f 也能够生成转存文件,但是转存文件却不能按照配置每天自动生成。

查看cron日志(cron日志地址:/var/log/cron)发现每天的定时任务都会执行

Oct 16 3:00:47 localhost anacron[24471]: Job `cron.daily' started
Oct 16 3:00:47 localhost run-parts(/etc/cron.daily)[24475]: starting logrotate
Oct 16 3:00:50 localhost run-parts(/etc/cron.daily)[24484]: finished logrotate
Oct 16 3:00:50 localhost run-parts(/etc/cron.daily)[24475]: starting man-db.cron
Oct 16 3:00:51 localhost run-parts(/etc/cron.daily)[24495]: finished man-db.cron
Oct 16 3:00:51 localhost anacron[24471]: Job `cron.daily' terminated

但是没有生成转存文件。

解决方案

出现该问题是由于selinux的安全策略导致的,只需要给转存日志所在的目录增加安全上下文 var_log_t 即可

chcon -Rv --type=var_log_t /data/log

执行上面命令会对/data/log目录中的所有文件添加安全上下文。之后再观察转存文件便能够成功生成。

以上就是Fluentd搭建日志收集服务的详细内容,更多关于Fluentd 日志收集的资料请关注三水点靠木其它相关文章!

Servers 相关文章推荐
nginx对http请求处理的各个阶段详析
Mar 31 Servers
利用Nginx代理如何解决前端跨域问题详析
Apr 02 Servers
nginx配置虚拟主机的详细步骤
Jul 21 Servers
Apache Hudi的多版本清理服务彻底讲解
Mar 31 Servers
Kubernetes中Deployment的升级与回滚
Apr 01 Servers
Nginx配置根据url参数重定向
Apr 11 Servers
Nginx限流和黑名单配置
May 20 Servers
nginx rewrite功能使用场景分析
May 30 Servers
Ubuntu安装Mysql+启用远程连接的完整过程
Jun 21 Servers
nginx之queue的具体使用
Jun 28 Servers
nginx代理实现静态资源访问的示例代码
Jul 07 Servers
Apache SkyWalking 监控 MySQL Server 实战解析
Sep 23 Servers
Flink 侧流输出源码示例解析
Sep 23 #Servers
修改Nginx配置返回指定content-type的方法
Sep 23 #Servers
Nginx如何配置多个服务域名解析共用80端口详解
Sep 23 #Servers
VMware虚拟机安装 Windows Server 2022的详细图文教程
zabbix如何添加监控主机和自定义监控项
Aug 14 #Servers
教你使用RustDesk 搭建一个自己的远程桌面中继服务器
Aug 14 #Servers
nginx配置指令之server_name的具体使用
Aug 14 #Servers
You might like
PHP+JS+rsa数据加密传输实现代码
2011/03/23 PHP
有道搜索和IP138的IP的API接口(PHP应用)
2012/11/29 PHP
php时区转换转换函数
2014/01/07 PHP
php基于PDO实现功能强大的MYSQL封装类实例
2017/02/27 PHP
实例讲解YII2中多表关联的使用方法
2017/07/21 PHP
jquery中获得$.ajax()事件返回的值并添加事件的方法
2010/04/15 Javascript
使用js修改客户端注册表的方法
2013/08/09 Javascript
jquery动态分页效果堪比时光网
2014/09/25 Javascript
jQuery选择器源码解读(八):addCombinator函数
2015/03/31 Javascript
JS中的Replace方法使用经验分享
2015/05/20 Javascript
jquery实现列表上下移动功能
2016/02/25 Javascript
jQuery实现背景滑动菜单
2016/12/02 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
2018/05/18 Javascript
详解封装基础的angular4的request请求方法
2018/06/05 Javascript
javascript中的this作用域详解
2019/07/15 Javascript
vue实现行列转换的一种方法
2019/08/06 Javascript
vue调用语音播放的方法
2019/09/27 Javascript
vuex存取值和映射函数使用说明
2020/07/24 Javascript
Python序列之list和tuple常用方法以及注意事项
2015/01/09 Python
Python切片知识解析
2016/03/06 Python
python:socket传输大文件示例
2017/01/18 Python
Python 实现数据库更新脚本的生成方法
2017/07/09 Python
Python 实现在文件中的每一行添加一个逗号
2018/04/29 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
python单例模式实例解析
2018/08/28 Python
Django Sitemap 站点地图的实现方法
2019/04/29 Python
Python面向对象特殊属性及方法解析
2020/09/16 Python
eBay比利时购物网站:eBay.be
2019/08/09 全球购物
应届生自我鉴定
2013/12/11 职场文书
车队司机自我鉴定
2014/03/02 职场文书
聘用意向书
2014/07/29 职场文书
六查六看心得体会
2014/10/14 职场文书
担保书格式范文
2015/09/22 职场文书
幼儿教师继续教育培训心得体会
2016/01/19 职场文书
【海涛解说】pis亲自推荐,其实你从来不会玩NW
2022/04/01 DOTA
吉利入股戴姆勒后smart“长大了”
2022/04/21 数码科技