fluentd收集docker容器并存为es索引
前言:
这几天研究了下fluentd,不得不说,整体上来说还是蛮复杂的,尤其配置文件难以找到一个标准的参考对象,所使用的功能需要不同的插件来支持,功能多样化的同时也意味着配置的复杂,多次尝试之后,算摸索到了一个可用的docker容器日志收集方案。接下来会简单介绍下所应用的配置,启动方式,以及找资料中碰到的疑惑问题。
td-agent与fluentd是什么关系:
td-agent是Fluentd的稳定发行版本,它的出现是因为Fluentd不易于安装。本质上td-agent和Fluentd是一个东西。td-agent一般是作为应用直接安装在linux系统上的。我只了解到这里,因为容器化的趋势,学习它是没有价值的,有兴趣的话可以研究下。
td-agent如何安装
适于于Redhat&Centos的安装方式:
$ curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh
fluentd的插件问题:
fluentd中的功能大都需要插件来支持,即配置文件中每个配置,这意味着你想使用的功能都需要安装额外的插件,你不能直接使用docker search来拉fluentd镜像直接使用,需要对镜像进行再制作。
你可以选择不同的日志收集方式,也可以选择将fluentd收集到的日志存储到不同的存储组件中,当然,这些功能都需要安装对应的组件的插件才能够在配置文件中选择,我使用的是容器化安装的fluentd,将本机容器日志存储在es索引中。最终用kibana来展示。
日志收集方案演示:
启动fluentd容器:
首先,得拉取镜像,我选择的是下面这个镜像 docker pull docker.io/fluent/fluentd 当然,配置文件需要手动修改,所以,启动命令如下: docker run -d -p 24224:24224 -v /data/fluent.conf:/fluentd/etc/fluent.conf --name="fluentd" docker.io/fluent/fluentd
fluent.conf是fluentd的配置文件,我的配方/data/fluent.conf是这样的:
<source> type forward #source表示日志源来自转发,forward与http是默认安装的组件,不需要额外的插件支持。 port 24224 #在24224端口启动forward接收转发 bind 0.0.0.0 #允许接收任意IP的转发 </source> <match *> @type copy #match模块表示日志再转发 <store> @type elasticsearch #转发日志到es,这需要安装es的插件 hosts 192.168.74.182:9200 #es的配置信息 logstash_format true #启动转发 logstash_prefix my-test #转发到es的索引名称 logstash_dateformat %Y.%m #按月来划分索引,可以删除无用数据 flush_interval 5s #每5s刷新一次 </store> <store> @type stdout #搜索到数据后立即转发到es </store> </match>
ok,上面的配置文件是我测试多次,得到的可用文件
当然,你需要进入容器执行安装es插件的命令:
docker exec -it fluentd bash gem install fluent-plugin-elasticsearch 当然,安装完了我们要重启下容器 docker restart fluentd
到这一步,我们fluentd配置就告一段落了,es的安装启动可以参考下我之前的博客
启动nginx测试容器:
docker run -d -p 80:80 --log-driver=fluentd --name="nginx" docker.io/nginx
nginx的启动就没有那么多的顾忌了,加上--log-driver=fluentd参数即可,当然,最好加上--log-opt fluentd-async-connect,因为前一个参数使nginx容器与fluentd容器绑定了。fluentd挂掉的话,nginx容器也会挂掉,这当然不是我们所希望的,所以,生产环境还是在容器启动时加上asyc参数。最后,需要先启动es,再启动fluentd,再启动nginx,因为它们是互相依赖的关系。
验证:
查看fluentd的日志,我们就可以看到fluentd所收集到的日志:
<source> type forward port 24224 bind "0.0.0.0" </source> <match *> @type copy <store> @type "elasticsearch" hosts "192.168.74.182:9200" logstash_format true logstash_prefix "my-test" logstash_dateformat "%Y.%m" flush_interval 5s <buffer> flush_interval 5s </buffer> </store> <store> @type "stdout" </store> </match> </ROOT> 2020-11-13 08:11:20 +0000 [info]: starting fluentd-1.3.2 pid=8 ruby="2.5.2" 2020-11-13 08:11:20 +0000 [info]: spawn command to main: cmdline=["/usr/bin/ruby", "-Eascii-8bit:ascii-8bit", "/usr/bin/fluentd", "-c", "/fluentd/etc/fluent.conf", "-p", "/fluentd/plugins", "--under-supervisor"] 2020-11-13 08:11:21 +0000 [info]: gem 'fluent-plugin-elasticsearch' version '4.2.2' 2020-11-13 08:11:21 +0000 [info]: gem 'fluentd' version '1.3.2' 2020-11-13 08:11:21 +0000 [info]: adding match pattern="*" type="copy" 2020-11-13 08:11:21 +0000 [info]: #0 'flush_interval' is configured at out side of <buffer>. 'flush_mode' is set to 'interval' to keep existing behaviour 2020-11-13 08:11:21 +0000 [warn]: #0 Detected ES 7.x: `_doc` will be used as the document `_type`. 2020-11-13 08:11:21 +0000 [warn]: #0 'type' is deprecated parameter name. use '@type' instead. 2020-11-13 08:11:21 +0000 [info]: adding source type="forward" 2020-11-13 08:11:21 +0000 [info]: #0 starting fluentd worker pid=19 ppid=8 worker=0 2020-11-13 08:11:21 +0000 [info]: #0 listening port port=24224 bind="0.0.0.0" 2020-11-13 08:11:21 +0000 [info]: #0 fluentd worker is now running worker=0 2020-11-13 08:11:26.000000000 +0000 67b9cf765a25: {"log":"192.168.74.1 - - [13/Nov/2020:08:11:26 +0000] \"GET / HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36\" \"-\"","container_id":"67b9cf765a25505510613f77c400f107a6d4bcd3039e3831460fad28bd467c0b","container_name":"/nginx","source":"stdout"}
日志中包含的信息有,fluentd的配置文件的信息,fluentd的版本,ruby版本,es插件等等的版本信息,最后一个就是收集到的日志信息。
查看es的索引:
[root@my yibin]# curl http://192.168.74.182:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open log-audit-2020.11 Hi1qLtXGQbm2NdNjK_gXTw 1 1 481 0 210.4kb 210.4kb green open .kibana_task_manager_1 eFqwbcB2RTq7LZKatgHF4g 1 0 2 0 21.7kb 21.7kb yellow open log-secure-2020.11 DEDAhB6dS5uo50jeY2Tu4A 1 1 2 0 12.4kb 12.4kb yellow open my-test-2020.11 HNsZBogvQMiwWwh3uj6DBA 1 1 38 0 20.4kb 20.4kb green open .apm-agent-configuration 7AsnoJtoT3WrB7p26BP14w 1 0 0 0 283b 283b green open .kibana_1 TmqoMtVJTOOgtG4Cl3L0kA 1 0 10 3 30.2kb 30.2kb
可以看到我们my-test的索引成功生成了,最后我们再将它添加到kibana中进行整理与展示就行了。
当然,仅仅是一个容器的话,这样是没有问题的,如果是多个容器,我们就需要将他们区分,在开始运行docker容器时,我们添加了参数--log-driver fluentd
来指定容器日志输出到fluentd进行转发,但收集到的日志没有明显能够说明该条日志来自于哪个app的标签。这样的需求可以通过在启动容器时添加--log-opt tag=thrall
参数使得该容器输出的日志都带上tag=thrall
的标签。这样我们就可以知道该条日志来源于哪个app。
<match *thrall*> #匹配tag中包含thrall的日志 @type elasticsearch host localhost port 9200 include_tag_key #会输出所有tag到每一条日志记录中 include_tag_key true tag_key log_name logstash_format true logstash_prefix thrall #我们可以将每个容器日志起单独的名字,也可以将他们放到一个索引里,最后使用kibana展示中的过滤功能来完成内容的分隔 </match>