ELK
ELK(ElasticSearch, Logstash, Kibana),三者组合在一起搭建实时的日志分析平台,目前大多数公司都在使用这套体系!
Elasticsearch 是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful 风格接口,多数据源,自动搜索负载等。
Logstash 是一个完全开源的工具,他可以对你的日志进行收集、过滤,并将其存储供以后使用(如,搜索)。
Kibana 也是一个开源和免费的工具,它 可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。
为什么要使用ELK
现阶段,随着各种项目的推进,基础服务越来越多,各个服务都是集群部署,服务器的数量也快速增长,这样就给我们的运维工作人员带来了更多的问题,比如:问题排查困难、运维管理困难、系统预警困难等等。因此就需要搭建一套集中式的日志收集、存储、分析系统,而ELK正好可以高效的解决这些问题。
项目架构
第一种ELK架构,如图,这是最简单的一种ELK架构方式。优点是搭建简单,易于上手。缺点是Logstash耗资源较大,运行占用CPU和内存高。另外没有消息队列缓存,存在数据丢失隐患。建议供学习者和小规模集群使用。
此架构首先由Logstash分布于各个节点上搜集相关日志、数据,并经过分析、过滤后发送给远端服务器上的Elasticsearch进行存储。Elasticsearch将数据以分片的形式压缩存储并提供多种API供用户查询,操作。用户亦可以更直观的通过配置Kibana Web Portal方便的对日志查询,并根据数据生成报表(详细过程和配置在此省略)。
第二种架构,如图,引入了消息队列机制,位于各个节点上的Logstash Agent先将数据/日志传递给Kafka(或者Redis),并将队列中消息或数据间接传递给Logstash,Logstash过滤、分析后将数据传递给Elasticsearch存储。最后由Kibana将日志和数据呈现给用户。因为引入了Kafka(或者Redis),所以即使远端Logstash server因故障停止运行,数据将会先被存储下来,从而避免数据丢失。
第三种架构,如图,此种架构将收集端logstash替换为beats,更灵活,消耗资源更少,扩展性更强。同时可配置Logstash 和Elasticsearch 集群用于支持大集群系统的运维日志数据监控和查询。
项目搭建
项目环境
OS:rhel6.5
server1(172.25.66.1):es、logstash、nginx、apache;
server2(172.25.66.2):es、logstash;
server3(172.25.66.3):es、kibana。
Elasticsearch
一、单机安装es
1、下载elasticsearch安装包并安装
从图中可以看出,当我们安装好es后,打开服务的时候报错了,报错原因为没有配置java环境,这是因为es是使用java开发的,所以我们接下来配置java环境。
2、安装jdk
可以看到,当我们安装完jdk后,我们的es服务就可以正常打开了。
3、打开服务后,会出现两个端口,分别为9200与9300端口
4、编辑es配置文件
cd /etc/elasticsearch/
vim elasticsearch.yml # 主配置文件
17 cluster.name: my-es # 集群的名称my-es
23 node.name: server1 # 当前节点的主机名
33 path.data: /var/lib/elasticsearch/ # 数据目录
37 path.logs: /var/log/elasticsearch/ # 日志目录
54 network.host: 172.25.66.1 # 当前主机的IP
58 http.port: 9200 # 对外端口号
修改完成后重启es服务
5、现在我们可以在浏览器中输入172.25.66.1:9200查看es数据
我们所看到的只有简单的数据,没有图形界面也没有分析等,所以我们选择安装相应图形界面的插件,方便分析处理数据
6、安装插件
cd /usr/share/elasticsearch/
cd /bin
./plugin list # 查看已经安装的插件
/usr/share/elasticsearch/bin/plugin install file:/root/elk/elasticsearch-head-master.zip
安装好后,我们用./plugin list查看
7、这次我们在浏览器中重新输入172.25.66.1:9200/_plugin/head就可以看到es的图形界面了
8、在该web界面下导入一组数据
点击复合查询,在文本框输入:
{"username":"guodong","passwd":"123"}
点击提交请求,然后再右边就会反馈结果
二、搭建es集群
Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。
1、在server2和server3上安装elasticsearch-2.3.3.rpm和jdk-8u121-linux-x64.rpm
2、编辑server1上的es配置文件elasticsearch.yml
68行 discovery.zen.ping.unicast.hosts: ["server1", "server2","server3"]
# 表示该集群由三台主机构成,主机名分别是server1,server2和server3
将修改好的配置文件发送给server2和server3上,在server2上和server3上修改配置文件中的sevrername和ip
3、启动server2和sevrer3上的服务
/etc/init.d/elasticsearch start
启动服务后,在es的web界面刷新就可以看到,server2与server3已经加入my-es集群
4、为了将集群中三台主机所负责的功能模块分开,我们在配置文件elasticsearch.yml中设定:
#server1是主节点,同时承担http查询任务
vim elasticsearch.yml
23 node.name: server1
24 node.master: true
25 node.data: false
26 http.enabled: true
# server2负责存储数据和http查询任务
vim elasticsearch.yml
23 node.name: server2
25 node.master: false
26 node.data: true
27 http.enabled: true
# server3和server2相同
vim elasticsearch.yml
23 node.name: server2
25 node.master: false
26 node.data: true
27 http.enabled: true
5、重启所有节点上的服务
6.查询集群的状态
curl -XGET ‘http://172.25.66.1:9200/_cluster/health?pretty=true’
至此,es集群搭建完毕
Logstash
Logstash是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您喜欢的“存储库”中。(我们的存储当然是Elasticsearch。)
1、安装logstash工具
2、命令行运行
在终端中,像下面这样运行命令来启动Logstash进程:
/opt/logstash/bin/logstash -e ‘input{stdin{}} output{stdout{codec=>rubydebug}}’
执行命令后,你会发现终端在等待你的输入。我们敲入Hello World,回车,看看会返回什么结果
命令行中的标准输出stdout中可以定义输出格式,比如codec=>rubybug,将输出格式该为ruby格式
3、将采集到的数据发送到es中
/opt/logstash/bin/logstash -e ‘input{stdin{}}output{elasticsearch{host=>[“172.25.66.1”] index=>“logstash-%{+YYYY.MM.dd}”}}’
执行这样的命令后,我们在终端进行输入,不会看到输出结果,因为logstash只将数据发送到了es中,并没有输出在终端
可以看到我们在输入两条数据后回车,终端并没有输出内容,我们可以在es的web界面中查看,数据是否到达es,在es的web界面中点击数据浏览
es中成功收到logstash发送来的数据
4、将logstash中的数据同时发送到es与终端
/opt/logstash/bin/logstash -e ‘input{stdin{}}output{elasticsearch{hosts=>[“172.25.66.1”] index=>“logstash-%{+YYYYY.MM.dd}”} stdout{codec=>rubydebug}}’
可以看到我们在输入数据后,终端返回了结果,我们再看看es中是否收到数据
5、上边的各种模块都是直接在命令行选择模块,输入或者输出。我们也可以在文件中编写使用的模块,选择输入和输出
cd /etc/logstash/conf.d/
vim es.conf # 文件名,可以随意取
input {
stdin {} # 输入是标准终端输入standard input
}
output {
elasticsearch { # 第一个输出是到elasticsearch
hosts => ["172.25.66.1"] # elasticsearch所在的主机
index => "logstash-%{+YYYY.MM.dd}"
}
stdout { # 第二个输出是标准终端输出
codec => rubydebug # 输出的风格是rubydebug
}
}
在终端的运行情况
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/es.conf
6、logstash中的syslog模块
syslog可能是运维领域最流行的数据传输协议了。当你想从设备上收集系统日志的时候,syslog应该会是你的第一选择,尤其是网络设备,比如思科中的syslog几乎是唯一可行的方法。
我们将server1作为一个日志收集器,用来收集server2的系统日志
(1):编辑一个使用syslog模块的文件
vim message.conf
input {
syslog {
port => 514 # 输入是server2的日志,同步日志端口为514/udp
}
}
output {
# elasticsearch {
# hosts => ["172.25.66.1"] # 输出到server1的elasticsearch
# index => "message-%{+YYYY.MM.dd}"
# }
stdout {
codec => rubydebug # 输出到标准屏幕输出
}
}
(2):在server2中配置rsyslog
vim /etc/rsyslog.conf
*.* @@172.25.66.1:514
/etc/init.d/rsyslog restart # 重新打开rsyslog服务
(3):在server1以终端占用的方式执行
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/message.conf
(4):重新打开一个终端连接server1查看端口
(5):现在在server1上可以收集到server2上的日志信息,在server2上执行logger tigger,在server1上立即可以看到trigger的输出
7、利用logstash中的模块将日志记录中的多行输出变为一行
(1):查看elasticsearch的日志记录文件
cd /var/log/elasticsearch
cat my-es.log
看到以[]为界线的日志有时候并不在一行
(2):利用filter对输入进行过滤处理再指定输出
vim /etc/logstash/conf.d/message.conf
input {
file {
path => "/var/log/elasticsearch/my-es.log" # 待处理日志所在位置
start_position => "beginning" # 从日志的开始处处理
}
}
filter {
multiline {
pattern => "^\["
negate => true
what => "previous"
}
}
output {
elasticsearch {
hosts => ["172.25.66.1"]
index => "es-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}
(3):在终端执行操作
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/message.conf
# 因为在终端出有大量的java日志,所以就不再展示
8、使用grok正则捕获插件使httpd服务的日志按照指定格式输出
(1):编辑一个处理httpd日志的文件test.conf
vim test.conf
input {
stdin {} # 输入是终端标准输入
}
filter {
grok {
match => { "message" => "%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}" }
# 利用grok对输入进行正则匹配,然后按照指定格式输出
}
}
output {
stdout {
codec => rubydebug # 标准终端输出
}
}
(2):终端执行
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/test.conf
172.25.66.2 GET /index.html 15888 0.043 # 标准输入
9、引用系统中的变量对httpd服务的输出日志进行处理,按照指定格式输出
vim message.conf
input {
file {
path => ["/var/log/httpd/access_log","/var/log/httpd/error_log"] # 日志文件所在的位置
start_position => "beginning" # 开始同步的位置=>文件开始处
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
# 引用变量COMBINEDAPACHELOG
}
}
output {
elasticsearch {
hosts => ["172.25.66.1"]
index => "apache-%{+YYYY.MM.dd}"
}
stdout {
codec => rubydebug
}
}
终端执行并使用浏览器访问server1的apache主页
采用消息队列对ES与Logstash进行解耦
在生产环境中,从每台应用服务器运行Logstash进程并将数据直接发送到ES中,显然不是第一选择,原因有三:第一,过多的客户端连接对ES是一种额外的压力;第二,网络抖动会影响到Logstash进程,进而影响生产应用;第三,运维人员未必愿意在生产服务器上部署Java,或者让Logstash跟业务代码争夺java资源。所以,在实际运用中,Logstash进程会被分为两个不同的角色。运行在应用服务器上的尽量减轻运行压力,只做读取和转发,这个角色叫Shipper;运行在独立服务器上的完成数据解析处理,负责写入ES的角色,叫做Indexer。
Logstash作为无状态的软件,配合消息队列系统,可以很轻松地做到线性扩展,由Shipper采集数据存储到消息队列系统中,这里我们使用redis,再由Indexer从redis中拿数据,发送给ES。
1、在server2中安装redis
tar zxf redis-3.0.6.tar.gz
cd redis-3.0.6
make
make install
打开redis
cd /root/redis-3.0.6/utils/
./install_server.sh
查看redis端口
2、在server1上安装nginx
rpm -ivh nginx-1.8.0-1.el6.ngx.x86_64.rpm
在logstash的配置目录下编辑nginx.conf文件对nginx日志进行分析
vim nginx.conf
input {
file {
path => "/var/log/nginx/access.log" # nginx的日志
start_position => "beginning"
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG} %{QS:x_forwarded_for}" } # 在apache日志的前提下再加上自己的日志输出
}
}
output {
redis {
host => ["172.25.66.2"]
port => 6379 # 输出到server2的redis端口
data_type => "list" # 在redis中以列表形式存储
key => "logstash:redis" # 定义列表形式的键值对
}
stdout {
codec => rubydebug
}
}
修改nginx的日志权限
chmod 644 /var/log/nginx/access.log # 保证对所有用户可写
在终端执行处理nginx日志的文件
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/nginx.conf
在物理机进行压测ab -c 1 -n 10 http://172.25.66.1/index.html在server1上看日志输出
现在我们的Shipper已经将应用服务器上的nginx服务的日志数据采集并存储到了消息队列redis中,接下来我们要在独立服务器中,让Indexer从redis中获取数据并发送到ES
3、在server2中安装logstash
rpm -ivh logstash-2.3.3-1.noarch.rpm
cd /etc/logstash/conf.d/
vim es.conf
input {
redis { # 从redis中拿数据
host => "172.25.66.2"
port => 6379
data_type => "list"
key => "logstash:redis" # 格式和上边的保持一致
}
}
output {
elasticsearch { # 输出是将数据输出到elasticsearch中
hosts => ["172.25.66.1"]
index => "nginx-%{+YYYY.MM.dd}"
}
}
/opt/logstash/bin/logstash -f /etc/logstash/conf.d/es.conf
在网页中刷新,出现nginx索引
kibana
Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的,Kibana因其丰富的图表类型和漂亮的前端界面,被很多人理解成一个统计工具。而我个人认为,ELK这一套体系,不应该和hadoop体系同质化。定期的离线报表,不是Elasticsearch专长所在(多花费分词、打分这些步骤在高负载压力环境上太奢侈了),也不应该由kibana来完成(每次刷新都是重新计算)。kibana的使用场景应该集中在两方面:
实时监控。通过histogram面板,配合不同条件的多个queries可以对一个事件走很多个维度组合出不同的时间序列走势。时间序列数据是最常见的监控报警了。
问题分析。通过Kibana的交互式界面可以很快的将异常时间或者事件范围缩小到秒级别或者个位数。
1、在server3上安装kibana
rpm -ivh kibana-4.5.1-1.x86_64.rpm
2、编辑其主配置文件
cd /opt/kibana/config/
vim kibana.yml
打开服务并查看端口
/etc/init.d/kibana start
3、在server3上配置kibana对获得的数据进行分析
在浏览器中输入172.25.66.3:5601进入操作界面
(1):指定一个可以匹配一个或多个Elasticsearch索引的index pattern,这里我们匹配nginx
点击create添加indnex pattern,第一个被添加的pattern会自动被设置为默认值。
4、我们在server1与server2中执行logstash,并且使用ab工具对server1中的nginx进行压侧,随后ES收到的数据就会在kibana中展示出来
点击左上角的Discover,在这个页面上,我们可以提交搜索请求,过滤结果,然后检查返回的文档里的数据
4、在Visualize页转换数据成图表
我们选择柱状图来显示
上面我们使用172.25.66.11主机对server1的nginx做了10次压测,接下来我们再使用172.25.66.250主机对server1主机的nginx做5次压测
至此,我们的ELK日志分析平台搭建完毕