本文系原创,转载请注明。
本文地址: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状况