ES系列十8、FileBeat發送日誌到logstash、ES、多個output過濾配置

1、FileBeat基本概念

簡單概述html

  最近在瞭解ELK作日誌採集相關的內容,這篇文章主要講解經過filebeat來實現日誌的收集。日誌採集的工具備不少種,如fluentd, flume, logstash,betas等等。首先要知道爲何要使用filebeat呢?由於logstash是jvm跑的,資源消耗比較大,啓動一個logstash就須要消耗500M左右的內存,而filebeat只須要10來M內存資源。經常使用的ELK日誌採集方案中,大部分的作法就是將全部節點的日誌內容經過filebeat送到kafka消息隊列,而後使用logstash集羣讀取消息隊列內容,根據配置文件進行過濾。而後將過濾以後的文件輸送到elasticsearch中,經過kibana去展現。java

filebeat介紹linux

  Filebeat由兩個主要組成部分組成:prospector和 harvesters。這些組件一塊兒工做來讀取文件並將事件數據發送到您指定的output。git

什麼是harvesters?
  harvesters負責讀取單個文件的內容。harvesters逐行讀取每一個文件,並將內容發送到output中。每一個文件都將啓動一個harvesters。harvesters負責文件的打開和關閉,這意味着harvesters運行時,文件會保持打開狀態。若是在收集過程當中,即便刪除了這個文件或者是對文件進行重命名,Filebeat依然會繼續對這個文件進行讀取,這時候將會一直佔用着文件所對應的磁盤空間,直到Harvester關閉。默認狀況下,Filebeat會一直保持文件的開啓狀態,直到超過配置的close_inactive參數,Filebeat纔會把Harvester關閉。github

關閉Harvesters會帶來的影響:
  file Handler將會被關閉,若是在Harvester關閉以前,讀取的文件已經被刪除或者重命名,這時候會釋放以前被佔用的磁盤資源。
  當時間到達配置的scan_frequency參數,將會從新啓動爲文件內容的收集。
  若是在Havester關閉之後,移動或者刪除了文件,Havester再次啓動時,將會沒法收集文件數據。
  當須要關閉Harvester的時候,能夠經過close_*配置項來控制。json

什麼是Prospector?vim

  Prospector負責管理Harvsters,而且找到全部須要進行讀取的數據源。若是input type配置的是log類型,Prospector將會去配置度路徑下查找全部能匹配上的文件,而後爲每個文件建立一個Harvster。每一個Prospector都運行在本身的Go routine裏。ruby

  Filebeat目前支持兩種Prospector類型:log和stdin。每一個Prospector類型能夠在配置文件定義多個。log Prospector將會檢查每個文件是否須要啓動Harvster,啓動的Harvster是否還在運行,或者是該文件是否被忽略(能夠經過配置 ignore_order,進行文件忽略)。若是是在Filebeat運行過程當中新建立的文件,只要在Harvster關閉後,文件大小發生了變化,新文件纔會被Prospector選擇到。app

filebeat工做原理jvm

  Filebeat能夠保持每一個文件的狀態,而且頻繁地把文件狀態從註冊表裏更新到磁盤。這裏所說的文件狀態是用來記錄上一次Harvster讀取文件時讀取到的位置,以保證能把所有的日誌數據都讀取出來,而後發送給output。若是在某一時刻,做爲output的ElasticSearch或者Logstash變成了不可用,Filebeat將會把最後的文件讀取位置保存下來,直到output從新可用的時候,快速地恢復文件數據的讀取。在Filebaet運行過程當中,每一個Prospector的狀態信息都會保存在內存裏。若是Filebeat出行了重啓,完成重啓以後,會從註冊表文件裏恢復重啓以前的狀態信息,讓FIlebeat繼續從以前已知的位置開始進行數據讀取。
Prospector會爲每個找到的文件保持狀態信息。由於文件能夠進行重命名或者是更改路徑,因此文件名和路徑不足以用來識別文件。對於Filebeat來講,都是經過實現存儲的惟一標識符來判斷文件是否以前已經被採集過。
  若是在你的使用場景中,天天會產生大量的新文件,你將會發現Filebeat的註冊表文件會變得很是大。這個時候,你能夠參考( the section called 「Registry file is too large? edit),來解決這個問題。

2、下載FileBeat安裝包

wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.1-linux-x86_64.tar.gz

3、FileBeat發送日誌到ES

一、解壓文件

tar -zxvf filebeat-6.3.1-linux-x86_64.tar.gz

二、編輯filebeat.yml

vim filebeat.yml

按照要求修改輸入和輸出部分爲(紅色):

