這陣子斷斷續續的弄 ELK,記下 filebeat 和 logstash 混用時該注意的事項。
由於所在的環境是一個比較混雜的環境,有很舊的 OS (CentOS 5) 也有比較新且不同家族的 OS (Ubuntu 16.04),用 logstash 完全可以搞定這個問題,但是 logstash 實在太肥了,當要做到自動化的時候,你會發現一台 Web Server 裡面會塞很多 agent …,這時每個 agent 的輕量化就很重要了,可以不選 loading 重的就不選。
由於 filebeat 的效率比較好(Golang),所以 CentOS 6 和 Ubuntu 16.04 我都是用 filebeat,真的蠻快的,但是 CentOS 5 就比較杯具了,不支援 Golang 的狀況下只能選用 logstash,所以造就必須要混用 filebeat 和 logstash 的環境。
在混用的狀況下在 Web Server 都不會有什麼問題,最大的問題是你怎麼集中後做 filter,用 logstash 大概就是直接用 _type 來分類,可是 filebeat 在 6 之後的版本拿掉 document_type 了,官方解釋是要逐漸淘汰 _type 概念,可是 logstash 還有 _type 概念啊啊啊啊啊!
沒關係,船到橋頭自然直 … filebeat 拿掉 document_type 後告訴你要改用 custom field,也就是說 logstash 也要改用 custom field,否則兩邊 input 進來的資料會無法 mapping。
Filebeat 和 Logstash 的 custom fields
假設我用 logtype 這個 field 來統一兩邊的 log 類型
filebeat 可以利用 fields input,以 apache access log 為例:
$ vim /etc/filebeat/conf.d/apache-access-log.yml --- - type: log paths: - /var/log/apache2/*access*.log - /var/log/httpd/*access*.log - /opt/httpd*/logs/*access*.log - /opt/httpd*/logs/*access*_log* encoding: plain fields: logtype: apache-access-log
logstash 則是用 add_field input
$ vim /etc/logstash/conf.d/01-input-apache-access-log.conf input { file { path => ["/var/log/apache2/access.log"] start_position => "beginning" add_field => { "[fields][logtype]" => "apache-access-log" } } }
logstash 過濾 field filter
這邊就沒什麼難的了,直接抓 fields.logtype 這個值丟 grok pattern 就好了。
$ vim /etc/logstash/conf.d/02-filter-apache-access-log.conf filter { if [fields][logtype] == "apache-access-log" { grok { # defind grok plugin setting patterns_dir => "/etc/logstash/patterns/" match => { "message" => "%{HTTPD_COMMONLOG}" } } geoip { source => "clientip" } } }
雖然有點坑,但是用 fields 來處理特殊狀況其實是比較好用,畢竟彈性比較大,可以做到許多複雜的事情。