# 非K8S主机部署Filebat

## **filebeat介绍**

　　Filebeat由两个主要组成部分组成：prospector和 harvesters。这些组件一起工作来读取文件并将事件数据发送到您指定的output。

### 什么是harvesters？

harvesters负责读取单个文件的内容。harvesters逐行读取每个文件，并将内容发送到output中。

每个文件都将启动一个harvesters。harvesters负责文件的打开和关闭，这意味着harvesters运行时，文件会保持打开状态。

如果在收集过程中，即使删除了这个文件或者是对文件进行重命名，Filebeat依然会继续对这个文件进行读取，这时候将会一直占用着文件所对应的磁盘空间，直到Harvester关闭。默认情况下，Filebeat会一直保持文件的开启状态，直到超过配置的close\_inactive参数，Filebeat才会把Harvester关闭。

#### 关闭harvester会产生以下结果：&#x20;

1）如果在harvester仍在读取文件时文件被删除，则关闭文件句柄，释放底层资源。

&#x20;2）文件的采集只会在scan\_frequency过后重新开始。即当时间到达配置的scan\_frequency参数，将会重新启动为文件内容的收集

&#x20;3）如果在harvester关闭的情况下移动或移除文件，则不会继续处理文件

当需要关闭Harvester的时候，可以通过close\_\*配置项来控制

### 什么是Prospector？

　　Prospector负责管理Harvsters，并且找到所有需要进行读取的数据源。如果input type配置的是log类型，Prospector将会去配置度路径下查找所有能匹配上的文件，然后为每一个文件创建一个Harvster。每个Prospector都运行在自己的Go routine里。

　　Filebeat目前支持两种Prospector类型：log和stdin。每个Prospector类型可以在配置文件定义多个。log Prospector将会检查每一个文件是否需要启动Harvster，启动的Harvster是否还在运行，或者是该文件是否被忽略（可以通过配置 ignore\_order，进行文件忽略）。如果是在Filebeat运行过程中新创建的文件，只要在Harvster关闭后，文件大小发生了变化，新文件才会被Prospector选择到。

每个prospector都在自己的Go协程中运行。

以下示例将Filebeat配置为从与指定的匹配的所有日志文件中收集行：

```
filebeat.prospectors:
- type: log
  paths:
    - /var/log/*.log
    - /var/path2/*.log
```

Filebeat目前支持两种prospector类型：log和stdin。\
&#x20;每个Prospector类型可以在配置文件定义多个。\
&#x20;log Prospector将会检查每一个文件是否需要启动Harvster，启动的Harvster是否还在运行，或者是该文件是否被忽略（可以通过配置 ignore\_order，进行文件忽略）。\
&#x20;如果是在Filebeat运行过程中新创建的文件，只要在Harvster关闭后，文件大小发生了变化，新文件才会被Prospector选择到。

注：Filebeat prospector只能读取本地文件， 没有功能可以连接到远程主机来读取存储的文件或日志<br>

## **filebeat工作原理**　　

Filebeat可以保持每个文件的状态，并且频繁地把文件状态从注册表里更新到磁盘。这里所说的文件状态是用来记录上一次Harvster读取文件时读取到的位置，以保证能把全部的日志数据都读取出来，然后发送给output。如果在某一时刻，作为output的ElasticSearch或者Logstash变成了不可用，Filebeat将会把最后的文件读取位置保存下来，直到output重新可用的时候，快速地恢复文件数据的读取。在Filebaet运行过程中，每个Prospector的状态信息都会保存在内存里。如果Filebeat出行了重启，完成重启之后，会从注册表文件里恢复重启之前的状态信息，让FIlebeat继续从之前已知的位置开始进行数据读取。

Prospector会为每一个找到的文件保持状态信息。因为文件可以进行重命名或者是更改路径，所以文件名和路径不足以用来识别文件。对于Filebeat来说，都是通过实现存储的唯一标识符来判断文件是否之前已经被采集过。　　

