簡單概述
最近在了解ELK做日志采集相關的內容,這篇文章主要講解通過filebeat來實現日志的收集。日志采集的工具有很多種,如fluentd, flume, logstash,betas等等。首先要知道為什么要使用filebeat呢?因為logstash是jvm跑的,資源消耗比較大,啟動一個logstash就需要消耗500M左右的內存,而filebeat只需要10來M內存資源。常用的ELK日志采集方案中,大部分的做法就是將所有節點的日志內容通過filebeat送到kafka消息隊列,然后使用logstash集群讀取消息隊列內容,根據配置文件進行過濾。然后將過濾之后的文件輸送到elasticsearch中,通過kibana去展示。
filebeat介紹
Filebeat由兩個主要組成部分組成:prospector和 harvesters。這些組件一起工作來讀取文件並將事件數據發送到您指定的output。
什么是harvesters?
harvesters負責讀取單個文件的內容。harvesters逐行讀取每個文件,並將內容發送到output中。每個文件都將啟動一個harvesters。harvesters負責文件的打開和關閉,這意味着harvesters運行時,文件會保持打開狀態。如果在收集過程中,即使刪除了這個文件或者是對文件進行重命名,Filebeat依然會繼續對這個文件進行讀取,這時候將會一直占用着文件所對應的磁盤空間,直到Harvester關閉。默認情況下,Filebeat會一直保持文件的開啟狀態,直到超過配置的close_inactive參數,Filebeat才會把Harvester關閉。
關閉Harvesters會帶來的影響:
file Handler將會被關閉,如果在Harvester關閉之前,讀取的文件已經被刪除或者重命名,這時候會釋放之前被占用的磁盤資源。
當時間到達配置的scan_frequency參數,將會重新啟動為文件內容的收集。
如果在Havester關閉以后,移動或者刪除了文件,Havester再次啟動時,將會無法收集文件數據。
當需要關閉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選擇到。
filebeat工作原理
二、下載FileBeat安裝包
wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.3.1-linux-x86_64.tar.gz
三、FileBeat發送日志到ES
1、解壓文件
tar -zxvf filebeat-6.3.1-linux-x86_64.tar.gz
2、編輯filebeat.yml
vim filebeat.yml
按照要求修改輸入和輸出部分為(紅色):
# you can use different inputs for various configurations.
# Below are the input specific configurations.
enabled: true
paths:
/home/log/*.log
#- c:\programdata\elasticsearch\logs\*
# Glob pattern for configuration loading
path: ${path.config}/modules.d/*.yml
reload.enabled: true
# Glob pattern for configuration loading
path: ${path.config}/modules.d/*.yml
reload.enabled: true
# Array of hosts to connect to.
hosts: ["localhost:9200"]
3、啟動
./filebeat -e -c filebeat.yml -d "Publish"
4、驗證
上傳日志到文件到指定目錄

日志內容:
{"@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"}
5、kibana查看

四、FileBeat發送日志到Logstash,由logstash發送到ES
1、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"]
2、配置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,模板名字一樣的時候,新的模板會覆蓋舊的模板
}
}
3、啟動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" &
4、驗證
拷貝日志文件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"}
5、打開kibana

五、logstash多個output配置
1、修改配置文件、
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日志

六、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;
}
}
七、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中索引模板可分為兩種:
1、靜態模板
適合索引字段數據固定的場景,一旦配置完成,不能向里面加入多余的字段,否則會報錯
優點: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"
}
}
}
}
}
}
2、動態模板
適合字段數不明確,大量字段的配置類型相同的場景,多加字段不會報錯
優點:可動態添加任意字段,無須改動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" }
}
}
}
}
}
}

