ELK是对Elasticsearch、Logstash、Kibana整合平台的简称。在日常的运维工作中,要实时监控服务器的业务、系统和硬件状态,除了使用监控之外,还需要搜集大量的日志来进行分析。但是在面对海量的服务器和集群时,通过单台登录查询的方式显然是不可能的,对于不同时间段和集群日志的分析仅仅通过简单的脚本来统计也是难以实现。ELK日志平台通过日志搜集,查询检索和前端展示的方式帮我们实现了这样的功能。
Elasticsearch是个开源分布式搜索引擎,具有分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等特性。http://www.elastic.co/cn
Logstash是一个完全开源的工具,他可以对日志进行收集、分析,并将其存储.
Kibana 是一个开源和免费的工具,可以为 Logstash 和 ElasticSearch 提供的日志分析友的 Web 界面.
ELKStack 部署
Elasticsearch部署
Elasticsearch 需要安装java环境,首先需要安装JDK.
1
2
3
4
5
|
[root@node1]
# yum install -y java-1.8.0-openjdk
[root@node1]
# java -version
openjdk version
"1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-b15)
OpenJDK 64-Bit Server VM (build 25.111-b15, mixed mode)
|
安装Elasticsearch,可以通过在官方下载rpm包进行安装,由于yum安装的版本比较老,推荐使用在官方下载rpm包的方式安装。
推荐下载使用5.6的版本:
http://www.elastic.co/downloads/elasticsearch
yum 安装Elasticsearch:
1
|
yum
install
-y elasticsearch
|
LogStash部署
和Elasticsearch一样,在开始部署LogStash之前也需要你的环境中正确的安装的JDK。可以下载安装Oracle的JDK或者使用 yum安装openjdk.这里部署node2上。同样的,如果是在不同的机器上安装Logstash,需要再次下载安装PGP key:
1
|
rpm --
import
https:
//packages
.elastic.co
/GPG-KEY-elasticsearch
|
添加YUM仓库:
1
2
3
4
5
6
7
|
[root@node2 ~]
# vim /etc/yum.repos.d/logstash.repo
[logstash-2.3]
name=Logstash repository
for
2.3.x packages
baseurl=https:
//packages
.elastic.co
/logstash/2
.3
/centos
gpgcheck=1
gpgkey=https:
//packages
.elastic.co
/GPG-KEY-elasticsearch
enabled=1
|
安装Logstash:
1
|
[root@node2 ~]
# yum install -y logstash
|
Kibana部署
如果是在不同的机器上部署Kibana,需要安装PGP key.这里部署在node1上,所以不必再次安装。
添加yum仓库:
1
2
3
4
5
6
7
|
[root@node1 ~]
# vim /etc/yum.repos.d/kibana.repo
[kibana-4.5]
name=Kibana repository
for
4.5.x packages
baseurl=http:
//packages
.elastic.co
/kibana/4
.5
/centos
gpgcheck=1
gpgkey=http:
//packages
.elastic.co
/GPG-KEY-elasticsearch
enabled=1
|
安装Kibana:
1
|
[root@node1 ~]
# yum install -y kibana
|
在实际的生产环境,可以创建本地的YUM仓库,使用Cobbler来创建自己的YUM仓库:
1
2
3
4
5
6
7
|
[root@log-node1 ~]
# cobbler repo add --name=logstash-2.3 \
--mirror=http:
//packages
.elastic.co
/logstash/2
.3
/centos
--arch=x86_64 --breed=yum
[root@log-node1 ~]
# cobbler repo add --name=elasticsearch2 \
--mirror=http:
//packages
.elastic.co
/elasticsearch/2
.x
/centos
--arch=x86_64 --breed=yum
[root@log-node1 ~]
# cobbler repo add --name=kibana4.5 \
--mirror=http:
//packages
.elastic.co
/kibana/4
.5
/centos
--arch=x86_64 --breed=yum
[root@log-node1 ~]
# cobbler reposync
|
配置Elasticsearch
修改elasticsearch的配置文件:
1
2
3
4
5
6
7
8
9
|
[root@node1 ~]
# cd /etc/elasticsearch/
[root@node1 elasticsearch]
# grep "^[a-Z]" elasticsearch.yml
cluster.name: myes
#自定义cluster名称
node.name: node1
#本地节点主机名
path.data:
/data/es-data
#数据路径,如果是自定义的,需要修改目录权限elasticsearch
path.logs:
/var/log/elasticsearch
#日志路径
bootstrap.memory_lock:
true
#在启动时锁定内存,提升性能
network.host: 172.16.10.20
#本地主机名
http.port: 9200
#监听的端口
|
修改es内存参数,使最大内存和最小内存保持一致: (这里一般设置es内存为不超过服务器总内存的50%,最大不超过32G,最小应该大于2G)
vim /etc/elasticsearch/jvm.options
1
2
3
4
|
# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
-Xms4g
-Xmx4g
|
要使设置的内存生效,需要修改启动脚本的参数:
1
2
3
|
vim
/usr/lib/systemd/system/elasticsearch
.service
LimitNOFILE=65536
LimitMEMLOCK=infinity
# 设置内存不限制
|
修改数据目录的权限,并启动:
1
2
|
chown
-R elasticsearch.elasticsearch
/data/es-data
systemctl start elasticsearch
|
验证是否启动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@node1 elasticsearch]
# curl 172.16.10.20:9200
{
"name"
:
"node1"
,
"cluster_name"
:
"myes"
,
"cluster_uuid"
:
"0lJjtxjBRfeMO9WY8bl3-Q"
,
"version"
: {
"number"
:
"2.4.3"
,
"build_hash"
:
"d38a34e7b75af4e17ead16f156feffa432b22be3"
,
"build_timestamp"
:
"2016-12-07T16:28:56Z"
,
"build_snapshot"
:
false
,
"lucene_version"
:
"5.5.2"
},
"tagline"
:
"You Know, for Search"
}
|
1
2
3
4
5
|
[root@node1 elasticsearch]
# curl -i -XGET 'http://172.16.10.20:9200/_count?'
HTTP
/1
.1 200 OK
Content-Type: application
/json
; charset=UTF-8
Content-Length: 59
{
"count"
:0,
"_shards"
:{
"total"
:0,
"successful"
:0,
"failed"
:0}}
|
安装head:
在elasticsearch 5.x版本以后不再支持直接安装head插件,而是需要通过启动一个服务方式,git地址:https://github.com/mobz/elasticsearch-head
下载此zip包到服务器。同时需要安装npm, NPM的全称是Node Package Manager,是随同NodeJS一起安装的包管理和分发工具,它很方便让JavaScript开发者下载、安装、上传以及管理已经安装的包。
1
2
3
4
5
6
7
|
[root@node1 ~]
# git clone git://github.com/mobz/elasticsearch-head.git
[root@node1 ~]
# yum install -y npm
[root@node1 ~]
# cd elasticsearch-head
[root@node1 elasticsearch-
head
]
# npm install grunt -save
[root@node1 elasticsearch-
head
]
# ll node_modules/grunt #确认生成文件
[root@node1 elasticsearch-
head
]
# npm install #执行安装
[root@node1 elasticsearch-
head
]
# npm run start & 后台启动
|
使用9100端口登录,此时无法查看到节点的状态:
这时,需要开启跨域访问支持,然后重启elasticsearch服务:
[root@node2 elk]# vim /etc/elasticsearch/elasticsearch.yml ,末尾添加:
1
2
3
4
5
|
# 允许使用es-head插件访问,在5.6的版本中需要添加这两项参数
http.cors.enabled:
true
http.cors.allow-origin:
"*"
[root@node2 elk]
# systemctl restart elasticsearch
|
两个节点都修改配置文件后,显示节点已经加入集群:
添加Elasticsearch集群
当使用head访问Elasticsearch时,由于只有一个主分片,所以显示的yellow的状态,为了保证可靠性,我们需要再添加一个副分片。
同理,在node2上也安装上Elasticsearch,配置文件修改为本地的参数,同时,配置单播参数,自动发现node2,只需在node2上配置单播即可。
1
2
3
4
5
6
7
8
9
|
[root@node2 elasticsearch]
# grep "^[a-Z]" elasticsearch.yml
cluster.name: myes
node.name: node2
path.data:
/data/es-data
path.logs:
/var/log/elasticsearch
bootstrap.memory_lock:
true
network.host: 172.16.10.21
http.port: 9200
discovery.zen.
ping
.unicast.hosts: [
"172.16.10.20"
,
"172.16.10.21"
]
|
重新启动node2上的Elasticsearch,在node1上使用head登录,添加索引值:
此时,发现node1和node2分片信息已经加入进来,图中产生的分片,需要在"any request" 中添加对应的索引。
带的为master 节点,主节点会展示当前的状态。
Elasticsearch的健康检查
https://www.elastic.co/guide/en/elasticsearch/guide/current/_cluster_health.html
Elasticsearch提供了自身用于健康检查的API,会返回一组JSON的数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# curl -XGET http://172.16.10.20:9200/_cluster/health
# curl -XGET http://172.16.10.20:9200/_cluster/health?pretty=true
{
"cluster_name"
:
"myes"
,
"status"
:
"green"
,
"timed_out"
:
false
,
"number_of_nodes"
: 2,
"number_of_data_nodes"
: 2,
"active_primary_shards"
: 11,
"active_shards"
: 22,
"relocating_shards"
: 0,
"initializing_shards"
: 0,
"unassigned_shards"
: 0,
"delayed_unassigned_shards"
: 0,
"number_of_pending_tasks"
: 0,
"number_of_in_flight_fetch"
: 0,
"task_max_waiting_in_queue_millis"
: 0,
"active_shards_percent_as_number"
: 100.0
}
|
同时,官方还提供了多样监控信息,可以通过cat API的方式来返回需要的数据:
https://www.elastic.co/guide/en/elasticsearch/guide/current/_cat_api.html
1
2
|
# curl -XGET http://172.16.10.20:9200/_cat/health
1482981911 11:25:11 myes green 2 2 22 11 0 0 0 0 - 100.0%
|
对集群中的任意一个节点去查询,此节点都会从搜集到整个集群的信息进行返回:
1
2
3
4
|
# curl -XGET http://172.16.10.20:9200/_cat/nodes?v
host ip heap.percent
ram
.percent load node.role master name
172.16.10.20 172.16.10.20 5 93 0.83 d * node1
172.16.10.21 172.16.10.21 3 74 0.03 d m node2
|
1
2
3
4
|
# curl -XGET http://172.16.10.21:9200/_cat/nodes?v
host ip heap.percent
ram
.percent load node.role master name
172.16.10.20 172.16.10.20 5 93 0.92 d * node1
172.16.10.21 172.16.10.21 3 74 0.01 d m node2
|
Elasticsearch有green
/yellow
/red
三种不同的状态级别,green 表示所有节点分片正常,yellow 表示主节点分片正常,副本节点分片存在故障或丢失,red 表示主节点分片丢失,在搜索时只能返回部分结果。
提示: 在生产环境部署前,需要调整文件描述符数量和maximum map count 数量,否则, 在修改之后需要重启Elasticsearch。
如: sysctl -w vm.max_map_count=262144
Logstash日志搜集
Logstash可以使用多种方式处理数据。其中常用的是使用INPUT,OUTPUT,FILTER等功能对数据进行搜集和处理。可以使用TCP,file, rsyslog等方式来搜集不同的日志。
简单示例:
1
2
3
4
5
|
# /opt/logstash/bin/logstash -e 'input { stdin{} } output { stdout{} }'
Settings: Default pipeline workers: 1
Pipeline main started
hello
2016-12-29T04:00:39.937Z node2 hello
|
指定格式输出:
1
2
3
4
5
6
7
8
9
|
# /opt/logstash/bin/logstash -e 'input { stdin{} } output { stdout{ codec => rubydebug} }'
Pipeline main started
errttt
{
"message"
=>
"errttt"
,
"@version"
=>
"1"
,
"@timestamp"
=>
"2016-12-29T07:24:41.016Z"
,
"host"
=>
"node2"
}
|
Logstash使用插件将数据输入输出到不同的对象。
使用elasticsearch插件,output到Elasticsearch中:
https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html
手动测试:
1
2
3
4
5
|
# /opt/logstash/bin/logstash -e 'input { stdin{} } output { elasticsearch { hosts => ["172.16.10.20:9200"] index => "logstash-%{+YYYY.MM.dd}" } }'
Settings: Default pipeline workers: 1
Pipeline main started
rrrrr
ooooooooooooo
|
在web界面显示收取的信息:
Logstash-Input-file
在实际的生产环境中,如果要使用Logstash来搜集文件需要在每台主机上安装Logstash,因为只有使用logstash才能读取本地的INPUT file,当然,也可以通过网络和其他方式将文件内容发送给Logstash.
按照上面手动执行的方式实现是不现实的,通常会编辑一个配置文件,在启动logstash的时候指定此配置文件,就可以将文件输出记录到系统中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# vim /etc/logstash/conf.d/demo.conf # 默认文件的存放目录,可以在logstash的启动脚本中更改
input{
stdin{}
# input 插件
}
filter{
# filter可以没有,可以为空
}
output{
elasticsearch {
hosts => [
"172.16.10.21:9200"
]
# output中的插件 => 表示等于,[]表示数组,此处可以加多个IP
index =>
"logstash-%{+YYYY.MM.dd}"
# output中的index插件
}
stdout{
codec => rubydebug
}
}
|
启动logstash,并使用 -f 指定文件:
1
2
3
4
5
6
7
8
9
10
|
# /opt/logstash/bin/logstash -f /etc/logstash/conf.d/demo.conf
Settings: Default pipeline workers: 1
Pipeline main started
test1
#手动输入
{
"message"
=>
"test1"
,
"@version"
=>
"1"
,
"@timestamp"
=>
"2016-12-29T07:55:12.738Z"
,
"host"
=>
"node2"
}
|
这样在Elastic上就可以看到需要展示的数据。
使用Logstash搜集本地日志文件,并output到Elasticsearch
在node2主机上编辑Logstash的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# cat /etc/logstash/conf.d/file.conf
input{
file
{
path => [
"/var/log/messages"
,
"/var/log/secure"
]
type
=>
"system-log"
start_position =>
"beginning"
}
}
filter{}
output{
elasticsearch {
hosts => [
"172.16.10.20:9200"
]
index =>
"system-log-%{+YYYY-MM}"
}
}
|
启动Logstash:
1
|
# /opt/logstash/bin/logstash -f /etc/logstash/conf.d/file.conf
|
启动之后如下图:
上面的启动方式是前台启动,也可以使用系统默认的后台启动方式 :
1
|
/etc/init
.d
/logstash
start
|
Logstash if条件判断
在需要搜集多种日志到不同的index中时,需要使用If条件判断的方式,将对应的不同日志,放到不同的索引中,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[root@node2 ~]
# cat /etc/logstash/conf.d/file.conf
input{
file
{
path => [
"/var/log/messages"
,
"/var/log/secure"
]
type
=>
"system-log"
# 指定TYPE,被监控的文件不能有type字段
start_position =>
"beginning"
}
file
{
path =>
"/var/log/nginx/access.log"
type
=>
"nginx-log"
start_position =>
"beginning"
}
}
filter { }
output {
if
[
type
] ==
"system-log"
{
# 根据type判断写入哪个index
elasticsearch {
hosts => [
"172.16.10.20:9200"
]
index =>
"system-log-%{+YYYY-MM}"
}
}
if
[
type
] ==
"nginx-log"
{
elasticsearch {
hosts => [
"172.16.10.20:9200"
]
index =>
"nginx-log-%{+YYYY-MM}"
}
}
}
|
Logstash 正则匹配多行日志
在搜集日志的时候,默认是以事件的形式来逐条收集,但是如果同一事件日志内容有多行,如java日志,依旧使用默认的逐条收集的话,会造成日志格式支离破碎难以阅读,所以根据日志每段开始或者结尾的规律进行正则匹配,来收集日志也是非常重要的。
1
2
|