filebeat.inputs:
# Each - is an input. Most options can be set at the input level, so
# you can use different inputs for various configurations.
# Below are the input specific configurations.
- type: log
  # Change to true to enable this input configuration.
  enabled: true
  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    /home/log/*.log
    #- c:\programdata\elasticsearch\logs\*
。。。
 
#============================= Filebeat modules ===============================
filebeat.config.modules:
  # Glob pattern for configuration loading
  path: ${path.config}/modules.d/*.yml
  # Set to true to enable config reloading
  reload.enabled: true
 
。。。
 
#============================= Filebeat modules ===============================
filebeat.config.modules:
  # Glob pattern for configuration loading
  path: ${path.config}/modules.d/*.yml
  # Set to true to enable config reloading
  reload.enabled: true
 
 
output.elasticsearch:
  # Array of hosts to connect to.
  hosts: ["localhost:9200"]
 

三、啓動

./filebeat -e -c filebeat.yml -d "Publish"

四、驗證

上傳日誌到文件到指定目錄

日誌內容:

{"@timestamp":"2018-09-20T01:21:02.363+08:00","@version":1,"message":"測試日誌修改索引看看","logger_name":"com.example.demo.DemoApplicationTests","thread_name":"main","level":"INFO","level_value":20000,"appName":"test-name","appname":"test-name"}
{"@timestamp":"2018-09-20T01:21:02.364+08:00","@version":1,"message":"查詢全部學生,pageNo1,pageSize1","logger_name":"com.example.service.StudentService","thread_name":"main","level":"INFO","level_value":20000,"appName":"test-name","appname":"test-name"}
{"@timestamp":"2018-09-20T01:21:02.622+08:00","@version":1,"message":"Student(id=1, name=小明, classname=112, age=21, telphone=2147483647, nickName=null)","logger_name":"com.example.demo.DemoApplicationTests","thread_name":"main","level":"INFO","level_value":20000,"appName":"test-name","appname":"test-name"}

五、kibana查看

4、FileBeat發送日誌到Logstash,由logstash發送到ES

一、fileBeat配置

vim  /home/filebeat-6.3.1-linux-x86_64/filebeat.yml

(只改紅色部分其餘跟上面配置一致):

#output.elasticsearch: 關閉ES配置
  # Array of hosts to connect to.
  #hosts: ["localhost:9200"]


output.logstash:
# The Logstash hosts hosts: ["localhost:5044"]

二、配置Logstash

vim /home/logstash-6.3.1/config/conf.d/logstash-es.conf

添加配置:


input {
  beats {
    port => 5044
    ssl  => false
    codec => json  #格式化成json,不然下面%{appname}取不到值
  }
}

output {
     elasticsearch {
        #action => "index"
        hosts => ["localhost:9200"]
        index =>  "%{appname}-%{+YYYY.MM.dd}" #根據項目名稱動態建立索引
        template => "/home/elasticsearch-6.3.1/config/templates/logstash.json" 索引模板地址
        manage_template => false #關閉logstash默認索引模板
        template_name => "crawl" #映射模板的名字
        template_overwrite => true #若是設置爲true,模板名字同樣的時候,新的模板會覆蓋舊的模板
} }

三、啓動logstash和filebeat

/home/logstash-6.3.1/bin/logstash --path.settings /home/logstash-6.3.1/config/ -f /home/logstash-6.3.1/config/conf.d/logstash-es.conf &
/home/filebeat-6.3.1-linux-x86_64/filebeat -e -c filebeat.yml -d "Publish" &

四、驗證

拷貝日誌文件ELK-2018-09-20.log到/home/log文件下

內容以下:

{"@timestamp":"2018-09-20T01:56:55.293+08:00","@version":1,"message":"今天是中秋節放假111,pageNo1,pageSize1","logger_name":"com.example.service.StudentService","thread_name":"main","level":"INFO","level_value":20000,"appName":"test-name","appname":"test-name", "host": "192.168.1.100"}

五、打開kibana

5、logstash多個output配置

一、修改配置文件、

input {
    tcp {
        port => 10514
        codec => "json"
    }
}

input {
  beats {
    port => 5044
    ssl  => false
    codec => json
  }
}

output {

     elasticsearch {
        #action => "index"
        hosts => ["localhost:9200"]
        index =>  "%{appname}-%{+YYYY.MM.dd}"
        template => "/home/elasticsearch-6.3.1/config/templates/logstash.json"
        manage_template => false #關閉logstash自動管理模板功能  
        template_name => "crawl" #映射模板的名字  
        template_overwrite => true
     }


     if [level] == "ERROR" {
         elasticsearch {
            #action => "index"
            hosts => ["localhost:9200"]
            index =>  "%{appname}-error-%{+YYYY.MM.dd}"
            template => "/home/elasticsearch-6.3.1/config/templates/logstash.json"
            manage_template => false #關閉logstash自動管理模板功能
            template_name => "crawl" #映射模板的名字
            template_overwrite => true
         }
     }
}

output {
    stdout {
        codec => rubydebug
    }
}

打開kibana另一個索引中只有errorr日誌

6、logback生成ELK日誌中文亂碼問題

自定義json過濾器

 <!-- 輸出到ELK文件 -->
    <appender name="elkLog"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGPATH}${file.separator}ELK-${TIMESTAMP}.log</file>
        <append>true</append>
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" >
           <jsonFactoryDecorator class="com.example.logback.MyJsonFactoryDecorator" />             <customFields>{"appname":"${appName}"}</customFields>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGPATH}${file.separator}all${file.separator}%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

java類

package com.example.logback;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import net.logstash.logback.decorate.JsonFactoryDecorator;

public class MyJsonFactoryDecorator implements JsonFactoryDecorator {
    @Override
    public MappingJsonFactory decorate(MappingJsonFactory factory) {
        // 禁用對非ascii碼進行escape編碼的特性
        factory.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
        return factory;
    }
}

7、logstash+elasticsearch配置索引模板

在使用logstash收集日誌的時候,咱們通常會使用logstash自帶的動態索引模板,雖然無須咱們作任何定製操做,就能把咱們的日誌數據推送到elasticsearch索引集羣中,可是在咱們查詢的時候,就會發現,默認的索引模板經常把咱們不須要分詞的字段,給分詞了,這樣以來,咱們的比較重要的聚合統計就不許確了: 

若是使用的是logstash的默認模板,它會按-切分機器名,這樣以來想統計那臺機器上的收集日誌最多就有問題了,因此這時候,就須要咱們自定義一些索引模板了: 

在logstash與elasticsearch集成的時候,總共有以下幾種使用模板的方式: 

(1)使用默認自帶的索引模板 ,大部分的字段都會分詞,適合開發和時候快速驗證使用 
(2)在logstash收集端自定義配置模板,由於分散在收集機器上,維護比較麻煩 
(3)在elasticsearc服務端自定義配置模板,由elasticsearch負責加載模板,可動態更改,全局生效,維護比較容易 

以上幾種方式: 

使用第一種,最簡單,無須任何配置 
使用第二種,適合小規模集羣的日誌收集,須要在logstash的output插件中使用template指定本機器上的一個模板json路徑, 例如  template => "/tmp/logstash.json" 

使用第三種,適合大規模集羣的日誌收集,如何配置,主要配置logstash的output插件中兩個參數:

manage_template => false//關閉logstash自動管理模板功能  
template_name => "crawl"//映射模板的名字  

若是使用了,第三種須要在elasticsearch的集羣中的config/templates路徑下配置模板json,在elasticsearch中索引模板可分爲兩種: 

一、靜態模板

 適合索引字段數據固定的場景,一旦配置完成,不能向裏面加入多餘的字段,不然會報錯 
優勢:scheam已知,業務場景明確,不容易出現因字段隨便映射從而形成元數據撐爆es內存,從而致使es集羣所有宕機 
缺點:字段數多的狀況下配置稍繁瑣 

一個靜態索引模板配置例子以下: 

{  
  "crawl" : {  
      "template": "crawl-*",  
        "settings": {  
            "index.number_of_shards": 3,  
            "number_of_replicas": 0   
        },  
    "mappings" : {  
      "logs" : {  
        "properties" : {  
          "@timestamp" : {  
            "type" : "date",  
            "format" : "dateOptionalTime",  
            "doc_values" : true  
          },  
          "@version" : {  
            "type" : "string",  
            "index" : "not_analyzed",  
        "doc_values" : true      
          },  
          "cid" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "crow" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "erow" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "host" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "httpcode" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "message" : {  
            "type" : "string"  
          },  
          "path" : {  
            "type" : "string"  
          },  
          "pcode" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "pro" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "ptype" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "save" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "t1" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "t2" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "t3" : {  
            "type" : "string",  
            "index" : "not_analyzed"  
          },  
          "url" : {  
            "type" : "string"  
          }  
        }  
      }  
    }  
  }  
}  

 

二、動態模板 

適合字段數不明確,大量字段的配置類型相同的場景,多加字段不會報錯 

優勢:可動態添加任意字段,無須改動scheaml, 
缺點:若是添加的字段很是多,有可能形成es集羣宕機 

以下的一個logstash的動態索引模板,只設置message字段分詞,其餘的字段默認不分詞

{  
  "template" : "crawl-*",  
  "settings" : {  
   "index.number_of_shards": 5,  
   "number_of_replicas": 0    
  
},  
  "mappings" : {  
    "_default_" : {  
      "_all" : {"enabled" : true, "omit_norms" : true},  
      "dynamic_templates" : [ {  
        "message_field" : {  
          "match" : "message",  
          "match_mapping_type" : "string",  
          "mapping" : {  
            "type" : "string", "index" : "analyzed", "omit_norms" : true,  
            "fielddata" : { "format" : "disabled" }  
          }  
        }  
      }, {  
        "string_fields" : {  
          "match" : "*",  
          "match_mapping_type" : "string",  
          "mapping" : {  
            "type" : "string", "index" : "not_analyzed", "doc_values" : true  
          }  
        }  
      } ],  
      "properties" : {  
        "@timestamp": { "type": "date" },  
        "@version": { "type": "string", "index": "not_analyzed" },  
        "geoip"  : {  
          "dynamic": true,  
          "properties" : {  
            "ip": { "type": "ip" },  
            "location" : { "type" : "geo_point" },  
            "latitude" : { "type" : "float" },  
            "longitude" : { "type" : "float" }  
          }  
        }  
      }  
    }  
  }  
}  
相關文章
相關標籤/搜索