ELK學習筆記之Logstash和Filebeat解析對java異常堆棧下多行日志配置支持


 

0x00 概述

logstash官方最新文檔
假設有幾十台服務器,每台服務器要監控系統日志syslog、tomcat日志、nginx日志、mysql日志等等,監控OOM、內存低下進程被kill、nginx錯誤、mysql異常等等,可想而知,這是多么的耗時耗力。
logstash采用的是插件化體系架構,幾乎所有具體功能的實現都是采用插件,已安裝的插件列表可以通過bin/logstash-plugin list --verbose列出。或者訪問https://www.elastic.co/guide/en/logstash/current/input-plugins.html、https://www.elastic.co/guide/en/logstash/current/output-plugins.html。

 

0x01 logstash配置文件格式

分為輸入、過濾器、輸出三部分。除了POC目的外,基本上所有實際應用中都需要filter對日志進行預處理,無論是nginx日志還是log4j日志。output中的stdout同理。

input {
    log4j {
        port => "5400"
    }
    beats {
        port => "5044"
    }
}
filter {  # 多個過濾器會按聲明的先后順序執行
    grok {
        match => { "message" => "%{COMBINEDAPACHELOG}"}
    }
    geoip {
        source => "clientip"
    }
}
output {
    elasticsearch {
		action => "index"
		hosts => "127.0.0.1:9200" # 或者 ["IP Address 1:port1", "IP Address 2:port2", "IP Address 3"] ,支持均衡的寫入ES的多個節點,一般為非master節點
		index  => "logstash-%{+YYYY-MM}"
    }
	stdout { 
		codec=> rubydebug 
	}
	file {
        path => "/path/to/target/file"
    }
}
# logstash支持的常用輸入包括syslog(參考RFC3164)、控制台、文件、redis、beats。
# logstash支持的常用輸出包括es、控制台、文件。
# logstash支持的常用過濾器包括grok、mutate、drop、clone、geoip。

 

查看logstash各種命令行選項

[root@elk1 bin]# ./logstash --help
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Usage:
    bin/logstash [OPTIONS]