如果在你的使用场景中，每天会产生大量的新文件，你将会发现Filebeat的注册表文件会变得非常大。这个时候，你可以参考（[the section called “Registry file is too large?](https://www.elastic.co/guide/en/beats/filebeat/current/faq.html#reduce-registry-size)[edit](https://github.com/elastic/beats/edit/5.1/filebeat/docs/faq.asciidoc)），来解决这个问题。

启动Filebeat时，它会启动一个或多个查找器，查看您为日志文件指定的本地路径。 对于prospector 所在的每个日志文件，prospector 启动harvester。 每个harvester都会为新内容读取单个日志文件，并将新日志数据发送到libbeat，后者将聚合事件并将聚合数据发送到您为Filebeat配置的输出。\
\
图片来源：<https://www.jianshu.com/p/6282b04fe06a>

![](https://upload-images.jianshu.io/upload_images/3763264-8c83a34f568d1a67.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/940/format/webp)

### Filebeat如何保持文件的状态？

Filebeat 保存每个文件的状态并经常将状态刷新到磁盘上的注册文件中。\
&#x20;该状态用于记住harvester正在读取的最后偏移量，并确保发送所有日志行。\
&#x20;如果输出（例如Elasticsearch或Logstash）无法访问，Filebeat会跟踪最后发送的行，并在输出再次可用时继续读取文件。\
&#x20;在Filebeat运行时，每个prospector内存中也会保存的文件状态信息，\
&#x20;当重新启动Filebeat时，将使用注册文件的数据来重建文件状态，Filebeat将每个harvester在从保存的最后偏移量继续读取。

每个prospector为它找到的每个文件保留一个状态。\
&#x20;由于文件可以被重命名或移动，因此文件名和路径不足以识别文件。\
&#x20;对于每个文件，Filebeat存储唯一标识符以检测文件是否先前已采集过。

如果您的使用案例涉及每天创建大量新文件，您可能会发现注册文件增长过大。请参阅注册表文件太大？编辑有关您可以设置以解决此问题的配置选项的详细信息。

### Filebeat如何确保至少一次交付

Filebeat保证事件至少会被传送到配置的输出一次，并且不会丢失数据。 Filebeat能够实现此行为，因为它将每个事件的传递状态存储在注册文件中。

在输出阻塞或未确认所有事件的情况下，Filebeat将继续尝试发送事件，直到接收端确认已收到。

如果Filebeat在发送事件的过程中关闭，它不会等待输出确认所有收到事件。\
&#x20;发送到输出但在Filebeat关闭前未确认的任何事件在重新启动Filebeat时会再次发送。\
&#x20;这可以确保每个事件至少发送一次，但最终会将重复事件发送到输出。\
&#x20;也可以通过设置shutdown\_timeout选项来配置Filebeat以在关闭之前等待特定时间。

注意：\
&#x20;Filebeat的至少一次交付保证包括日志轮换和删除旧文件的限制。如果将日志文件写入磁盘并且写入速度超过Filebeat可以处理的速度，或者在输出不可用时删除了文件，则可能会丢失数据。\
&#x20;在Linux上，Filebeat也可能因inode重用而跳过行。有关inode重用问题的更多详细信息，请参阅filebeat常见问题解答。

\
filebeat实践-内存占用-最大内存占用

filebeat在空载情况(没有日志可采集)下的确不会有大的内存开销,但在有大量的日志需要采集时,filebeat的内存占用是没有固定值的, 那有没有理论值呢?答案是有, 为啥这么说,看下面公式:

&#x20;                             **bytes\_each\_log \* spool\_size \* M + a\*N**

其中, **bytes\_each\_log**是单条日志大小, **spool\_size**是配置文件里配置项,  **M**是单条日志在内存里的溢价系数(>1), **N**表示采集的文件个数,a为常数.

spool\_size的默认值是2048, 好多人估计都不会配置这个项,也会因此埋下祸根(OOM):\
10MB为filebeat支持的单条日志最大长度,超过的将会被截断丢弃

![1240](http://upload-images.jianshu.io/upload_images/3257594-f67711cf8043bd6b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

假设忽略**a\*N部分的内存开销, 单条日志的内存溢价为3, 一旦出现单条日志大于50KB且有瞬间爆发量的时候, filebeat的内存占用将大于300MB,是不是有点吓人!如果出现了极端情况,单条日志>10M,即使filebeat会截断到10M那也是20GB!!是不是腿都软了!!!**

**filebeat在实际使用过程中内存>300M,甚至15GB的情况浣熊都遇到过, 内存超过300M几乎经常遇到,基本都是因为客户没有按照吩咐的去做导致的; 15GB的那次有点意外和惊喜, 客户在自己的日志文件里打了大量的二进制文件(后来知道真相的我眼泪掉下来...), 大量的二进制文件触发了10MB规则,还好吃掉15GB内存后filebeat因OOM退出了,没有带来严重的损失.**

那怎么样才能避免以上内存灾难呢?划重点了,快快拿出小本本记录:

**(1)每个日志生产环境生产的日志大小,爆发量都不一样, 要根据自己的日志特点设定合适的spool\_size值;什么叫合适,至少能避免内存>200MB的灾难;**

**(2)在不知道日志实际情况(单条大小,爆发量), 务必把spool\_size设置上,建议128或者256;**

queue.mem.events消息队列的大小，默认值是4096，这个参数在6.0以前的版本是spool-size，通过命令行，在启动时进行配置

&#x20;max\_message\_bytes 单条消息的大小, 默认值是10M&#x20;

filebeat最大的可能占用的内存是max\_message\_bytes \* queue.mem.events = 40G，考虑到这个queue是用于存储encode过的数据，raw数据也是要存储的，所以，在没有对内存进行限制的情况下，最大的内存占用情况是可以达到超过80G。

###

最后分享张实践图片:

&#x20;       单条日志为45KB, spool\_size为2048的内存开销,陡坡下是spool\_size调整为128的效果.

![1240](http://upload-images.jianshu.io/upload_images/3257594-46b39c41846657b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## **安装filebeat服务**

下载和安装key文件

```
rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
```

创建yum源文

```
[root@localhost ~]# vim /etc/yum.repos.d/elk-elasticsearch.repo
[elastic-5.x]
name=Elastic repository for 5.x packages
baseurl=https://artifacts.elastic.co/packages/5.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-m
```

开始安装

```
yum install filebeat
```

启动服务

```
systemctl start filebeat
systemctl status filebeat
```

**收集日志**

这里我们先以收集docker日志为例，简单来介绍一下filebeat的配置文件该如何编写。具体内容如下

```
[root@localhost ~]# grep "^\s*[^# \t].*$" /etc/filebeat/filebeat.yml 
filebeat.prospectors:
- input_type: log
  paths:
    - /var/lib/docker/containers/*/*.log
output.elasticsearch:
  hosts: ["192.168.58.128:9200"]
```

和我们看的一样，其实并没有太多的内容。我们采集/var/lib/docker/containers/\*/\*.log，即filebeat所在节点的所有容器的日志。输出的位置是我们ElasticSearch的服务地址，这里我们直接将log输送给ES，而不通过Logstash中转。

再启动之前，我们还需要向ES提交一个filebeat index template，以便让elasticsearch知道filebeat输出的日志数据都包含哪些属性和字段。filebeat.template.json这个文件安装完之后就有，无需自己编写，找不到的同学可以通过find查找。加载模板到elasticsearch中：

```
[root@localhost ~]# curl -XPUT 'http://192.168.58.128:9200/_template/filebeat?pretty' -d@/etc/filebeat/filebeat.template.json
{
  "acknowledged" : true
}
```

重启服务

```
systemctl restart filebeat
```

提示：如果你启动的是一个filebeat容器，需要将/var/lib/docker/containers目录挂载到该容器中；

**Kibana配置**

如果上面配置都没有问题，就可以访问Kibana，不过这里需要添加一个新的index pattern。按照manual中的要求，对于filebeat输送的日志，我们的index name or pattern应该填写为："filebeat-\*"。
