• fluentd学习笔记


    转载自http://blog.csdn.net/qq_27252133/article/details/53520416

    原文https://blog.laisky.com/p/fluentd/

    最近为了做一些数据分析,把我自己服务器上所有应用的日志都通过 fluentd 转存到 mongodb 了,第一次用 fluentd,记录一些笔记。

    因为是初学,绝大部分内容来源于官方文档2,等实际线上使用一段时间后再来更新一些心得。


    一、Install

    fluent 比较烦的一点是,从 gem 安装和从 rpm、yum 安装的名字不一样,连配置文件的路径都不一样,需要记住的是:

    • 从 gem 安装的,配置文件和执行程序都叫做 fluent;
    • 从 rpm 安装的,配置文件和执行程序都叫做 td-agent。

    1、安装 fluentd

    详细可参见官方文档

    以 CentOS 为例:

    # 安装
    $ sudo curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
    
    # 启动
    $ sudo /etc/init.d/td-agent start
    

    2、安装插件

    # 从 rpm 安装的话,
    # 比如要使用下例的 mongo,需要安装
    # $ sudo td-agent-gem install fluent-plugin-mongo
    $ sudo td-agent-gem <PLUGIN_NAME>
    
    # 从 gem 安装的话
    $ sudo gem install <PLUGIN_NAME>
    

    二、简介

    fluentd 是一个日志收集系统,通过丰富的插件,可以收集来自于各种系统或应用的日志,然后根据用户定义将日志做分类处理。

    通过 fluentd,你可以非常轻易的实现像追踪日志文件并将其过滤后转存到 MongoDB 这样的操作。fluentd 可以彻底的将你从繁琐的日志处理中解放出来。

    用图来做说明的话,使用 fluentd 以前,你的系统是这样的:

    null

    使用了 fluentd 后,你的系统会成为这样:

    null

    (图片来源3


    三、配置文件

    1、路径

    分为两种情况:

    • 如果是通过 gem 安装的,那么可以通过下列命令生成和编辑配置文件
    $ sudo fluentd --setup /etc/fluent
    $ sudo vi /etc/fluent/fluent.conf
    
    • 如果是通过 RPM, Deb 或 DMG 安装的,那么配置文件在:
    $ sudo vi /etc/td-agent/td-agent.conf
    

    2、重用

    你可以在配置文件里使用 @include 来切分你的配置文件,include 支持多种写法:

    # 绝对路径
    include /path/to/config.conf
    # 相对路径
    @include conf.d/*.conf
    # 甚至 URL
    @include http://example.com/fluent.conf
    

    3、数据格式

    在配置文件里你需要为很多参数赋值,这些值必须使用 fluentd 支持的数据格式,有下列这些:

    • string:字符串,最常见的格式,详细支持语法见文档1
    • integer:整数
    • float:浮点数;
    • size 大小,仅支持整数
      • <INTEGER>k 或 <INTERGER>K
      • <INTEGER>m 或 <INTERGER>M
      • <INTEGER>g 或 <INTERGER>G
      • <INTEGER>t 或 <INTERGER>T
    • time:时间,也只支持整数;
      • <INTEGER>s 或 <INTERGER>S
      • <INTEGER>m 或 <INTERGER>M
      • <INTEGER>h 或 <INTERGER>H
      • <INTEGER>d 或 <INTERGER>D
    • array:按照 JSON array 解析;
    • hash:按照 JSON object 解析。

    四、命令

    配置文件的核心是各种命令块(directives),每一种命令都是为了完成某种处理,命令与命令之前还可以组成串联关系,以 pipline 的形式流式的处理和分发日志。

    最常见的方式就是 source 收集日志,然后由串联的 filter 做流式的处理,最后交给 match 进行分发。

    同时你还可以用 label 将任务分组,用 error 处理异常,用 system 修改运行参数。

    下面是详细的说明。

    1、source

    source 是 fluentd 的一切数据的来源,每一个 source 内都包含一个输入模块,比如原生集成的包含 http 和 forward 两个模块,分别用来接收 HTTP 请求和 TCP 请求:

    # Receive events from 24224/tcp
    # This is used by log forwarding and the fluent-cat command
    <source>
      @type forward
      port 24224
    </source>
    
    # http://this.host:9880/myapp.access?json={"event":"data"}
    <source>
      @type http
      port 9880
    </source>
    

    当然,除了这两个外,fluentd 还有大量的支持各种协议或方式的 source 插件,比如最常用的 tail 就可以帮你追踪文件。

    每一个具体的插件都包含其特有的参数,比如上例中 port 就是一个参数,当你要使用一个 source 插件的时候,注意看看有哪些参数是需要配置的,然后将其写到 source directive 内。

    source dirctive 在获取到输入后,会向 fluent 的路由抛出一个事件,这个事件包含三个要素:

    • tag
    • time
    • record

    那上例代码中的第二个 source 举例,当我们发起一个 http://this.host:9880/myapp.access?json={"event":"data"} 的请求时,这个 source 会抛出:

    # generated by http://this.host:9880/myapp.access?json={"event":"data"}
    tag: myapp.access
    time: (current time)
    record: {"event":"data"}
    

    关于如何编写一个输入插件,可以参考文档4

    2、match

    match 用来指定动作,通过 tag 匹配 source,然后执行指定的命令来分发日志,最常见的用法就是将 source 收集的日志转存到数据库。

    # http://this.host:9880/myapp.access?json={"event":"data"}
    <source>
      @type http
      port 9880
    </source>
    
    # 将标记为 myapp.access 的日志转存到文件
    <match myapp.access>
      @type file
      path /var/log/fluent/access
    </match>
    

    上例中的 myapp.access 就是 tag,tag 有好几种匹配模式:

    • *:匹配任意一个 tag;
    • **:匹配任意数量个 tag;
    • a b:匹配 a 或 b;
    • {X,Y,Z}:匹配 X, Y, Z 中的一个。

    比如我可以写成这样:

    <match a.*>
    <match **>
    <match a.{b,c}>
    <match a.* b.*>
    

    fluentd 按照 match 出现的顺序依次匹配,一旦匹配成功就不会再往下匹配,所以如果你先写了一个 match **,然后后面的所有的 match 都会被忽略。

    然后我们使用了 @type file 插件来处理事件,这个插件有一个 path 属性,用来指定输出文件。

    用法和 source 几乎一模一样,不过 source 是抛出事件,match 是接收并处理事件。你同样可以找到大量的各式各样的输出插件,也可以参考文档5自己写一个。

    3、filter

    filter 和 match 的语法几乎完全一样,但是 filter 可以串联成 pipeline,对数据进行串行处理,最终再交给 match 输出。

    # http://this.host:9880/myapp.access?json={"event":"data"}
    <source>
      @type http
      port 9880
    </source>
    
    <filter myapp.access>
      @type record_transformer
      <record>
        host_param "#{Socket.gethostname}"
      </record>
    </filter>
    
    <match myapp.access>
      @type file
      path /var/log/fluent/access
    </match>
    

    这个例子里,filter 获取数据后,调用原生的 @type record_transformer 插件,在事件的 record 里插入了新的字段 host_param,然后再交给 match 输出。

    你可以参考文档6来学习如何编写自定义的 filter。

    虽然各个插件都有各自的参数,不过 fluentd 为所有的插件都设定了一组默认的参数: - @type:指定插件类型; - @id:给插件指定一个 id; - @label:指定 label; - @log_level:指定插件接收的日志级别。

    你可以在任意插件内指定这些参数。

    4、system

    fluentd 的相关设置,可以在启动时设置,也可以在配置文件里设置,包含:

    • log_level
    • suppress_repeated_stacktrace
    • emit_error_log_interval
    • suppress_config_dump
    • without_source

    5、label

    label 用于将任务进行分组,方便复杂任务的管理。

    你可以在 source 里指定 @label @<LABEL_NAME>,这个 source 所触发的事件就会被发送给指定的 label 所包含的任务,而不会被后续的其他任务获取到。

    看个例子:

    <source>
      @type forward
    </source>
    
    <source>
      # 这个任务指定了 label 为 @SYSTEM
      # 会被发送给 <label @SYSTEM>
      # 而不会被发送给下面紧跟的 filter 和 match
      @type tail
      @label @SYSTEM
    </source>
    
    <filter access.**>
      @type record_transformer
      <record>
        # ...
      </record>
    </filter>
    <match **>
      @type elasticsearch
      # ...
    </match>
    
    <label @SYSTEM>
      # 将会接收到上面 @type tail 的 source event
      <filter var.log.middleware.**>
        @type grep
        # ...
      </filter>
      <match **>
        @type s3
        # ...
      </match>
    </label>
    

    6、error

    用来接收插件通过调用 emit_error_event API 抛出的异常,使用方法和 label 一样,通过设定 <label @ERROR> 就可以接收到相关的异常。


    五、Demo

    1、Config

    一个监听 Nginx 日志的例子:

    <source>
      @type tail
      @id nginx-access
      @label @nginx
      path /var/log/nginx/access.log
      pos_file /var/lib/fluentd/nginx-access.log.posg
      tag nginx.access
      format /^(?<remote>[^ ]*) (?<host>[^ ]*) [(?<time>[^]]*)] (?<code>[^ ]*) "(?<method>S+)(?: +(?<path>[^"]*) +S*)?" (?<size>[^ ]*)(?: "(?<referer>[^"]*)" "(?<agent>[^"]*)")?$/
      time_format %d/%b/%Y:%H:%M:%S %z
    </source>
    
    <source>
      @type tail
      @id nginx-error
      @label @nginx
      path /var/log/nginx/error.log
      pos_file /var/lib/fluentd/nginx-error.log.posg
      tag nginx.error
    
      format /^(?<time>d{4}/d{2}/d{2} d{2}:d{2}:d{2}) [(?<log_level>w+)] (?<pid>d+).(?<tid>d+): (?<message>.*)$/
    </source>
    
    <label @nginx>
      <match nginx.access>
        @type mongo
        database nginx
        collection access
        host 10.47.12.119
        port 27016
    
        time_key time
        flush_interval 10s
      </match>
      <match nginx.error>
        @type mongo
        database nginx
        collection error
        host 10.47.12.119
        port 27016
    
        time_key time
        flush_interval 10s
      </match>
    </label>
    

    为了匹配,你也需要修改 Nginx 的 log_format 为:

    log_format main '$remote_addr $host [$time_local] $status "$request" $body_bytes_sent "$http_referer" "$http_user_agent"';
    

    2、Docker

    我自己在用的一个 docker 的镜像和 docker-compose.yml

  • 相关阅读:
    NOI2021游记-记最后一段日子
    7.20 ZROI-Day7模拟赛
    7.19 ZROI-Day6模拟赛
    7.18 ZROI-Day5模拟赛
    7.17 ZROI-Day4模拟赛
    7.16 ZROI-DAY3 模拟赛
    7.15 ZROI-DAY2 模拟赛
    7.13 ZROI-DAY1赛后总结
    7.9模拟赛赛后总结
    7.7模拟赛赛后总结
  • 原文地址:https://www.cnblogs.com/fanren224/p/8457181.html
Copyright © 2020-2023  润新知