elk筆記5--logstash使用
1 logstash 簡介
Logstash是一個具有實時pipeline功能的開源數據收集引擎, 其可以動態統一來自不同來源的數據,並將數據標準化到目標位置。 也可以清洗數據並使其大衆化,以用於不同的高級下游分析和可視化用例。如圖1所示。
Logstash會動態提取,轉換和傳送數據,而不需要考慮數據的格式或複雜性,其使用grok從非結構化數據中獲取結構化的數據,從IP地址解密地理座標,對敏感字段進行匿名化或排除,並簡化整體處理。
在elk中,logstash 通過input,filter,output對數據進行處理,處理後寫入到具體的es索引中,如圖2所示。
圖1
圖2
2 logstash 使用案例
-
初步使用,輸入直接輸出
bin/logstash -e ‘input{stdin{}} output{stdout{}}’
-
將輸入直接寫入到es
bin/logstash -e ‘input{stdin{}} output{elasticsearch{hosts=>[“127.0.0.1:9200”]} stdout{}}’
output中去掉stdout{} 則沒有對應的輸出
輸入hello,world後結果如下:
此時默認以 logstash-2020.04.13 新建對應的索引, 新建Index Pattern後可以從Discover查尋到輸入的hello world,如下所示:
由於默認爲5P 1R,一個節點時候會導致無法新建另外的1R,因此出現yellow狀態;更改配置爲5P0R後,恢復爲green; -
收集系統日誌
收集syslog和dmesg日誌,只需要在input和output中添加syslog和dmesg的規則即可。
當規則較多的時候直接將其寫入到對應的配置文件中,此時啓動方式爲 bin/logstash -f …/pipeline/default.conf 。input{ file{ path => "/var/log/syslog" type => "syslog" start_position => "beginning" } file{ path => "/var/log/dmesg" type => "dmesg" start_position => "beginning" } } filter{ } output{ if [type] == "syslog" { elasticsearch { hosts => ["127.0.0.01:9200"] index => "syslog-%{+YYYY.MM.dd}" } } output{ if [type] == "dmesg" { elasticsearch { hosts => ["127.0.0.01:9200"] index => "dmesg-%{+YYYY.MM.dd}" } } }
-
收集 es_error.log日誌
此處需要使用codec,否則一個事件的多行沒有被統一處理;
codec-pluginsinput{ file{ path => "/home/xg/soft/bigdata/log/es6.8.8/es6.8.log" type => "es_error" start_position => "beginning" } } filter{ } output{ if [type] == "syslog" { elasticsearch { hosts => ["127.0.0.01:9200"] index => "syslog-%{+YYYY.MM.dd}" } } output{ if [type] == "es_error" { elasticsearch { hosts => ["127.0.0.01:9200"] index => "es_error-%{+YYYY.MM.dd}" } } }
此時,一個事件的多行被分隔爲多條日誌,需要使用codec加以處理, 具體處理如下所示:
file{ path => "/home/xg/soft/bigdata/log/es6.8.8/es6.8.log" type => "es_error" start_position => "beginning" codec => multiline { # Grok pattern names are valid! :) pattern => "^\[" negate => true what => "previous" } }
改進後可以多行顯示java的堆棧信息,如下圖所示:
-
收集apache 訪問日誌
訪問apache日誌需要使用自定義的grok或者默認的grok解析,此處使用默認的%{COMBINEDAPACHELOG} 方式進行解析。
相關的input,output,filter內容如下:input{ file{ path => "/var/log/apache2/access.log" type => "apache_access" start_position => "beginning" } } filter{ if [type] == "apache_access"{ grok { match => { "message" => "%{COMBINEDAPACHELOG}"} } } } output{ if [type] == "apache_access" { elasticsearch { hosts => ["127.0.0.01:9200"] index => "apache_access-%{+YYYY.MM.dd}" } } }
日誌收集後,即可在對應的discover查看,如下:
-
收集自定義日誌(grok解析)
此處用python構建了2類日誌,一個爲自定義格式的字符串,另外一個是純json格式,相關代碼如下#!/usr/bin/python3 import time import datetime import random import json company_list = [['baidu','39.156.69.79'],['ali','140.205.220.96'],['tencent','140.205.220.96'],['bytedance','36.110.162.63'],['google','216.58.200.46']] user_list = ['ally','bob','cindy','daid', 'friday','gad'] type_list = ['buy','sell','search','other'] def get_logs(): date_str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') user = user_list[random.randint(0,len(user_list)-1)] type_str = type_list[random.randint(0,len(type_list)-1)] item = company_list[random.randint(0,len(company_list)-1)] msg =date_str.split('.')[0] +', '+user+' '+ type_str + ' on ' + item[0] str_log = '[' + date_str+'] ['+item[1]+'] ['+ user +'] [' + type_str + '] '+msg+'\n' dict_log = {'date_str':date_str,'ip':item[1],'user':user,'action':type_str,'msg':msg} json_log = json.dumps(dict_log)+'\n' return str_log, json_log def save_str_2_doc(data_str, filename): with open(filename,'a') as f: f.write(data_str) if __name__ == "__main__": path_str = '/home/xg/soft/bigdata/log/testlog/str.log' path_json = '/home/xg/soft/bigdata/log/testlog/json.log' while(True): str_log, json_log = get_logs() save_str_2_doc(str_log,path_str) save_str_2_doc(json_log,path_json) time.sleep(30)
日誌收集後,使用grok解析對應日誌,然後在intpu,filter,output中添加對應的文件即可。具體內容如下:
input{ file{ path => "/home/xg/soft/bigdata/log/testlog/str.log" type => "test_log" start_position => "beginning" } } filter{ if [type] == "test_log" { grok { match => { "message" => "\[%{GREEDYDATA:date_str}] \[%{IP:ip}] \[%{DATA:user}] \[%{DATA:action}] %{GREEDYDATA:msg}" } } } } output{ if [type] == "test_log" { #stdout{} elasticsearch { hosts => ["127.0.0.01:9200"] index => "test_log-%{+YYYY.MM.dd}" } } }
日誌收集後,即可在對應的discover查看,如下:
-
收集純json日誌
使用6中的代碼生成純json字符串,在filter中使用json插件解析即可。具體內容如下:input{ file{ path => "/home/xg/soft/bigdata/log/testlog/json.log" type => "json_log" start_position => "beginning" } } filter{ if [type] == "json_log" { json { source => "message" } } } output{ if [type] == "json_log" { #stdout{} elasticsearch { hosts => ["127.0.0.01:9200"] index => "json_log-%{+YYYY.MM.dd}" } } }
日誌解析出來後, 在discover中查看結果和6中一樣。
此時,如果需要進一步解析ip歸屬等信息,可以在filter中添加geoip功能,具體內容如下。filter{ if [type] == "json_log" { json { source => "message" } geoip { source => "ip" target => "ip_geo" } } }
解析後的效果如下:
3 使用技巧
-
使用codec解決多行被切割爲多個日誌的問題
默認情況下讀取文件每行爲一個時間, 對於產生多行的日誌會被分開爲多個事件,此時需要使用codec對其進行多行處理 -
geo ip處理注意事項
最簡單的使用方法即: 在geoip中添加source和target字段即可,其中source是需要解析的源ip。 -
json處理
純json,只需要使用在filter中使用json插件加以處理即可。 -
注意
若測試時候使用多個type來區分不同的日誌,則在json字段或者grok的字段中不應該有type字段,否則使用grok或者json解析的時候會出錯。
具體案例即爲: 上述使用type=>"test_log"後, 在grok中不可以繼續使用type字段,需要換成其它不同的字段。
4 說明
測試使用的elk版本爲6.8.8
logstash/6.8/index