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>

参考链接:

使用fluentd管理docker日志

原文地址:https://www.cnblogs.com/xiaoyuxixi/p/13949750.html