一、ELK日志分析系统介绍 1.1传统的日志统计及分析方式
日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及时采取措施纠正错误。
通常,日志被分散的储存不同的设备上。如果你管理数十上百台服务器,你还在使用依次登录每台机器的传统方法查阅日志。这样是不是感觉很繁琐和效率低下。当务之急我们使用集中化的日志管理,例如:开源的syslog,将所有服务器上的日志收集汇总。
集中化管理日志后,日志的统计和检索又成为一件比较麻烦的事情,一般我们使用grep、awk和wc等Linux命令能实现检索和统计,但是对于要求更高的查询、排序和统计等要求和庞大的机器数量依然使用这样的方法难免有点力不从心。 1.2 ELK介绍
开源实时日志分析ELK平台能够完美的解决我们上述的问题,ELK由ElasticSearch、Logstash和Kiabana三个开源工具组成。
(1)、Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
(2)、Logstash是一个完全开源的工具,可以对日志进行收集、过滤,并将其存储供以后使用(如:搜索)。 (3)、Kibana 也是一个开源和免费的可视化工具,可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。 1.2.1 Elasticsearch介绍
Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎,Lucene是当前行业内最先进、性能最好的、功能最全的搜索引擎库。但Lucene只是一个库。无法直接使用,必须使用Java作为开发语言并将其直接集成到应用中才可以使用,而且Lucene非常复杂,需要提前深入了解检索的相关知识才能理解它是如何工作的。
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
但Elasticsearch不仅仅值是Lucene库和全文搜索,它还有以下用途: ? 分布式的实时文件存储,每个字段都被索引并可被搜索
? 分布式的实时分析搜索引擎
? 可以扩展到上百台服务器,处理PB级结构化或非结构化数据 1.2.2 Elasticsearch基础概念
Elasticsearch有几个核心概念。从一开始理解这些概念会对整个学习过程有莫大的帮助。 时(NRT)
Elasticsearch是一个接近实时的搜索平台。意味着检索一个文档直到这个文档能够被检索到有一个轻短暂的延迟(通常是1秒)。 (2)、集群(cluster)
集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字很重要,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好习惯,但是使用默认值来进行测试/开发也可以。 (3)、节点(node)
节点是值集群中的具体服务器,作为集群的一部分,它可存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机名字,这个名字会在服务启动时赋予节点。这个名字对于管理者非常重要,因为在管理过程中,需要确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点。
节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着如果在网络中启动了若干个节点,并假定它们能够相互发现彼此,那么各节点将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
在一个集群里,可以拥有任意多个节点。并且,如果当前网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。 (4)、索引(index)
索引是指一个拥有相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。每个索引均由一个名字来标识(必须全部是小写字母的),并且当要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。 “索引”有两个意思:
(1)、接近实
A.作为动词,索引指把一个文档“保存”到 ES 中的过程,某个文档被索引后,就可以使用 ES 搜索到这个文档
B.作为名词,索引指保存文档的地方,相当于数据库概念中的“库”
为了方便理解,我们可以将 ES 中的一些概念对应到我们熟悉的关系型数据库上:
ES DB 索引 库 类型 表 文档 行 在一个集群中,可以定义任意多的索引。 (5)、类型(type)
在一个索引中,可以定义一种或多种类型。类型是指索引的一个逻辑上的分类/分区,其语义可自定义。通常情况下,会为具有一组共同字段的文档定义一个类型。比如说,我们假设运营一个博客平台并且将所有的数据存储到一个索引中。在这个索引中,可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。 (6)、文档(document)
文档是指可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个普遍存在的互联网数据交互格式。
在一个index/type里面,可以存储任意多的文档。注意,尽管一个文档物理上存在于一个索引之中,但文档必须被赋予一个索引的type。
(7)、分片和复制(shards & replicas)
一个索引可以存储超出单个节点磁盘限制的大量数据。比如以下情况,一个具有10亿文档的索引占据1TB的磁盘空间,而集群中任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。
为了解决此问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当创建一个索引的时候,可以指定想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。 分片之所以重要,主要有两方面的原因: A.允许水平分割/扩展内容容量
B.允许在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量 至于一个分片怎样分布,它的文档怎样聚合搜索请求,是完全由Elasticsearch管理的,用户对此是透明的。 在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点无原因就处于离线状态,或者由于任何原因消失了的情况下,Elasticsearch提供一个故障转移机制,它允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。 复制之所以重要,有两个主要原因:
A.在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。
B.扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行
总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,可以在任何时候动态地改变复制的数量,但是事后不能改变分片的数量。
默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。 1.2.3 Logstash介绍
Logstash的主要功能是收集和过滤,类似于shell中的管道符“|”。它的工作过程是将数据进行收集,并对收集的入职根据策略进行分类和过滤,最后进行输出.
实际上,Logstash 是用不同的线程来实现收集、过滤、输出功能的,可运行 top 命令然后按下 H 键查看线程。
数据在线程之间以事件的形式流传。并且,logstash 可以处理多行事件。
Logstash 会给事件添加一些额外信息。其中最重要的就是 @timestamp,是用来标记事件的发生时间。因为这个字段涉及到 Logstash 的内部流转,所以必须是一个json对象,如果自定义给一个字符串字段重命名为 @timestamp 的话,Logstash会直接报错,那么就需要使用filters/date插件来管理这个特殊字段。额外信息还包括以下几个概念: A.host 标记事件发生在哪里。 B.type 标记事件的唯一类型。
C.tags 标记事件的某方面属性。这是一个数组,一个事件可以有多个标签。
也可以自定义个事件添加字段或者从事件里删除字段。事实上事件本身就是是一个 Ruby对象。 1.2.4 Kibana介绍
Kibana是一个开源的分析与可视化平台,用于和Elasticsearch一起使用,可以用kibana搜索、查看、交互存放在Elasticsearch索引里的数据,使用各种不同的图表、表格、地图等kibana能够很轻易地展示高级数据分析与可视化。
Kibana对大量数据的呈现非常清晰。它简单、基于浏览器的接口能快速创建和分享实时展现Elasticsearch查询变化的动态仪表盘。
Kibana支持LInux、Windows等操作系统。 版本要求:Kibana要求安装版本要和Elasticsearch一致。 Kibana版本 5.X 5.1 5.1 5.1 5.1.0 Elasticsearch版本 2.X 5.0 5.1 5.2 5.1.1 是否支持 不支持 不支持 支持 支持(会有提示升级的警告) 支持 本次安装部署的Kibana版本为4.3.1版本,对应Elasticsearch版本为 二 ELK安装配置 2.1 系统架构介绍
此架构的工作流程是 Logstash agent(shipper)监控并过滤客户端日志,将过滤后的日志内容发给Redis(indexer),此处的Redis既充当消息队列的角色,由于其优越的持久化机制也被用来做缓存,然后Logstash Server(indexer)从Redis的对应位置拿出日志数据,并将其输出到ElasticSearch中,ElasticSearch获取到数据后开始生产索引,然后使用Kibana进行页面展示。这是一个完成的日志收集、存储、检索流程。 2.2 安装Elasticsearch OS:Centos 6.5
elk-node1:
在两台主机上分别安装Elasticsearch。 准备工作:
(1)、关闭防火墙、Selinux # iptables -F
# chkconfig iptables off # setenforce 0
# vim /etc/sysconfig/selinux 改为:
SELINUX=disabled (2)、配置java环境
# yum install -y java # java -version
OpenJDK 64-Bit Server VM (build 24.151-b00, mixed mode)
(3)、配置主机信息 node1、node2节点分别配置: 其中node1是master,node2是slave # vim /etc/hosts 2.2.1 Yum方式安装
(1)、下载并安装GPG-Key # rpm --import (2)、添加yum仓库
[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages gpgcheck=1 enabled=1
(3)、安装elasticsearch # yum install -y elasticsearch (4)、安装测试软件 # yum install -y redis # yum install -y nginx (5)、部署配置 # mkdir -p /data/es-data elk-node1:
# vim /etc/elasticsearch/elasticsearch.yml cluster.name: nova ##集群名称
node.name: elk-node1 ##节点名,建议和主机一致
node.master: true ##指定该节点是否有资格被选举成为master node,默认是true,es是默认集群中的第一台机器为master,如
果这台机挂了就会重新选举master。
node.data: false ##指定该节点是否存储索引数据,默认为true。
path.data: /data/es-data ##数据存放路径
path.logs: /var/log/elasticsearch/ ##日志存放文件
bootstrap.memory_lock: true ##内存锁机制,锁住内存,不被使用到交换分区去
##网络主机访问权限设置
http.port: 9200 ##web端口
elk-node2:
# vim /etc/elasticsearch/elasticsearch.yml cluster.name: nova ##集群名称
node.name: elk-node2 ##节点名,建议和主机一致
node.master: false ##指定该节点是否有资格被选举成为master node,默认是true,默认集群中的第一台机器为master,如果这台机
挂了就会重新选举master。
node.data: true ##指定本节点为数据存储节点
path.data: /data/es-data ##数据存放路径
path.logs: /var/log/elasticsearch/ ##日志存放文件
bootstrap.memory_lock: true ##内存锁机制,锁住内存,不被使用到交换分区去
##网络主机访问权限设置
http.port: 9200 ##web端口
##多播自动发现禁用开关,当前设置为关闭?
# chown -R elasticsearch.elasticsearch /data/ (6)、启动服务
# /etc/init.d/elasticsearch start
Starting elasticsearch: [ OK ]
# chkconfig elasticsearch on
# /etc/init.d/elasticsearch status
elasticsearch (pid 2309) is running...
# netstat -antplu| egrep \"9200|9300\"
tcp 0 0 :::9200 :::* LISTEN 2309/java tcp 0 0 :::9300 :::* LISTEN 2309/java
(7)、验证
1)、web浏览器访问 验证正确。
2)、通过命令的方式查看
注:即可在本机查看,也可在其他主机查看。
HTTP/1.1 200 OK ##访问成功
Content-Type: application/json; charset=UTF-8
Content-Length: 95
{
\"count\" : 0,
\"_shards\" : {
\"total\" : 0,
\"successful\" : 0,
\"failed\" : 0
}
}
2.2.2 源码安装 (1)、解压安装
# cd /usr/local/src
# mv elasticsearch-2.4.6 /usr/loca/es
(2)、创建es用户及数据目录 # groupadd es # useradd -g es es # mkdir -r /data/es-data # chown -R es:es /data/es-data # mkdir -r /var/log/elasticsearch # chown -R es:es /var/log/elasticsearch (3)、es配置
# vim /usr/local/es/config/elasticsearch.yml
注:配置参数时,需要先设置一个空格,否则启动时会报错。
cluster.name: nova node.name: elk-node3 node.master: false node.data: true path.data: /data/es-data path.logs: /data/logs/es path.logs: /data/logs/es http.port: 9200
(4)、启动
源码安装的es不能使用root用户启动,必须使用创建好的普通用户进行启动。 # su - es
$ /usr/local/es/bin/elasticsearch &
[2017-09-29 23:57:38,334][WARN ][bootstrap] unable to install syscall filter: seccomp unavailable: CONFIG_SECCOMP not compiled into
kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed
[2017-09-29 23:57:38,346][WARN ][bootstrap] Unable to lock JVM Memory: error=12,reason=Cannot allocate memory
[2017-09-29 23:57:38,346][WARN ][bootstrap] This can result in part of the JVM being swapped out.
[2017-09-29 23:57:38,346][WARN ][bootstrap] Increase RLIMIT_MEMLOCK, soft limit: 65536, hard limit: 65536
[2017-09-29 23:57:38,346][WARN ][bootstrap] These can be adjusted by modifying /etc/security/limits.conf, for example:
# allow user 'es' mlockall
es soft memlock unlimited
es hard memlock unlimited
[2017-09-29 23:57:38,347][WARN ][bootstrap] If you are logged in interactively, you will have to re-login for the new limits to take effect.
[2017-09-29 23:57:38,704][INFO ][node] [elk-node3] initializing ...
[2017-09-29 23:57:39,167][INFO ][plugins] [elk-node3] modules [lang-groovy, reindex, lang-expression], plugins [], sites []
[2017-09-29 23:57:39,205][INFO ][env] [elk-node3] using [1] data paths, mounts [[/ (/dev/mapper/vg_nginx-lv_root)]], net usable_space [33.2gb], net total_space [36.8gb], spins? [possibly], types [ext4]
[2017-09-29 23:57:39,205][INFO ][env] [elk-node3] heap size [1015.6mb], compressed ordinary object pointers [true]
[2017-09-29 23:57:39,205][WARN ][env] [elk-node3] max file descriptors [4096] for elasticsearch process likely too low, consider increasing to at least [65536]
[2017-09-29 23:57:40,645][INFO ][node] [elk-node3] initialized
[2017-09-29 23:57:40,645][INFO ][node] [elk-node3] starting ...
[2017-09-2923:57:40,695][INFO][discovery][elk-node3] nova/DSP41KSoR2C_RdXJNPO4zg
显示以上信息表示es启动成功。 $ netstat -antplu | grep java
tcp 0 0 :::9200 :::* LISTEN 3375/java tcp 0 0 :::9300 :::* LISTEN 3375/java
端口已开启。 验证:
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8 Content-Length: 98 {
\"count\" : 78, \"_shards\" : { \"total\" : 21, \"successful\" : 21, \"failed\" : 0
} }
验证正常。 2.2.3 head插件安装 (1)、方法一:直接安装
# /usr/share/elasticsearch/bin/plugin install mobz/elasticsearch-head 安装完成,进行验证。 插件安装成功。 删除插件:
# /usr/share/elasticsearch/bin/plugin list
Installed plugins in /usr/share/elasticsearch/plugins:
- head ##当前已安装插件
# /usr/share/elasticsearch/bin/plugin remove head
-> Removing head...
Removed head ##删除成功
注:源码安装的es,在安装head插件后,重启会报错。 报错信息: 解决方案:
# vim /usr/local/es/plugins/head/plugin-descriptor.properties
description=head - A web front end for an elastic search cluster version=master site=true name=head
然后进行重启,重启后正常。
(2)、方法二:源码安装 ,提取密码:ifj7 # cd /usr/local/src/
# unzip elasticsearch-head-master.zip # cd /usr/share/elasticsearch/plugins/ # mkdir head # cd head/
# cp -r /usr/local/src/elasticsearch-head-master/* ./
# chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/plugins # /etc/init.d/elasticsearch restart
命令测试插件安装成功。
Web界面显示正确,说明插件安装成功。 2.2.4 实例测试
(1)、插入数据实例测试
打开”复合查询“,在POST选项下,任意输入如/index-demo/test,然后在下面输入数据,查看返回结果。 注:内容之间换行的逗号不要漏掉
点击”验证JSON“->”提交请求“,提交成功后,观察右栏里出现的信息:有index,type,version等信息,failed:0(成功消息)
测试成功。 (2)、实例测试
选择\"复合查询\"选项,选择GET选项,在/index-demo/test/后面输入上面POST结果中 的id号,不输入内容,即{}括号里为空!
点击”验证JSON“和\"提交请求\",观察右栏内显示结果。
结果中有上述插入的数据,这就是elasticsearch检索功能的具体体现。 (3)、实例查询
打开\"基本查询\",查看下数据,如下,即可查询到(1)步骤中插入的数据。 打开“数据浏览”,也能查看到插入的数据。 其中也可通过mesg和user关键字检索相应数据。
2.2.5 kopf监控插件 (1)、方法一
# /usr/share/elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf 安装成功。
(2)、方法二:源码安装
# wget
# unzip master.zip
# cd /usr/share/elasticsearch/plugins/ # mkdir kopf # cd kopf
# cp -r /usr/local/src/elasticsearch-kopf-master/* ./
# chown -R elasticsearch:elasticsearch /usr/share/elasticsearch/plugins # /etc/init.d/elasticsearch restart
Stopping elasticsearch: [FAILED] Starting elasticsearch: [ OK ] 测试验证: 2.3 安装Logstash 2.3.1 下载源码安装包 2.3.2 安装 2.3.3 配置环境 # vim /etc/profile
export PATH=$PATH:/usr/local/logstash/bin # source /etc/profile 2.3.4 重启elasticsearch # /etc/init.d/elasticsearch restart
2.3.5 数据测试 logstash常用参数:
-e :指定logstash的配置信息,可以用于快速测试; -f :指定logstash的配置文件;可以用于生产环境;
(1)、基本输入输出(数据未写入elasticsearch中) # logstash -e 'input { stdin{} } output { stdout{} }'
Settings: Default filter workers: 1
Logstash startup completed
hello ##输入
world ##输入
##输出
(2)、使用rubydebug详细输出(数据未写入elasticsearch中) # logstash -e 'input { stdin{} } output { stdout{ codec => rubydebug} }'
Settings: Default filter workers: 1
Logstash startup completed
hello ##输入
{ ##输出下面信息
\"message\" => \"hello\
\"@version\" => \"1\
\"@timestamp\" => \"2017-09-19T19:32:44.701Z\
}
world ##输入
{ ##输出线面信息
\"message\" => \"world\
\"@version\" => \"1\
\"@timestamp\" => \"2017-09-19T19:32:55.357Z\}
(3)、把输入内容输出到elasticsearch中
Settings: Default filter workers: 1
Logstash startup completed
123456 ##输入内容
nova
hello
world
SIGINT received. Shutting down the pipeline. {:level=>:warn}
Logstash shutdown completed
注:使用rubydebug和写到elasticsearch中的区别:其实就在于后面标准输出的区别, 前者使用codec;后者使用elasticsearch。
测试:写到elasticsearch中内容在logstash中查看,如下图:
注:master收集到日志后,会把一部分数据碎片到salve上(随机的一部分数据),master和slave又都会各自做副本,并把副本放到对方机器上,这样就保证了数据不会丢失。
如下,master收集到的数据放到了自己的第3分片上,其他的放到了slave的第0,1,2,4分片上。 (1)、elasticsearch查看 (2)、Logstash查看 (3)、文本查看
(4)、既写到elasticsearch中又写到文件中 stdout{ codec => rubydebug}}'
Settings: Default filter workers: 1
Logstash startup completed
yangguoqiang ##输入
{ ##输出内容
\"message\" => \"yangguoqiang\
\"@version\" => \"1\
\"@timestamp\" => \"2017-09-19T21:02:36.313Z\
}
nihao ##输入
{ ##输出内容
\"message\" => \"nihao\
\"@version\" => \"1\
\"@timestamp\" => \"2017-09-19T21:02:39.163Z\
}
Logstash shutdown completed
注:以上文本可以长期保留、操作简单、压缩比大。 验证:
输出信息被记录在文本中,可实时查询。 2.3.6 logstash的配置和文件编写 # mkdir /etc/logstash (1)、logstash的配置
input{stdin{ }}
output{
stdout { codec => rubydebug }
}
执行:
Settings: Default filter workers: 1
Logstash startup completed
beijing ##输入信息
{ ##输出信息
\"message\" => \"beijing\
\"@version\" => \"1\
\"@timestamp\" => \"2017-09-20T09:00:46.581Z\
}
验证:
收集系统日志配置
# vim /etc/logstash/log_file.conf
input { file {
path => \"/var/log/messages\" type => \"system\"
start_position => \"beginning\" } } output {
elasticsearch { } }
验证:
(3)、收集java日志,其中包含上面讲到的系统日志收集
# vim /etc/logstash/log_java.conf
2)、
(input { file {
##系统日志输入
path => \"/var/log/messages\" type => \"system\"
start_position => \"beginning\" } } input { file {
path => \"/var/log/elasticsearch/nova.log\" type => \"es-error\"
start_position => \"beginning\" } } output {
##输出到es中
##es-error日志输入
if [type] == \"system\"{ elasticsearch { } }
if [type] == \"es-error\"{ elasticsearch { } } }
注:如果你的日志中有type字段 那你就不能在conf文件中使用type
##判断日志type,如果符合es-error字段,则输出到es中。
验证:
案例(3)中是将每个报错收集成一行内容,并不是按照一个报错、一个时间模块方式收集的。 (4)、以事件方式收集报错信息 # vim /etc/logstash/multiline.conf
input { stdin {
codec => multiline { pattern => \"^\\[INFO\" negate => true
what => \"previous\" } } } output { stdout {
codec => \"rubydebug\" } }
执行:
# logstash -f multiline.conf
Settings: Default pipeline workers: 2 Pipeline main started 123 456 [123 {
##输出 ##输入
\"@timestamp\" => \"2017-09-20T14:36:59.487Z\ \"message\" => \"123\\n456\ \"@version\" => \"1\ \"tags\" => [ [0] \"multiline\" ], } 123] [456] {
##输出
##输入
\"@timestamp\" => \"2017-09-20T14:37:36.771Z\ \"message\" => \"[123\\n123]\ \"@version\" => \"1\ \"tags\" => [ [0] \"multiline\" ], }
Pipeline main has been shutdown stopping pipeline {:id=>\"main\
注:在没有遇到“[”的时候,系统不会收集,只有遇见“[”的时候,才算是一个事件,才收集起来。
2.4 Kibana安装配置 node:elk-node2 2.4.1 安装kibana # cd /usr/local/src # wget
2.4.2 配置kibana
# vim /usr/local/kibana/config/kibana.yml
server.port: 5601
9:19200\"
kibana.index: \".kibana\"
# /usr/local/kibana/bin/kibana & # netstat -antplu | grep node 验证:
2.4.3 Kibana Web界面介绍 (1)、Setting窗口
点击“Create”进行创建一个index或者Pattern,用于在分析时确定ES中的Index。Kibana会自动加载该Index下doc的field,并自动选择合适的field用于图标中的时间字段:
注:这里输入的index或Pattern项必须为之前logstash中配置好的index。 点击“Discover”,注意右上角是查询的时间范围。 如果没有查找到数据,那么就需要需调整这个时间范围。 选择时间段后,就可看到ES中的数据信息。 关键字搜索:
点击右边的保存按钮,保存该查询为localhost_logs,点击Sava保存。
(2)、Visualize窗口
接下来去Visualize页面,点击新建一个柱状图(Vertical Bar Chart),然后选择刚刚保存的查询localhost_logs。
之后,Kibana将生成类似于下图的柱状图(只有1条日志,而且是在同一时间段的,比较丑,但足可以说明问题)
在左边设置图形的各项参数,点击Apply Changes按钮,右边的图形将被更新。
同理,其他类型的图形都可以实时更新。点击右边的保存,保存此图,命名为localhost_logs_visual。 (3)、Dashboard窗口
切换到Dashboard页面,单击新建按钮,选择刚刚保存的search_all_logs_visual图形,面板上将展示该图。
如果有较多数据,我们可以根据业务需求和关注点在Dashboard页面添加多个图表:柱形图,折线图,地图,饼图等等。当然,我们可以设置更新频率,让图表自动更新。如果设置的时间间隔够短,就很趋近于实时分析了。
到这里,ELK平台部署和基本的测试已完成。 三 ELK+Redis架构安装部署
如果生产环境使用Logstash agent直接连接ELK,则会出现以下这个问题:
一旦Elasticsearch出现问题,就不能进行日志采集处理了!这种情况下该怎么办呢? 解决方案:
可以在Client和Elasticsearch之间添加一个中间件作为缓存,先将采集到的日志内容写到中间件上,然后再从中间件输入到Elasticsearch中。这就比较完美的解决了上述的问题了。 3.1 Redis安装配置 3.1.1 安装依赖性
# yum repolist ##获取当前有效rpm包。
# yum -y install gcc gcc-c++ make gmake cmake zlib tcl ##安装依赖性
# cd /usr/local/src ##进入软件包目录(规范化) # wget \\\\下载软件包 ##解压并进入redis目录
# cd redis-3.2.9 ##解压并进入redis目录 # ./runtest ##运行测试
# make MALLOC=libc ##预编译 编译安装 # make test ##编译测试 # cd src ##进入src目录安装 # make PREFIX=/usr/local/redis install ##编译安装 # cd utils/
# .src/install_server.sh //脚本执行后,所有选项都以默认参数为准即可
Please select the redis port for this instance: [6379] Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf] Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log] Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379] Selected default - /var/lib/redis/6379 Please select the redis executable path [] Selected config: Port : 6379
Config file : /etc/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /var/lib/redis/6379 Executable : /usr/local/bin/redis-server Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort. ##此处回车 Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345! ##运行等级为345 Starting Redis server... Installation successful!
##默认为[],设置为/usr/local/redis/bin/redis-server
##此处回车,可设置
##此处回车,可设置
##此处回车,可设置
##此处回车,可设置
3.1.3 配置redis
# vim /usr/local/redis/etc/6379.conf
port 6379
tcp-backlog 511
timeout 60s
tcp-keepalive 300
daemonize yes
supervised no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /var/log/redis_6379.log
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis/6379
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-timeout 60
repl-disable-tcp-nodelay no
requirepass mima
maxclients 10000
maxmemory 256m
maxmemory-policy volatile-ttl
maxmemory-samples 5
appendonly no
appendfilename \"appendonly.aof\"
appendfsync always
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events \"\"
hash-max-ziplist-entries 128
hash-max-ziplist-value 1024
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
3.1.4 设置守护进程
# chmod 755 /etc/init.d/redis # vim /etc/init. d/redis
#!/bin/sh
# Simple Redis init.d script conceived to work on Linux systems # as it does use of the /proc filesystem. # chkconfig: - 58 74
# description: Redis_6379 is a persistent key-value database REDISPORT=6379
EXEC=/usr/local/redis/bin/redis-server CLIEXEC=/usr/local/redis/bin/redis-cli PIDFILE=/var/run/redis_${REDISPORT}.pid CONF=\"/etc/redis/${REDISPORT}.conf\" case \"$1\" in start)
if [ -f $PIDFILE ] then
echo \"$PIDFILE exists, process is already running or crashed\" else
echo \"Starting Redis server...\" $EXEC $CONF fi
echo \"Redis start\" ;; stop)
if [ ! -f $PIDFILE ] then
echo \"$PIDFILE does not exist, process is not running\" else
PID=$(cat $PIDFILE) echo \"Stopping ...\"
$CLIEXEC -a \"mima\" -p $REDISPORT shutdown while [ -x /proc/${PID} ] do
echo \"Waiting for Redis to shutdown ...\"
sleep 1 done
echo \"Redis stopped\" fi ;; status)
PID=$(cat $PIDFILE) if [ ! -x /proc/${PID} ] then
echo 'Redis is not running' else
echo \"Redis is running ($PID)\" fi ;; restart) $0 stop $0 start ;; *)
echo \"Please use start or stop as first argument\" ;; esac
# chkconfig --add redis # chkconfig redis on
#添加系统服务
#设置开机自启
# service redis start ##服务启动 # service redis status ##查看服务状态 # service redis stop ##服务关闭 # service redis restart ##服务重启 3.1.5 测试redis
(error) NOAUTH Authentication required.
##认证失败,即未进行密码认证,
##redis的认证方式是auth “密码”,其中密码是/etc/redis/ 6379.conf文件中的“requirepass ”参数中 OK PONG
3.2 ELK+redis连接配置 3.2.1 输出信息到屏幕
# vim /etc/logstash/log_redis.conf ##logstash+redis配置
input { stdin{ } } output{
stdout { codec => rubydebug } redis {
type => \"redis-log\"
host =>
##设置输出方式,此方式为文本输出
##主机
##认证密码 ##端口
##选择数据库目录,自动创建 ##数据类型
password => \"mima\" port => \"6379\"
db => \"6\"
data_type => \"list\" key => \"demo\" } }
##键值对
# logstash agent -f log_redis.conf --verbose
starting agent {:level=>:info}
starting pipeline {:id=>\"main\Settings: Default pipeline workers: 2
Starting pipeline {:id=>\"main\Pipeline main started nihao {
##输入内容 ##输出内容
\"message\" => \"nihao\ \"@version\" => \"1\
\"@timestamp\" => \"2017-09-22T11:31:30.082Z\ \"host\" => \"elk-node2\" }
Input plugins stopped! Will shutdown filter/output workers. {:level=>:info} Pipeline main has been shutdown stopping pipeline {:id=>\"main\Closing inputs {:level=>:info} Closed inputs {:level=>:info}
验证:
##登陆redis数据库
##密码验证,如果此处没有进行密码验证,则会报出错误,错误信息如下:“NOAUTH Authentication required.” OK
##查看redis信息查看 # Server
redis_version:3.2.9 ##redis版本信息 redis_git_sha1:00000000 redis_git_dirty:0
redis_build_id:2fd0f0229ac00f27 redis_mode:standalone arch_bits:64
multiplexing_api:epoll
gcc_version:4.4.7 ##gcc版本信息
process_id:24757 ##当前 Redis 服务器进程id
run_id:3563e3ab4f6739fde5a523a668bca974b202706e tcp_port:6379
uptime_in_seconds:357768 ##运行时长(秒) uptime_in_days:4 hz:10
executable:/usr/local/redis/bin/redis-server config_file:/etc/redis/6379.conf # Clients
connected_clients:1 ##客户端连接数 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 # Memory
used_memory:1001568 ## Redis 分配的内存总量 used_memory_human:978.09K used_memory_rss:3497984
## Redis 分配的内存总量(包括内存碎片)
##运行时长(天)
used_memory_rss_human:3.34M used_memory_peak:2425176
used_memory_peak_human:2.31M ###Redis所用内存的高峰值 total_system_memory_human:3.74G ## 系统内存总量 used_memory_lua:49152 used_memory_lua_human:48.00K maxmemory_human:244.14M maxmemory_policy:volatile-ttl mem_fragmentation_ratio:3.49 mem_allocator:libc # Persistence loading:0
rdb_changes_since_last_save:2 rdb_bgsave_in_progress:0 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1
aof_enabled:0 ##redis是否开启了aof aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok # Stats
total_connections_received:346605 ##运行以来连接过的客户端的总数量 total_commands_processed:4084150 ##运行以来执行过的命令的总数量 instantaneous_ops_per_sec:0
instantaneous_input_kbps:0.00 instantaneous_output_kbps:0.00 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:346624 keyspace_misses:898947 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:195 migrate_cached_sockets:0 # Replication
role:master ##当前实例的角色master还是slave connected_slaves:0 ##当前连接slave数量 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 # CPU
used_cpu_sys:289.65 ##CPU 系统使用量 used_cpu_user:4.06
##CPU用户使用量 ##CPU系统子进程使用量
used_cpu_sys_children:0.01
used_cpu_user_children:0.00 ##CPU用户子进程使用量 # Cluster cluster_enabled:0 # Keyspace
db0:keys=1,expires=0,avg_ttl=0 ##各个数据库的 key 的数量,以及带有生存期的 key 的数量 db1:keys=1,expires=0,avg_ttl=0 db6:keys=1,expires=0,avg_ttl=0 ##选择db6库目录 OK
##查看当前库目录下的所有key值
##当前库目录下只有“demo”一个key值
##集群模式启动
1) \"demo\"
##查看“demo”key的第二个value
\"{\\\"message\\\":\\\"2\\\ ##查看“demo”key的最后一个value
\"{\\\"message\\\":\\\"8\\\
以上实验证明输入信息可以正常输出到redis数据库对应库中,并以key:value简直对的形式存储。
3.2.2 输出信息到Elasticsearch # vim /etc/logstash/log_es_redis.conf
input { redis {
password => \"mima\" ##redis认证密码 port => \"6379\" db => \"6\"
##redis端口
##此处的db库名应与此前写入redis数据库的库名一致。
data_type => \"list\" key => \"demo\" } } output {
elasticsearch { ##将redis库中的数据输出到es中 ##es服务IP+端口
index => 'redis-in- ##redis日志名称 } }
##此处的key值名应与此前写入redis数据库的key值名一致。
验证:
# logstash -f /etc/logstash/redis_es.conf &
打开浏览器,输入es系统的ip+端口,查看redis是否写入到系统中。
Redis日志成功输出到es系统,并且分片存储。
3.2.3 收集Nginx日志
客户端需要安装logstash agent。
(1)、首先需要安装Nginx和logstash agent (2)、nginx配置
Nginx配置文件路径:/etc/nginx/ # vim /etc/nginx/nginx.conf
##将nginx的日志格式配置为json格式
........................
log_format json '{\"@timestamp\":\"$time_iso8601\"' ##时间 '\"client_user\":\"$remote_user\ ##客户端用户 '\"client_ip\":\"$remote_addr\ '\"request\":\"$request\ '\"status\":\"$status\
##客户端IP地址 ##请求 ##请求状态 ##请求包大小 ##客户端浏览器
'\"size\":\"$body_bytes_sent\
'\"user_agent\":\"$http_user_agent\ '\"referer\":\"$http_referer\
'\"x-forwarded-for\":\"$http_x_forwarded_for\"' '}'; ...........................................
# vim /etc/nginx/conf.d/server.conf ##虚拟主机配置
server {
listen 8080;
access_log /data/logs/access_json.log json; location / {
root /data/www/html;
index index.html index.htm index.php; } }
# /etc/init.d/nginx restart
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Stopping nginx: [ OK ] Starting nginx: [ OK ]
(3)、Logstash agent配置
Logstash配置文件路径:/usr/local/logstash/log_nginx.conf # vim /usr/local/logstash/log_nginx.conf
input { ##输入信息 file {
path => [\"/data/logs/access_json.log\"] type => \"nginx_access_log\"
##acess日志文件路径 ##类型
##从什么地方开始收集 ##收集格式
start_position => \"beginning\" codec => \"json\" } file {
##error日志文件路径 ##类型
##从什么地方开始收集 ##收集格式
path => [\"/data/logs/error.log\"] type => \"nginx_error_log\" start_position => \"beginning\" codec => \"json\" } } output {
##输出信息 ##判断输出类型 ##输出到redis数据库中
if [type] == \"nginx_access_log\"{ redis{
##redis主机
##端口
##redis认证密码 ##db库 ##数据格式
port => \"6379\"
password => \"mima\" db => \"2\"
data_type => \"list\"
key => \"access\" ##设置redis的“key” } }
if [type] == \"nginx_error_log\"{ redis{
port => \"6379\" password => \"mima\" db => \"1\" data_type => \"list\" key => \"error\" } } }
(4)、logstash server配置
Logstash server配置路径:/etc/logstash/log_nginx.conf # vim /etc/logstash/log_nginx.conf
input {
##输入信息
##从redis数据库中输入
redis {
type => \"nginx_access_log\" password => \"mima\" port => \"6379\" db => \"3\" data_type => \"list\" key => \"access\" } redis {
type => \"nginx_error_log\" password => \"mima\" port => \"6379\"
db => \"1\" data_type => \"list\" key => \"error\"
} output {
##输出信息
##判断条件 ##输出到es中
}
if [type] == \"nginx_access_log\"{ elasticsearch { ##es主机加端口
##输出到es的格式
} }
if [type] == \"nginx_error_log\"{ elasticsearch { } } }
(4)、启动logstash服务
Logstash agent:# logstash -f /usr/local/logstash/log_nginx.conf & Logstash server:# logstash -f /etc/logstash/log_nginx.conf & 验证:
打开浏览器,输入es网址,查看
Es中的index是按照logstash server中配置的方式呈现的,说明从redis写入es中是成功的。
其中,es存储的日志格式与nginx配置文件中设置的格式一致。 四、性能测试 4.1 客户端性能测试
注:当前测试仅为实验测试阶段,如需准确数据,需对线上业务进行测试。
案例:分别测试客户端运行仅运行nginx服务、仅运行logstash客户端命令和同时运行nginx服务和logstash客户端命令,分别查看客户端资源消耗情况。
(1)、仅运行nginx服务 # /etc/init.d/nginx start 内存:
负载:
top监控:
由上图可知,当系统只运行nginx服务时,系统资源消耗较低,基本对系统无影响。 (2)、仅运行logstash命令
# logstash agent -f /usr/local/logstash/log_nginx.conf & top监控:
内存: 负载:
由上图可以看出,当系统只运行logstash客户端命令时,系统资源比只运行nginx服务消耗的资源多,并且开始有负载,但负载很小。
(3)同时运行nginx服务和logstash客户端命令 top监控: 内存: 负载:
同时运行nginx服务与logstash客户端命令后,系统内存使用量有少许上涨,负载基本保持不变。内存使用量占总内存约为40%~45%之间。
综合以上测试信息预测,如果线上使用logstash作为客户端进行日志收集和过滤管,那么对于系统的压力较大,尤其是内存方面,对于数据库服务器,logstash客户端运行会造成系统内存严重不足,因此需要寻求更加轻量级的客户端日志收集工具。
因篇幅问题不能全部显示,请点此查看更多更全内容