Jusene's Blog

ELK Stack 日志分析平台

字数统计: 1.9k阅读时长: 9 min
2017/08/03 Share

ELK Stack

ELK Stack我们常常说这是日志分析平台,但是我认为这更应该是大数据分析平台,因为这不仅仅是可以分析日志,只是对于大部分公司来说这是分析日志绝佳的技术栈,所以这里我们也是根据公司业务做日志分析。

ELK Stack我们统称是Elasticsearch,LogStash,Kibana的集群构造,Elastcsearch我们大致介绍了下这是一个功能强大的搜索引擎和文档NoSQL数据库,LogStash我们可以理解是一个数据采集器和管道,Kibina将LogStash收集到的数据存在Elasticsearch的数据通过web展示出来。在这里Elasticsearch我们讲过了,LogStash是需要讲的重点,而Kibana只是数据展示可以自行摸索展示。

LogStash

为什么说是LogStash是数据采集器和管道呢?因为LogStash可以通过多种机制采集数据,如通过tcp/udp协议、文件、syslog、windows eventlog及stdin等,获取数据后可以通过内部filter插件对数据进行过滤修改操作,然后输出到stdout或者存储设备上。所以在这里我们也可以猜出LogStash的大致工作过程是stdin–>filter–>stdout的过程,这就像一个管道过一遍数据。

LogStash由JRuby编写,所以运行环境需要JVM虚拟机,而最新的LogStash需要JAVA 1.8的版本才可以运行,ELK的框架如下所示:

在数据的采集过程中我们加了了以broker,因为在生成环境中,生成日志是海量的,如果将日志持续不进行缓冲存入ES集群,ES集群的压力将会很大,也会影响ES集群的工作效率,所以我们加入broker来承上启下,而这个broker有很多选择,最常用的就是redis,redis可以很轻松的处理几十万的并发请求。

LogStash是一个高度插件化的程序,而我们常用的插件不外乎:

  • input
  • filter
  • codec
  • output

LogStash支持的数据类型:

  • Array:[items1,items2,…]
  • Boolean:true,false
  • Bytes:
  • Codec:编码器
  • Hash: key => value
  • Number
  • Password
  • Path: 问价路径
  • String: 字符串
    支持字段引用:[]
    条件判断:
  • ==、!=、<=、<、>、>=
  • =、!
  • in,not in
  • and,or

LogStash配置

input插件

  • LogStash测试一:从标准输入读入,从标准输出输出
1
~]# vim /etc/logstash/conf.d/simple.conf
2
input {
3
	stdin {}
4
}
5
6
output {
7
	stdout {
8
		codec => rubydebug
9
	}
10
}
11
~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/simple.conf
  • LogStash测试二:从文件中读入,从标准输出输出
1
~]# vim /etc/logstash/conf.d/fromfile.conf
2
input {
3
        file {
4
                path => "/var/log/messages"
5
                type => "system"
6
                start_position => "beginning"
7
        }
8
	}
9
10
	output {
11
        stdout {
12
                codec => rubydebug
13
        }
14
	}

file插件从文件中读入事件流,使用ruby gem的filewatch监听文件变化,并把监听的inode,marjor number,minor number,pos记录在.sincedb中,所以不必担心每次从头开始读取文件。

  • LogStash测试三:从udp中读入,从标准输出输出

为了测试udp读入数据,我们需要有程序往udp放松数据,而collectd是由c语言写的性能监听程序,我们可以是他的network模块来发送系统的健康数据。

1
~]# yum install -y collectd    #注意在epel源中
2
~]# vim /etc/collectd.conf
3
Hostname    "test"
4
LoadPlugin syslog
5
LoadPlugin cpu
6
LoadPlugin interface
7
LoadPlugin load
8
LoadPlugin memory
9
LoadPlugin network
10
<Plugin network>
11
        <Server "127.0.0.1" "25826">
12
        </Server>
13
</Plugin>
14
~]# systemctl start collectd
15
16
~]# vim /etc/logstash/conf.d/collectd.conf
17
input{
18
				udp {
19
        			port => 25826
20
        			type => "collectd"
21
        			codec => collectd{}
22
				}
23
			}
24
			output {
25
        		stdout {
26
                	codec => rubydebug
27
				}
28
			}

