本文系原創,轉載請註明。
本文地址:http://blog.csdn.net/xeseo/article/details/38817315
前言:
現在的系統,動則分佈式,分佈式情況下,錯誤的定位比傳統的單機要麻煩很多。因爲log文件分佈在不同的feature的不同節點。一直想找一種方式來簡化這個過程。
目前主流的log監控有:
Splunk:商業收費
syslog-ng:漏數據
flume:java寫的,有點重
chukwa:專爲Hadoop服務
scribe:java寫的,略重
zabbix、ganglia:全面的系統監控,大材小用
graylog2:不詳,沒來得及研究
目標要輕量級、可擴展、分佈式、儘量實時。
最終找到了ELK(Elasticsearch、Logstash和Kibana)。Elasticsearch一家子。
簡介
Logstash是JRuby寫的log收集工具,特點引用官方的話“Ship logs from any source, parse them,get the right timestamp, index them, and search them.”
基本使用框架如下
logstash本身只有收集、解析和建立索引功能。這個框架中,shipper就是利用logstash的收集、解析功能來做agent,把目標log收集到broker去。Index還是利用logstash的索引功能。
這種架構是比較標準的,在數據量稍大的情況下,靠shipper聚集到broker,最後統一由index處理的。但如果數據量小,可以用一種更簡單的框架:
因爲logstash本身作爲agent或index都是分佈式的,可自動加入cluster。所以在這種情況下,去掉一個broker,直接交到storage。(如果有錯,還請指正。)
常用的Broker是Redis,logstash book上面推薦的。
這裏的Search&Storage,就用自家的Elasticsearch,它的主要特點:
- 分佈式、HA、近乎實時
- 讀寫分離
- 面向文檔
- 由於是document oriented,所以不需要特定的schema定義。可以在index階段隨意指定。
- 基於apche的Lucene搜索引擎
- 將logstash建立的index打碎成shards。shards有primary和replica。
- primary是真正存儲的地方,每一個新Index默認創建五個primary shards。該數量可以在Index被創建前改變。但是index一旦創建就無法再變。
- replica是primary shards的備份,該數量可以隨時改變,主要用於保護數據和加速查找(讀寫分離)。
- 將logstash建立的index打碎成shards。shards有primary和replica。
WebInterface,還是Elasticsearch家族的一員——Kibana。Kibana是一款完全基於HTML5和js的web統計界面,易於拓展,看上去也比較高大尚。
最新版的logstash自帶了一個,可以用bin目錄的logstash-web直接啓動。
所以部署框架詳情如下:
這個框架中除了Kibana外,都是分佈式的~囧 意味着都可以變成cluster。
安裝
- 下載logstash、Elasticsearch和redis的tar包。Kibana就不用下了,直接用logstash自帶的。
- 將logstash的tar包分別解壓到目標集羣的每個機器上。最好是同一位置。logstash不需要額外配置什麼,大部分都是靠命令行參數。啓動命令:
bin/logstash -f xxx.conf
額外參數:
-p指定端口,默認9292端口
- 安裝redis
- 解壓出來後,執行make命令
- 拷貝執行文件
# mkdir /usr/local/redis/{conf,run,db}–pv
#cp redis.conf /usr/local/redis/conf
#cd src
#cp reids-benchmark redis-check-aof redis-check-dump redis-cli redis-servermkreleasehdr.sh /usr/local/redis/
- 配置redis
# vi /usr/local/redis/conf/redis.conf
daemonize yes … dir /usr/local/redis/db/ |
- 啓動
#cd/usr/local/redis/
# ./redis-server conf/redis.conf
- 測試一下
# ./redis-benchmark
- 安裝elasticsearch
- 解壓出來後修改config/elasticsearch.yml (自己替換通配符)
cluster.name <YOUR_CLUSTER_NAME> node.name <NODE_NAME> |
- 啓動 ./bin/elasticsearch
- 寫logstash的配置
logstash的配置包含input,filter和 output三部分,每一部分都有很多的插件可用,可支持讀寫解析file, socket, tcp, udp, jmx等。具體參見:http://logstash.net/docs/1.4.2/
另外filter中的grok,有個debug頁面非常不錯:http://grokdebug.herokuapp.com/
可以在這個頁面測試grok表達式和查看常用的grok pattern
例子: shipper.conf
input{ file { type => "java_error" path => ["/opt/tomcat/logs/catalina.out"] add_field => {"feature" => "tomcat"} codec => multiline { pattern => "(^\d+\serror)|(^.+Exception:?.*)|(^\s+at .+)|(^\s+... \d+ more)|(^\s*Caused by:.+)" what => "previous" } } file { type => "java_error" add_field => {"feature" => "pbq"} path => ["/opt/pbq/logs/bigada.log"] codec => multiline { pattern => "(^\d+\serror)|(^.+Exception:?.*)|(^\s+at .+)|(^\s+... \d+ more)|(^\s*Caused by:.+)" what => "previous" } } file { type => "java_error" add_field => {"feature" => "storm"} path => ["/opt/apache-storm-0.9.2-incubating/logs/worker-*.log","/opt/apache-storm-0.9.2-incubating/logs/seq.log"] codec => multiline { pattern => "(^\d+\serror)|(^.+Exception:?.*)|(^\s+at .+)|(^\s+... \d+ more)|(^\s*Caused by:.+)" what => "previous" } } file { type => "java_error" add_field => {"feature" => "kafka"} path => ["/opt/kafka_2.9.2-0.8.1/logs/server.log"] codec => multiline { pattern => "(^\d+\serror)|(^.+Exception:?.*)|(^\s+at .+)|(^\s+... \d+ more)|(^\s*Caused by:.+)" what => "previous" } } file { type => "pbp_seq" path => ["/opt/tomcat/logs/seq.log"] } file { type => "pbp_seq" path => ["/opt/pbq/logs/seq.log"] } file { type => "pbp_seq" path => ["/opt/apache-storm-0.9.2-incubating/logs/seq.log"] } }
filter{ if [type] == "java_error" { grok{ match => ["message", "%{JAVASTACKTRACEPART}|%{TIMESTAMP_ISO8601:timestamp} ERROR \[%{JAVACLASS:class}\] - <%{GREEDYDATA}>|%{TIMESTAMP_ISO8601:timestamp} %{DATA:class} \[ERROR\] <%{DATA:thread}> %{GREEDYDATA}"] tag_on_failure => ["grokfailure"] } }
if [type] == "pbp_seq"{ grok{ match => [ "message", "%{TIMESTAMP_ISO8601:timestamp} %{DATA:class} \[%{LOGLEVEL:log_level}\] <%{DATA:thread}> PBP Seq %{DATA:feature} \[%{DATA:sessionId}\] - \[%{DATA:seq}\] - \[%{INT:step:int}\] %{GREEDYDATA:status}" ] tag_on_failure => [ "grokfailure" ] } }
if "grokfailure" in [tags] { drop { } } }
output { stdout{} redis{ host => "10.1.110.22" data_type => "list" key => "logstash" } } |
這個shipper監控了我項目中的tomcat、pbq、storm、kafka的錯誤,以及從各個節點發出來的PBP Seq(我加在各個節點源碼裏打印出來的log)
用multiline插件合併了java exception的trace到一個logstash event的message裏面,同時用filter過濾了非目標的log,否則log數據量會很大。
如果是用redis做broker,那麼還需要一個index的conf,例子:central.conf
input{ redis { host => "10.1.110.22" type => "redis-input" data_type => "list" key => "logstash" } } output { stdout{} elasticsearch{ cluster => "logstash" } } |
其中cluster的值,對應elasticserach中所填的<YOUR_CLUSTER_NAME>
如果是我上面說的簡單的框架,那麼直接把shipper的output中redis部分替換成
elasticsearch{
host=> "10.1.110.22"
cluster =>"logstash"
}
- 啓動logstash
- 在各個節點上執行./logstash -f shipper.conf
- 在index節點上執行./logstash -f central.conf
- 在index節點上執行./logstash-web
- 瀏覽器打開http://<IP_OF_INDEX_NODE>:9292/可以看到Kibana界面
它已經自帶了一個logstash dashboard,進去就可以看到我們所監控的日誌了。
可以點選左下角的Fields,來查看想要看的fields
注:
Kibana有一個問題,它列出來的fields只能按照一個field進行排序。事實上Elasticsearch支持組合排序。這個問題已經進入了Kibana的JIRA,有望在未來解決。
貼一個我定義的問題收集界面:
至此,一個ELK的典型應用已經搭建完畢。但是,這裏有兩個問題:
- elasticsearch的index以日期爲單位,默認是不會刪除的,顯然得定期刪除。
- 每個logstash的情況必須也得監控起來,否則,如果一個節點上的logstash掛了,顯然其上的錯誤日誌是不會得到監控的。
爲了解決問題1,elasticsearch提供了一個python的腳本——curator,github源碼地址:https://github.com/elasticsearch/curator/
安裝步驟:https://github.com/elasticsearch/curator/wiki/Installation
wiki裏面寫的是服務器可以連接外網情況下,直接用pip安裝。
由於我的服務器無法連接外網,所以只能自己手動裝,步驟如下:
- 下載依賴包
- 按照上面順序,解壓後進入其目錄依次用命令python setup.py intall安裝
- 執行curator(參考https://github.com/elasticsearch/curator/wiki/Examples)
每天定期刪
python curator.py --host 10.1.110.22 delete --older-than 1
超過100MB刪
pythoncurator.py --host 10.1.110.22 delete --disk-space 0.1
注意:
curator似乎有點bug,我安裝完畢後,直接用curator命令會報錯,但是直接進入curator_master/curator/下面執行pythoncurator.py是可以用的。
解決問題2,由於我是選用了簡單框架,不含redis的broker的,所以我這裏可以給elasticsearch安裝插件kopf,官網地址:https://github.com/lmenezes/elasticsearch-kopf
該插件可以直接監控elasticsearch的集羣狀況,其中就包含其輸入的組件狀況,即logstash。
注:
如果是安裝了redis,使用了shipper+broker+index的框架,那麼kopf只能監控到index的狀況!
安裝步驟非常簡單
- git clonegit://github.com/lmenezes/elasticsearch-kopf.git
- cd elasticsearch-kopf
- git checkout 1.2
這裏參考對應版本
elasticsearch version |
kopf version |
0.90.X |
0.90 |
1.0.X |
1.0 |
1.1.X |
1.1 |
1.2.X |
|
- 然後把整個elasticsearch-kopf包拷到elasticsearch的服務器上,到elasticsearch的bin目錄執行
./plugin --install elasticsearch-kopf FILE:///<PATH>/elasticsearch-kopf.zip
- 瀏覽器打開http://<IP_OF_ELASTICSEARCH>:9200/_plugin/kopf/#/cluster可以看見elasticsearch的cluster狀況