Fluentd学习笔记

转载自:https://blog.laisky.com/p/fluentd/


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


<think>我们正在讨论Fluentd的配置指南和常见问题。根据引用内容,Fluentd是一个日志收集工具,工作流程分为输入、处理和输出三个阶段。以下将结合引用内容,提供Fluentd的配置指南和常见问题解答。 ### 一、Fluentd 配置指南 Fluentd的配置主要分为三个部分:输入(source)、过滤(filter)和输出(match)。配置通常写在`fluent.conf`文件中。 #### 1. 输入配置(Source) 输入配置定义日志来源。Fluentd支持多种输入源,如文件、HTTP、syslog等。以下是一些常见配置示例: - **文件输入**(监控日志文件): ```xml <source> @type tail path /var/log/nginx/access.log # 日志文件路径 pos_file /var/log/td-agent/nginx-access.log.pos # 记录读取位置 tag nginx.access # 标签,用于后续路由 format nginx # 使用内置的nginx格式解析 </source> ``` 引用[4]中提到的Nginx日志,这里使用`format nginx`可以解析Nginx的默认日志格式。 - **HTTP输入**(接收HTTP请求中的日志): ```xml <source> @type http port 8888 # 监听端口 bind 0.0.0.0 </source> ``` - **系统日志输入**(接收syslog): ```xml <source> @type syslog port 5140 tag system </source> ``` #### 2. 过滤配置(Filter) 过滤配置用于处理日志,例如解析、添加字段、删除字段等。以下示例: - **Grok解析**(将非结构化日志解析为结构化数据): ```xml <filter nginx.access> @type parser key_name message # 要解析的字段 format /(?<remote_ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ # 正则表达式 </filter> ``` - **添加字段**(例如添加环境标签): ```xml <filter nginx.access> @type record_transformer <record> env "production" </record> </filter> ``` - **条件过滤**(例如只保留错误日志): ```xml <filter nginx.access> @type grep <regexp> key level # 日志字段 pattern ERROR # 匹配ERROR级别 </regexp> </filter> ``` #### 3. 输出配置(Match) 输出配置定义日志发送到哪里。Fluentd支持多种输出,如Elasticsearch、Loki、文件等。 - **输出到Elasticsearch**(引用[1]中提到的EFK方案): ```xml <match nginx.access> @type elasticsearch host localhost port 9200 index_name nginx-access-%Y%m%d # 按日期建立索引 logstash_format true </match> ``` - **输出到Loki**(引用[2]中的配置): ```xml <match **> @type loki url "http://loki:3100" extra_labels {"env":"production"} <buffer> flush_interval 10s flush_at_shutdown true </buffer> </match> ``` - **输出到文件**: ```xml <match nginx.access> @type file path /var/log/fluentd/nginx-access </match> ``` #### 4. 完整配置示例 以下是一个完整的Fluentd配置示例,收集Nginx访问日志并输出到Elasticsearch: ```xml # 输入:监控Nginx访问日志 <source> @type tail path /var/log/nginx/access.log pos_file /var/log/td-agent/nginx-access.log.pos tag nginx.access format nginx </source> # 过滤:添加环境标签 <filter nginx.access> @type record_transformer <record> env "production" </record> </filter> # 输出:发送到Elasticsearch <match nginx.access> @type elasticsearch host localhost port 9200 index_name nginx-access-%Y%m%d logstash_format true </match> ``` ### 二、Fluentd 常见问题 #### 1. 如何收集Kubernetes中的日志? 在Kubernetes中,通常以DaemonSet形式部署Fluentd。每个节点运行一个Fluentd实例,收集该节点上所有容器的日志。配置要点: - 使用`in_tail`插件监控`/var/log/containers/*.log`。 - 通过Kubernetes元数据插件添加Pod名称、命名空间等标签。 - 输出到Elasticsearch或Loki。 示例配置(部分): ```xml <source> @type tail path /var/log/containers/*.log pos_file /var/log/fluentd-containers.log.pos tag kubernetes.* format json time_key time time_format %Y-%m-%dT%H:%M:%S.%NZ keep_time_key true </source> <filter kubernetes.**> @type kubernetes_metadata </filter> ``` #### 2. 如何处理高错误率日志? 引用[5]中提到日志分析效率提升的方法,针对高错误率场景: - **过滤错误日志**:使用`grep`过滤器只保留错误级别日志。 ```xml <filter app.logs> @type grep <regexp> key level pattern ERROR </regexp> </filter> ``` - **计算错误率**:结合Prometheus监控,使用`fluent-plugin-prometheus`导出错误计数指标。 ```xml <filter app.logs> @type prometheus <metric> name error_count type counter desc Total error logs <labels> service ${tag} </labels> </metric> </filter> ``` 然后通过Prometheus计算错误率:$错误率 = \frac{错误计数}{总日志计数}$。 #### 3. 性能优化 - **缓冲区配置**:调整缓冲区大小和刷新间隔,避免频繁IO。 ```xml <match **> @type elasticsearch # ...其他配置... <buffer> flush_interval 10s flush_thread_count 4 chunk_limit_size 2m </buffer> </match> ``` - **多工作进程**:对于高负载场景,启用多进程。 ```xml <system> workers 4 </system> ``` #### 4. 日志丢失问题 - **启用持久化**:使用文件缓冲区,防止重启时丢失日志。 ```xml <buffer> @type file path /var/log/fluentd/buffer </buffer> ``` - **重试机制**:配置输出失败时的重试策略。 ```xml <match **> # ...输出配置... <buffer> retry_type exponential_backoff retry_timeout 60 retry_max_times 10 </buffer> </match> ``` ### 三、与监控系统集成 引用[2]和[4]提到与Loki和Prometheus的集成: - **Loki**:轻量级日志系统,适合与Grafana配合使用(配置见引用[2])。 - **Prometheus**:通过`fluent-plugin-prometheus`暴露指标,监控日志流量和错误率。 示例:监控日志处理延迟 ```xml <source> @type prometheus </source> <filter nginx.access> @type prometheus <metric> name fluentd_log_delay_seconds type gauge desc Delay between log time and processing time key delay </metric> </filter> ``` ### 注意事项 - **标签(Tag)**:Fluentd通过标签路由日志,务必正确设置。 - **时间解析**:确保日志中的时间戳被正确解析,否则影响Elasticsearch中的时序展示。 - **版本兼容**:插件版本与Fluentd核心版本需兼容。 §§相关问题§§ 1. Fluentd在Kubernetes中如何收集多行日志(如Java堆栈跟踪)? 2. 如何配置Fluentd实现日志的实时报警(例如错误日志超过阈值时触发)? 3. Fluentd与Logstash在容器环境中的性能对比? 4. 如何优化Fluentd的内存使用,避免在高负载下崩溃?</think>### Fluentd 日志收集配置指南与常见问题 Fluentd 是一款开源的日志收集器,采用"输入-处理-输出"三层架构(引用[1]),支持动态服务发现(引用[3]),适用于云原生环境。以下是核心配置指南和典型问题解决方案: --- #### 一、基础配置指南 **1. 输入配置(收件)** 定义日志来源,支持文件、HTTP、syslog 等: ```xml # 监控 Nginx 访问日志(引用[4]) <source> @type tail path /var/log/nginx/access.log pos_file /var/log/td-agent/nginx-access.log.pos tag nginx.access format nginx # 使用内置 Nginx 解析模板 </source> # 接收 Java 应用日志(引用[1]) <source> @type tcp port 5170 tag java.app format json # 解析 JSON 格式日志 </source> ``` **2. 处理配置(打包)** 结构化日志并添加元数据: ```xml # 添加 Kubernetes 元数据(引用[3]) <filter kubernetes.**> @type kubernetes_metadata </filter> # 错误日志过滤(错误率 > 5% 时告警) <filter **> @type grep <exclude> key message pattern /ERROR/ # 捕获错误日志 </exclude> </filter> ``` **3. 输出配置(送件)** 发送到存储或分析系统: ```xml # 输出到 Elasticsearch(引用[1]) <match nginx.**> @type elasticsearch host localhost port 9200 index_name nginx-%Y%m%d </match> # 输出到 Loki(引用[2]) <match **> @type loki url "http://loki:3100" extra_labels {"env":"prod"} <buffer> flush_interval 10s # 缓冲区优化 </buffer> </match> ``` --- #### 二、典型场景配置 **场景1:Kubernetes 日志收集** 通过 DaemonSet 部署,自动发现 Pod 日志: ```yaml # fluentd-daemonset.yaml 片段 volumes: - name: varlog hostPath: {path: /var/log} - name: dockercontainers hostPath: {path: /var/lib/docker/containers} ``` 配置自动添加标签(引用[3]): ```xml <filter kubernetes.**> @type record_transformer <record> pod_name ${record["kubernetes"]["pod_name"]} namespace ${record["kubernetes"]["namespace_name"]} </record> </filter> ``` **场景2:高错误率处理** 当错误率 $错误率 = \frac{ERROR\_count}{total\_logs} > 5\%$ 时: 1. **实时统计**:使用 `fluent-plugin-prometheus` 导出指标 2. **动态路由**:将错误日志定向到专用存储 ```xml <match if {record["level"] == "ERROR"}> @type kafka brokers kafka:9092 topic error_logs # 分离错误日志通道 </match> ``` **场景3:性能优化** - **缓冲区配置**:防止日志丢失(引用[2]) ```xml <buffer> @type file path /var/log/fluentd-buffer flush_thread_count 4 chunk_limit_size 10MB </buffer> ``` - **异步处理**:启用多工作进程 ```bash fluentd -c /etc/fluentd.conf --workers 4 ``` --- #### 三、常见问题解决 **问题1:日志重复收集** **原因**:Kubernetes 中容器日志被 `stdout` 和文件同时捕获 **解决**:在 DaemonSet 中排除容器 JSON 日志 ```xml <source> @type tail path /var/log/containers/*.log exclude_path ["/var/log/containers/*_kube-system_*.log"] # 排除系统容器 </source> ``` **问题2:日志格式解析失败** **原因**:多行日志(如 Java 堆栈跟踪)未正确处理 **解决**:启用 `multiline` 解析 ```xml <source> @type tail format /(?<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (?<level>\w+) (?<message>.+)/ multiline_flush_interval 5s format_firstline /^\d{4}-\d{2}-\d{2}/ # 识别新日志行起始 </source> ``` **问题3:输出目标连接超时** **解决**:配置重试机制和降级策略 ```xml <match **> @type elasticsearch ... <secondary> @type file # 降级到本地文件 path /var/log/fluentd-fallback </secondary> retry_max_times 10 retry_wait 5s </match> ``` --- #### 四、最佳实践 1. **标签策略**:使用 `tag` 精细路由日志(如 `app.order_service`) 2. **资源限制**:容器化部署时设置 CPU/Memory 限制 3. **监控集成**: - 通过 Prometheus 监控 $日志量/秒$ 和 $处理延迟$(引用[5]) - Grafana 仪表盘展示错误率 $错误率$ 趋势 4. **安全配置**: ```xml <source> @type forward <security> self_hostname fluentd-prod shared_key YOUR_SECRET_KEY # TLS 加密传输 </security> </source> ``` > **提示**:完整配置参考 [Fluentd 官方文档](https://docs.fluentd.org) 或 Grafana Loki 集成指南(引用[2])。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值