ELK 使用心得
写在前面:我使用的架构是filebeat => kafka => logstash => elasticsearch <=> kibana;
一. Filebeat
首先是filebeat,filebeat用来采集日志,将日志信息推送给kafka。在这个过程中有几点是个人遇到的问题:1.一条日志信息有内容换行了,在收集日志时当然要归属于同一条信息;2.自定义字段补充日志信息;3.不同的业务的日志推送到kafka中的topic不同;
1.多行问题
解决方案如下:
multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'
multiline.negate: true
multiline.match: after
pattern是一个正则匹配,匹配日志开头;negate: true
和 match: after
设置来指定任何不符合指定模式的行都属于上一行。
解释上面案例的逻辑就是如果这一行不是以日期开头的话,那么就和上一行同属一条日志信息。
2.自定义字段
fields:
log_topics: programlog-test
s-ip: 172.22.66.66
可以通过以上方式添加想要增加的字段并存储信息,该字段会和收集到的日志信息一起发给kafka;
3.不同的topic
完整示例代码如下:
type: log enabled: true paths: - D:\log1\*.log fields: log_topics: log1 s-ip: 172.22.22.26 multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}' multiline.negate: true multiline.match: after - type: log enabled: true paths: - D:\logs\logdemo\*.log fields: log_topics: log2 s-ip: 172.22.22.26 multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}' multiline.negate: true multiline.match: after output.kafka: enable: true hosts: ["172.20.11.11:9092","172.20.22.22:9092","172.20.33.33:9092"] topic: '%{[fields][log_topics]}'
二. Logstash
logstash的任务是从kafka中读取信息,并将信息加工成自己需要的样式,加工过程用到很多正则,所以对logstash对服务器性能有一定的损耗。
logstash中的过滤用的是grok,常用参数如下:
match:
● 值类型是数组
● 默认值是 {}
● 描述:字段⇒值匹配
filter { grok { match => { "message" => "Duration: %{NUMBER:duration}" } } } #如果你需要针对单个字段匹配多个模式,则该值可以是一组,例如: filter { grok { match => { "message" => [ "Duration: %{NUMBER:duration}", "Speed: %{NUMBER:speed}" ] } } }
break_on_match:
● 值类型是布尔值
● 默认是true
● 描述:match可以一次设定多组,预设会依照顺序设定处理,如果日志满足设定条件,则会终止向下处理。但有的时候我们会希望让Logstash跑完所有的设定,这时可以将break_on_match设为false。
filter { grok { break_on_match => false match => ["message" , "%{TIMESTAMP_ISO8601:log-timestamp} (%{NOTSPACE:level}|-) (?<thread>\[(.*?)\]) (%{NOTSPACE:class}|-) (?<a-msg>\[-(.*?)\-]) (?<a-ex>\[-(.*?)\-])", "a-msg" , "(?<msg>(?<=\[-).*?(?=\-]))", "a-ex" , "(?<ex>(?<=\[-).*?(?=\-]))"] } }
add_field:
● 值类型是散列
● 默认值是 {}
● 描述:在匹配日志中增加一个 field,可以通过%{field}动态命名field名或field的值。
filter { grok { add_field => { "foo_%{somefield}" => "Hello world, from %{host}" } } } # 你也可以一次添加多个字段 filter { grok { add_field => { "foo_%{somefield}" => "Hello world, from %{host}" "new_field" => "new_static_value" } } }
remove_field:
● 值的类型:array
● 默认值:[]
● 描述:删除当前文档中的指定filted
1 filter { 2 grok { 3 remove_field => [ "foo_%{somefield}" ] 4 } 5 } 6 7 # 你也可以一次移除多个字段: 8 filter { 9 grok { 10 remove_field => [ "foo_%{somefield}", "my_extraneous_field" ] 11 } 12 }
完整logstash的.conf如下:
1 input { 2 kafka { 3 bootstrap_servers => ["172.21.6.66:9092,172.21.6.67:9092,172.21.6.68:9092"] 4 client_id => "client-01" 5 group_id => "logstash-01" 6 auto_offset_reset => "latest" 7 decorate_events => true 8 topics => ["log-test"] 9 type => "type1" 10 codec => json 11 } 12 13 } 14 15 filter { 16 grok { 17 break_on_match => false 18 match => ["message" , "%{TIMESTAMP_ISO8601:log-timestamp} (%{NOTSPACE:level}|-) (?<thread>\[(.*?)\]) (?<a-msg>\[-(.*?)\-]) (?<a-ex>\[-(.*?)\-])", 19 "a-msg" , "(?<msg>(?<=\[-).*?(?=\-]))", 20 "a-ex" , "(?<ex>(?<=\[-).*?(?=\-]))"] 21 } 22 mutate{ 23 remove_field => ["[a-msg]"] 24 remove_field => ["[a-ex]"] 25 } 26 } 27 28 29 output { 30 #输出到控制台 31 # stdout{ 32 # codec => rubydebug 33 # } 34 35 if[type]=="type1"{ 36 elasticsearch{ 37 hosts => ["172.20.33.77:9200"] 38 index => "log-%{+YYYY.MM.dd}" 39 } 40 } 41 }
启动logstash多实例方法:
1.
path.data: 持久化存储数据的文件夹,默认是logstash home目录下的data
bin/logstash --path.settings instance1
bin/logstash --path.settings instance2
不同instance中修改logstash.yml,自定义path.data,确保其不相同即可
2.
Logstash could not be started because there is already another instance using the configured data directory. If you wish to run multiple instances, you must change the "path.data" setting
将原先的命令:
/bin/logstash -f 010.conf
改为:
/bin/logstash -f 010.conf --path.data=/root/
其中,--path.data是指存放数据的路径