redis插件:从redis读取数据,支持redis channel和listen两种方式
下面会演示

filter插件

用于在将event通过output发出之前对其实现某些处理功能

其中在ELK中最重要的插件grok,用于分析并结构化文本数据:目前 是logstash中将非结构化日志数据转化为结构的🉑️查询数据的不二之选

模式定义位置:/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.1/patterns/grok-patterns

语法格式:
%{SYNTAX:SEMANTIC}

  • SYNTAX:预定于模式名称,即在/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.1/patterns/grok-patterns中预定义的正则匹配
  • SEMANTIC:匹配到的文本的自定义标识符,即匹配到的再次重命名成自定义的名字

如:匹配将 message => 10.211.55.24 GET /index.html 28 0.23,我们来拆解这个message信息。

1
input {
2
				stdin{}
3
			}
4
			filter {
5
				grok {
6
					    match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
7
				}
8
			}
9
			output {
10
				stdout {
11
					codec => rubydebug
12
				}
13
			}

匹配apache log:

1
input {
2
				file {
3
					path => ["/var/log/httpd/access_log"]
4
					type => "apachelog"
5
					start_position => "beginning"
6
				}
7
			}
8
9
			filter {
10
				grok {
11
					match => {"message" => "%{COMBINEDAPACHELOG}"}               #在/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.1/patterns/grok-patterns中预定义apache的日志格式
12
				}
13
			}
14
15
			output {
16
				stdout {
17
					codec => rubydebug
18
				}
19
			}

而nginx的日志格式在/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.1/patterns/grok-patterns中却没有,所以我们需要自己写:

1
~]# vim /usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.1/patterns/grok-patterns
2
#nginx log
3
NGUSERNAME [a-zA-Z\.\@\-\+_%]+
4
NGUSER %{NGUSERNAME}
5
NGINXACCESS %{IPORHOST:clientip} - %{NOTSPACE:remote_user} \[%{HTTPDATE:timestamp}\] \"(?:%(WORD:verb) %{NOTSPACE:request}(?:HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{NOTSPACE:http_x_forwarded_for}

ELK Stack配置过程

logstash采集服务器日志数据并存到reids中:

1
~]# vim /usr/logstash/conf.d/nginx-redis.conf
2
input {
3
        file {
4
                path => ["/var/log/nginx/access.log"]
5
                type => "nginxlog"
6
                start_position => "beginning"
7
        }
8
}
9
10
filter {
11
                grok {
12
                        match => {"message" => "%{NGINXACCESS}"}
13
                }
14
}
15
16
output {
17
                redis{
18
                        port => 6379
19
                        host => ["10.211.55.23"]
20
                        data_type => "list"
21
                        key => "logstash-%{type}"
22
}
23
}

从redis中取得数据并将数据输出到es集群:

1
~]# /usr/logstash/conf.d/redis-es.conf
2
input {
3
        redis {
4
                port => 6379
5
                host => ['10.211.55.23']
6
                data_type => "list"
7
8
                key => "logstash-nginxlog"
9
}
10
11
}
12
13
output {
14
15
        elasticsearch {
16
        hosts => "10.211.55.48:9200"
17
        index => "logstash-%{+YYYY.MM.dd}"
18
19
20
}
21
}

部署kibana

1
~]# vim /usr/local/kibana/config/kibana.yml
2
server.port: 5601
3
server.host: "0.0.0.0"
4
elasticsearch.url: "http://localhost:9200"
5
server.name: "my-kibana"
6
~]# sh /usr/local/kibana/bin/kibana

当然ELK的功能并没有这么简单,但是在这里整个ELK的工作过程应该很清楚了,还有LogStash太过重量级,作为agent收集日志对系统的性能损耗还是蛮严重的,如果有能力可以自行开发来收集数据,应该不是很难。kibana的功能可以对数据很快的进行整合,并以图表展示,有利于数据分析,而且在这里测试600条数据的搜索也是秒级就完成,再一次证明了ES的集权强大。

CATALOG
  1. 1. ELK Stack
  2. 2. LogStash
    1. 2.1. LogStash配置
    2. 2.2. input插件
    3. 2.3. filter插件
  3. 3. ELK Stack配置过程