Options:
    -n, --node.name NAME          Specify the name of this logstash instance, if no value is given
                                  it will default to the current hostname.
                                   (default: "elk1")
    -f, --path.config CONFIG_PATH Load the logstash config from a specific file
                                  or directory.  If a directory is given, all
                                  files in that directory will be concatenated
                                  in lexicographical order and then parsed as a
                                  single config file. You can also specify
                                  wildcards (globs) and any matched files will
                                  be loaded in the order described above.
    -e, --config.string CONFIG_STRING Use the given string as the configuration
                                  data. Same syntax as the config file. If no
                                  input is specified, then the following is
                                  used as the default input:
                                  "input { stdin { type => stdin } }"
                                  and if no output is specified, then the
                                  following is used as the default output:
                                  "output { stdout { codec => rubydebug } }"
                                  If you wish to use both defaults, please use
                                  the empty string for the '-e' flag.
                                   (default: nil)
    --modules MODULES             Load Logstash modules.
                                  Modules can be defined using multiple instances
                                  '--modules module1 --modules module2',
                                     or comma-separated syntax
                                  '--modules=module1,module2'
                                  Cannot be used in conjunction with '-e' or '-f'
                                  Use of '--modules' will override modules declared
                                  in the 'logstash.yml' file.
    -M, --modules.variable MODULES_VARIABLE Load variables for module template.
                                  Multiple instances of '-M' or
                                  '--modules.variable' are supported.
                                  Ignored if '--modules' flag is not used.
                                  Should be in the format of
                                  '-M "MODULE_NAME.var.PLUGIN_TYPE.PLUGIN_NAME.VARIABLE_NAME=VALUE"'
                                  as in
                                  '-M "example.var.filter.mutate.fieldname=fieldvalue"'
    --setup                       Load index template into Elasticsearch, and saved searches, 
                                  index-pattern, visualizations, and dashboards into Kibana when
                                  running modules.
                                   (default: false)
    --cloud.id CLOUD_ID           Sets the elasticsearch and kibana host settings for
                                  module connections in Elastic Cloud.
                                  Your Elastic Cloud User interface or the Cloud support
                                  team should provide this.
                                  Add an optional label prefix '<label>:' to help you
                                  identify multiple cloud.ids.
                                  e.g. 'staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRub3RhcmVhbCRpZGVudGlmaWVy'
    --cloud.auth CLOUD_AUTH       Sets the elasticsearch and kibana username and password
                                  for module connections in Elastic Cloud
                                  e.g. 'username:<password>'
    --pipeline.id ID              Sets the ID of the pipeline.
                                   (default: "main")
    -w, --pipeline.workers COUNT  Sets the number of pipeline workers to run.
                                   (default: 1)
    --experimental-java-execution (Experimental) Use new Java execution engine.
                                   (default: false)
    -b, --pipeline.batch.size SIZE Size of batches the pipeline is to work in.
                                   (default: 125)
    -u, --pipeline.batch.delay DELAY_IN_MS When creating pipeline batches, how long to wait while polling
                                  for the next event.
                                   (default: 50)
    --pipeline.unsafe_shutdown    Force logstash to exit during shutdown even
                                  if there are still inflight events in memory.
                                  By default, logstash will refuse to quit until all
                                  received events have been pushed to the outputs.
                                   (default: false)
    --path.data PATH              This should point to a writable directory. Logstash
                                  will use this directory whenever it needs to store
                                  data. Plugins will also have access to this path.
                                   (default: "/usr/local/app/logstash-6.2.4/data")
    -p, --path.plugins PATH       A path of where to find plugins. This flag
                                  can be given multiple times to include
                                  multiple paths. Plugins are expected to be
                                  in a specific directory hierarchy:
                                  'PATH/logstash/TYPE/NAME.rb' where TYPE is
                                  'inputs' 'filters', 'outputs' or 'codecs'
                                  and NAME is the name of the plugin.
                                   (default: [])
    -l, --path.logs PATH          Write logstash internal logs to the given
                                  file. Without this flag, logstash will emit
                                  logs to standard output.
                                   (default: "/usr/local/app/logstash-6.2.4/logs")
    --log.level LEVEL             Set the log level for logstash. Possible values are:
                                    - fatal
                                    - error
                                    - warn
                                    - info
                                    - debug
                                    - trace
                                   (default: "info")
    --config.debug                Print the compiled config ruby code out as a debug log (you must also have --log.level=debug enabled).
                                  WARNING: This will include any 'password' options passed to plugin configs as plaintext, and may result
                                  in plaintext passwords appearing in your logs!
                                   (default: false)
    -i, --interactive SHELL       Drop to shell instead of running as normal.
                                  Valid shells are "irb" and "pry"
    -V, --version                 Emit the version of logstash and its friends,
                                  then exit.
    -t, --config.test_and_exit    Check configuration for valid syntax and then exit.
                                   (default: false)
    -r, --config.reload.automatic Monitor configuration changes and reload
                                  whenever it is changed.
                                  NOTE: use SIGHUP to manually reload the config
                                   (default: false)
    --config.reload.interval RELOAD_INTERVAL How frequently to poll the configuration location
                                  for changes, in seconds.
                                   (default: 3000000000)
    --http.host HTTP_HOST         Web API binding host (default: "127.0.0.1")
    --http.port HTTP_PORT         Web API http port (default: 9600..9700)
    --log.format FORMAT           Specify if Logstash should write its own logs in JSON form (one
                                  event per line) or in plain text (using Ruby's Object#inspect)
                                   (default: "plain")
    --path.settings SETTINGS_DIR  Directory containing logstash.yml file. This can also be
                                  set through the LS_SETTINGS_DIR environment variable.
                                   (default: "/usr/local/app/logstash-6.2.4/config")
    --verbose                     Set the log level to info.
                                  DEPRECATED: use --log.level=info instead.
    --debug                       Set the log level to debug.
                                  DEPRECATED: use --log.level=debug instead.
    --quiet                       Set the log level to info.
                                  DEPRECATED: use --log.level=quiet instead.
    -h, --help                    print help

 

各配置的含義也可以參考
比較實用的是:

# -f filename.conf 指定配置文件
# --config.test_and_exit 解析配置文件正確性
# --config.reload.automatic 自動監聽配置修改而無需重啟,跟nginx -s reload一樣,挺實用的

 

ELK均采用YAML語言(https://baike.baidu.com/item/YAML/1067697?fr=aladdin)編寫配置文件。

YAML有以下基本規則: 

# 1、大小寫敏感 
# 2、使用縮進表示層級關系 
# 3、禁止使用tab縮進,只能使用空格鍵 
# 4、縮進長度沒有限制,只要元素對齊就表示這些元素屬於一個層級。 
# 5、使用#表示注釋 
# 6、字符串可以不用引號標注

 

JVM參數在config/jvm.options中設置。

# 配置文件中output和filter部分均支持主要常見的邏輯表達式比如if/else if,以及各種比較、正則匹配。
# 配置文件中還可以訪問環境變量,通過${HOME}即可,具體可以參考https://www.elastic.co/guide/en/logstash/current/environment-variables.html。

 

0x02 Beats Input插件

在開始看具體Input插件之前,我們看下哪些選項是所有插件都支持的。
其中主要的是id,如果一個logstash實例里面開了多個相同類型的插件,可以用來區分。

通過Beats插件加載數據源已經是ELK 6.x的主要推薦方式,所以我們來詳細看下Beats插件的配置

input {
  beats {
    port => 5044
  }
}

其中port是參數是必填的,沒有默認值。除了ssl配置外,其他幾乎都是可選的。
host默認是"0.0.0.0",代表監聽所有網卡,除非有特殊安全要求,也是推薦的做法。

 

0x03 核心解析插件Grok Filter

通常來說,各種日志的格式都比較靈活復雜比如nginx訪問日志或者並不純粹是一行一事件比如java異常堆棧,而且還不一定對大部分開發或者運維那么友好,所以如果可以在最終展現前對日志進行解析並歸類到各個字段中,可用性會提升很多。

grok過濾器插件就是用來完成這個功能的。grok和beat插件一樣,默認可用。
從非源頭上來說,日志體系好不好,很大程度上依賴於這一步的過濾規則做的好不好,所以雖然繁瑣,但卻必須掌握,跟nginx的重寫差不多。

# Logstash自帶了約120個模式,具體可見。
# grok的語法為:%{SYNTAX:SEMANTIC}

類似於java:

String pattern = ".*runoob.*";
boolean isMatch = Pattern.matches(pattern, content); 

其中的pattern就相當於SYNTAX,SEMANTIC為content,只不過因為解析的時候沒有字段名,所以content是賦給匹配正則模式的文本的字段名,這些字段名會被追加到event中。


例如對於下列http請求日志:

55.3.244.1 GET /index.html 15824 0.043
# 使用 %{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration} 匹配的話,除了原message外,事件中會新增下列額外字段:
client: 55.3.244.1
method: GET
request: /index.html
bytes: 15824
duration: 0.043


完整的grok例子如下:

input {
  file {
    path => "/var/log/http.log"
  }
}
filter {
  grok {
    match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
  }
}

注:如果重啟,logstash怎么知道讀取到http.log的什么位置了,在filebeat部分,我們會講到。
grok的主要選項是match和overwrite,前者用來解析message到相應字段,后者用來重寫message,這樣原始message就可以被覆蓋,對於很多的日志來說,原始的message重復存儲一份沒有意義。 https://www.elastic.co/guide/en/logstash/6.2/plugins-filters-grok.html#plugins-filters-grok-overwrite

雖然Grok過濾器可以用來進行格式化,但是對於多行事件來說,並不適合在filter或者input(multiline codec,如果希望在logstash中處理多行事件,可以參考https://www.elastic.co/guide/en/logstash/current/multiline.html)中處理,因為使用ELK的平台通常日志使用beats input插件,此時在logstash中進行多行事件的處理會導致數據流混亂,所以需要在事件發送到logstash之前就處理好,也就是應該在filebeat中預處理。

對於來自於filebeat模塊的數據,logstash自帶了針對他們的解析模式,參考https://www.elastic.co/guide/en/logstash/current/logstash-config-for-filebeat-modules.html,具體到filebeat的時候詳解。

 

0x04 ES Output插件

主要的選項包括:

# action,默認是index,索引文檔(logstash的事件)(ES架構與核心概念參考)。
# host,聲明ES服務器地址端口
# index,事件寫入的ES index,默認是logstash-%{+YYYY.MM.dd},按天分片index,一般來說我們會按照時間分片,時間格式參考http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html。

 

1. filebeat

從ELK 6.x開始,log4j輸入插件已經不再建議使用,推薦的替代是filebat。

 

2. filebeat工作原理

參考

Filebeat由兩個主要組件組成, prospectors和harvesters,他們一起協作tail文件並將事件發送給聲明的輸出。

harvester的職責是以行為單位讀取文件,發送給輸出,每個文件由不同的harvester讀取。

prospector的職責是管理harvester並找到要讀取的文件。

Filebeat當前支持log和stdin這兩種prospector,每種prospector可以定義多次。

Filebeat在注冊表(通過參數filebeat.registry_file聲明,默認是${path.data}/registry)中記錄了每個文件的狀態,狀態記錄了上一次harvester的讀取偏移量。prospector則記錄了每個找到的文件的狀態。Filebeat確保所有的事件都被發送至少一次。

filebeat的配置文件同樣采用YAML格式。

filebeat.prospectors:
- type: log
  paths:
    - /var/log/*.log  # 聲明日志文件的絕對路徑
  fields:
    type: syslog  # 聲明增加一個值為syslog的type字段到事件中
output.logstash:
  hosts: ["localhost:5044"]

 

filebeat支持輸出到Elasticsearch或者Logstash,一般來說通行的做法都是到Logstash,所以到ES的相關配置略過。
filebeat的命令行選項可以參考,配置文件所有配置項參考

默認情況下,filebeat運行在后台,要以前台方式啟動,運行./filebeat -e。

要使用Filebeat,我們需要在filebeat.yml配置文件的filebeat.prospectors下聲明prospector,prospector不限定只有一個。例如:

filebeat.prospectors:
- type: log
  paths:
    - /var/log/apache/httpd-*.log

- type: log
  paths:
    - /var/log/messages
    - /var/log/*.log

 

其他有用的選項還包括include_lines(僅讀取匹配的行)、exclude_lines(不讀取匹配的行)、exclude_files(排除某些文件)、tags、fields、fields_under_root、close_inactive(日志文件多久沒有變化后自動關閉harvester,默認5分鍾)、scan_frequency(prospector為harvester掃描新文件的頻率,注意,因close_inactive自動關閉的也算新文件,默認為10s,不要低於1s)等
具體可見

 

3. 解析多行消息

對於采用ELK作為應用日志來說,多行消息的友好展示是必不可少的,否則ELK的價值就大大打折了。要正確的處理多行消息,需要在filebeat.yml中設置multiline規則以聲明哪些行屬於一個事件。主要是由multiline.pattern、multiline.negate、multiline.match這三個參數決定。
比如,對於java日志而言,可以使用:

multiline.pattern: '^\['
multiline.negate: true
multiline.match: after

或者:

multiline.pattern: '^[[:space:]]+(at|\.{3})\b|^Caused by:'
multiline.negate: false
multiline.match: after

這樣,下面的日志就算一個事件了。

beat-logstash-some-name-832-2015.11.28] IndexNotFoundException[no such index]
    at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver$WildcardExpressionResolver.resolve(IndexNameExpressionResolver.java:566)
    at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:133)
    at org.elasticsearch.cluster.metadata.IndexNameExpressionResolver.concreteIndices(IndexNameExpressionResolver.java:77)
    at org.elasticsearch.action.admin.indices.delete.TransportDeleteIndexAction.checkBlock(TransportDeleteIndexAction.java:75)

 

詳細的配置可以參考https://www.elastic.co/guide/en/beats/filebeat/6.2/multiline-examples.html。

Filebeat支持的輸出包括Elasticsearch、Logstash、Kafka、Redis、File、Console,都挺簡單,可以參考https://www.elastic.co/guide/en/beats/filebeat/6.2/kafka-output.html。

Filebeat模塊提供了一種更便捷的方式處理常見的日志格式,比如apache2、mysql等。從性質上來說,他就像spring boot,約定優於配置。具體可以參考https://www.elastic.co/guide/en/beats/filebeat/6.2/filebeat-modules-overview.html。Filebeat模塊要求Elasticsearch 5.2以及之后的版本。

 

參考

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM