簡單概述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
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.1-linux-x86_64.tar.gz
tar -zxvf filebeat-6.3.1-linux-x86_64.tar.gz
vim filebeat.yml
按照要求修改輸入和輸出部分爲(紅色):
./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"}
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"]
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,模板名字同樣的時候,新的模板會覆蓋舊的模板
} }
/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"}
一、修改配置文件、
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日誌
自定義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; } }
在使用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" } } } } } } }