一、概念介绍
日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及时采取措施纠正错误。

通常,日志被分散的储存不同的设备上。如果你管理数十上百台服务器,你还在使用依次登录每台机器的传统方法查阅日志。这样是不是感觉很繁琐和效率低下。当务之急我们使用集中化的日志管理,例如:开源的syslog,将所有服务器上的日志收集汇总。

集中化管理日志后,日志的统计和检索又成为一件比较麻烦的事情,一般我们使用grep、awk和wc等Linux命令能实现检索和统计,但是对于要求更高的查询、排序和统计等要求和庞大的机器数量依然使用这样的方法难免有点力不从心。

开源实时日志分析ELK平台能够完美的解决我们上述的问题,ELK由ElasticSearch、Logstash和Kiabana三个开源工具组成:
1)ElasticSearch是一个基于Lucene的开源分布式搜索服务器。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是第二流行的企业搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
在elasticsearch中,所有节点的数据是均等的。

基本组件:
索引(index):文档容器,索引是具有类似属性的文档的集合,类似于表,索引名必须为小写字母
类型(type):类型是索引内部的逻辑分区,其意义完全取决于用户需求,一个索引内部可定义一个或多个类型。一般来说,类型就是拥有相同的域的文档的预定义。
文档(document):文档是Lucene索引和搜索的原子单位,字包含了一个或多个域,是域容器,基于JSON格式表示;每个域的组成部分:一个名称,或多个值;拥有多个值的域,通常称为多值域;
映射(mapping):原始内容存储为文档之前需要事先进行分析;例如:切词、过滤掉某些词等;映射用于定义此分析机制如何实现,除此之外,ES还为映射提供了诸如将域中的内容排序等功能。

ES的集群组件:
Cluster:ES的集群标识为集群名称:默认为”elasticsearch”,节点是以此名字来加入到某个集群中,一个节点只能属于一个集群
Node:运行了单个ES实例的主机即为节点,用于存储数据、参与集群索引及搜索操作。节点的标识依靠节点名
Shard:将索引切割为物理存储组件;但每个shard都是一个独立且完整的索引;创建索引时,ES默认将其割为5个shard,用户也可以按需自定义,创建完成后不可修改。
Shard有两种类型:primary shard和replica。Replica用于数据冗余及查询时的负载均衡。每个副本可自定义,且可动态修改
ES Cluster工作过程:
启动时,通过多播(默认)或单播方式在9300/tcp查找同一集群中的其它节点,并与之建立通信。集群中的所有节点会选举出一个主节点负责管理整个集群状态,以及在集群范围内决定各shard的分布方式。站在用户角度而言,每个均可接收并响应用户的各类请求。
集群状态有:green(可用),red(不可用),yellow(修复模式)
官方网站:https://www.elastic.co

JDK:
Oracke JDK
OpenJDK

ES的默认端口:
参与集群的事务:9300/tcp
Transport.tcp.port
接收请求:9200/tcp
http.port

Restful API
四类API:
1) 检查集群、节点、索引等健康,以及获取其相就状态
2) 管理集群、节点、索引及元数据/
3) 执行CRUD操作
4) 执行高级操作,如paging,filtering等
ES访问接口:9200/tcp
url –X<VERB> ‘<PROTOCOL>://HOST:PORT/<PATH>?<QUERY_STRING>’ –d ‘<BODY>’
VERB: GET、POST、PUT、HEAD 或者 DELETE
PROTOCOL: http,https
PATH: API 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm
QUREY_STRING: 任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)
BODY: 一个 JSON 格式的请求体 (如果请求需要的话);

curl –X GET ‘HTTP://192.1.1.5:9200/?preey
curl –X GET ‘HTTP://192.1.1.5:9200/_cat’ --查看cat API的参数
curl –X GET ‘HTTP://192.1.1.5:9200/_cat/nodes’ --查看节点
curl –X GET ‘HTTP://192.1.1.5:9200/_cat/nodes?v’ --显示详细信息节点

ELK stack(2)
Cluster APIs:
health: 集群状态
curl –XGET ‘http://192.1.1.10:9200/_cluster/health?pretty
state:
curl –XGET ‘http://192.1.1.10:9200/_cluster/state/<metrics>?pretty
stats: 统计数据
curl –XGET ‘http://192.1.1.10:9200/_cluster/stats
节点状态
curl –XGET ‘http://192.1.1.10:9200/_cluster/_nodes/stats

Plugins:
插件扩展ES的功能:
添加自定义的映射类型、自定义分析器、本地脚本、自定义发现方式;

安装:
直接将插件放置于plugins目录中即可:
使用plugin脚本进行安装:
安装路径/plugin install <name or url>
Install
Remove
List

2)Logstash是一个完全开源的工具,他可以对你的日志进行收集、过滤、分析,并将其存储供以后使用(如,搜索),您可以使用它。说到搜索,logstash带有一个web界面,搜索和展示所有日志。
3)Kibana 是一个基于浏览器页面的Elasticsearch前端展示工具,也是一个开源和免费的工具,它Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。

ELK工作原理展示图

如上图:Logstash收集AppServer产生的Log,并存放到ElasticSearch集群中,而Kibana则从ES集群中查询数据生成图表,再返回给Browser

二、ELK环境部署

1、基础环境介绍

系统: Centos7
防火墙: 关闭
Sellinux: 关闭

机器环境: 两台
elk-node1: 192.168.1.160 #master机器
elk-node2: 192.168.1.161 #slave机器

注明:
master-slave模式:
master收集到日志后,会把一部分数据碎片到salve上(随机的一部分数据);同时,master和slave又都会各自做副本,并把副本放到对方机器上,这样就保证了数据不会丢失。
如果master宕机了,那么客户端在日志采集配置中将elasticsearch主机指向改为slave,就可以保证ELK日志的正常采集和web展示

2、Elasticsearch安装配置
Elasticsearch是java程序,而且要跑在jdk1.8版本以上
elk-01和elk-02同时操作
写hosts文件

echo "192.1.1.160 elk-01" >> /etc/hosts

echo "192.1.1.161 elk-02" >> /etc/hosts

yum –y install java-1.8.0 --安装jdk1.8版本

安装elasticsearch

tar zxvf elasticsearch-5.6.4.tar.gz -C /elk

cd /elk

mv elasticsearch-5.6.4 ./ elasticsearch

修改配置文件

grep -v ^# /elk/elasticsearch/config/elasticsearch.yml

cluster.name: test-ELK //集群名
node.name: elk-01 //节点名
path.data: /elk/elasticsearch/data //data存储路径
path.logs: /elk/elasticsearch/logs //log存储路径
bootstrap.memory_lock: true //锁住内存,不被使用到交换分区去
network.host: 0.0.0.0 //监听地址
http.port: 9200 //监听端口
discovery.zen.ping.unicast.hosts: ["192.1.1.161"] //集群节点发现列表 写另外一台的ip
discovery.zen.minimum_master_nodes: 2 //集群可做master的最小节点数

mkdir /elk/elasticsearch/{data,logs} -p

useradd elk

chown -R elk.elk /elk/elasticsearch

修改系统参数

vi /etc/security/limits.conf --修改系统参数,让系统用户打开文件无限制

  • soft nofile 65536
  • hard nofile 65536
  • soft nproc 2048
  • hard nproc 4096
  • soft memlock unlimited
  • hard memlock unlimited

vi /etc/sysctl.conf --在此文件里加入以下参数

vm.max_map_count=262144

开户启动elasticsearch

su – elk

$ cd /elk/elasticsearch
$ nohup ./bin/ elasticsearch &

netstat -antlp |egrep "9200|9300"

tcp6 0 0 :::9200 ::: LISTEN 3005/java
tcp6 0 0 :::9300 :::
LISTEN 3005/java

然后通过web访问(访问的浏览器建议使用google、firefox、oper浏览器)
http://192.1.1.160:9200/
http://192.1.1.161:9200/

安装head插件,用于显示集群节点和数据信息
插件在线安装方法

/elk/elasticsearch/bin/plugin install mobz/elasticsearch-head

插件安装的目录:/elk/elasticsearch/plugins
chown -R elk:elk /elk/elasticsearch/plugins

插件访问(最好提前将elk-node2节点的配置和插件都安装后,再来进行访问和数据插入测试)

http://192.1.1.160:9200/_plugin/head/
http://192.1.1.161:9200/_plugin/head/

两台机器看到的内容完全一致,test-ELK是集群名称,健康值也是绿色

测试插入数据实例,看界面能不能正常显示
如下:打开”复合查询“,在POST选项下,任意输入如/q1708/test然后在下面输入数据(注意内容之间换行的逗号不要漏掉);
数据输入好之后(如下输入user:liuxiang,mess:test Elasticsearch内容),下面点击”验证JSON“->”提交请求“,提交成功后,观察右栏里出现的信息:有index,type,version等信息,failed:0(成功消息)

打开"基本查询",查看下数据,如下,即可查询到上面插入的数据:

打开“数据浏览”,也能查看到插入的数据:

主页界也会更新,显示刚才创建类型,也会显示数据碎片存取的位置

安装kopf监控插件

/elk/elasticsearch/bin/plugin install lmenezes/elasticsearch-kopf

chown -R elk:elk /elk/elasticsearch

访问插件:(如下,两个节点kopf插件都要装好,否则访问时会出现集群节点为×××的yellow告警状态)

http://192.1.1.160:9200/_plugin/kopf/#!/cluster
http://192.1.1.161:9200/_plugin/kopf/#!/cluster

到此Elasticsearch软件包安装完成。
接下来安装Logstarsh数据采集

Logstash安装配置(这个在客户机上是要安装的。elk-node1和elk-node2都安装)

基础环境安装(客户端安装logstash,收集到的数据写入到elasticsearch里,就可以登陆logstash界面查看到了)

tar zxvf logstash-2.2.4.tar.gz –C /elk

mv logstash-2.2.4 ./logstash

useradd logstash –s /sbin/nologin

chown -R logstash.logstash /elk/logstash

数据的测试

基本的输入输出,验证logstash能否接收到数据

/elk/logstash/bin/logstash -e 'input { stdin{ } } output { stdout{} }'

OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Settings: Default filter workers: 1
Logstash startup completed
elk01testtest //输入的内容
2017-11-18T23:45:57.985Z elk-02 elk01testtest //输出的内容
aaa2222 //输入的内容
2017-11-18T23:46:01.112Z elk-02 aaa2222 //输出的内容

Ctrl + c 中断
测试把内容写到elasticsearch中

/elk/logstash/bin/logstash -e 'input { stdin{} } output { elasticsearch { hosts => ["192.1.1.161:9200"]} }'

OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N

Settings: Default filter workers: 1
Logstash startup completed
aa //随意输入数据

写到elasticsearch中在logstash中查看,如下图:
注意:
master收集到日志后,会把一部分数据碎片到salve上(随机的一部分数据),master和slave又都会各自做副本,并把副本放到对方机器上,这样就保证了数据不会丢失。
如下,master收集到的数据放到了自己的第1,3分片上,其他的放到了slave的第0,2,4分片上

再点数据浏览,可以看到刚才输入的内容

收集系统日志

cd /elk/logstash

vim logfile.conf

input { //指定输出
file { //输出的内容为文件
path => "/var/log/messages" //文件路径
type => "system" //给该类日志内容定一个名称,可自定义
start_position => "beginning" //表示从哪里开始读取日志,beginning是所有都读
}
}

output { //指定输出到哪里
elasticsearch { //指定输出到elasticaearch服务里
hosts => ["192.1.1.160:9200"] //指定连接elasticaearch服务的ip和端口
index => "system-%{+YYYY.MM.dd}" //把日志按日期进行分类
}
}
执行上面日志信息的收集,如下,这个命令会一直在执行中,表示日志在监控收集中;如果中断,就表示日志不在收集!所以需要放在后台执行~

/elk/logstash/bin/logstash -f logfile.conf

登陆elasticsearch界面,查看本机系统日志的信息:

Kibana安装配置
kibana的安装:

tar zxvf kibana-4.3.3-linux-x64.tar.gz -C /elk/

cd /elk

mv kibana-4.3.3-linux-x64 ./kibana

修改配置文件:

pwd

/elk/kibana/config

vim kibana.yml

server.port: 5601
server.host: "0.0.0.0"
elasticsearch.url: "http://192.1.1.160:9200"
kibana.index: ".kibana"

启动kibana

cd /elk/kibana

./bin/kibana &

lsof -i:5601

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 57504 root 13u IPv4 213407 0t0 TCP *:esmagent (LISTEN)
访问kibana
http://192.1.1.160:5601
创建一个日志组,该名称要和前面写的file.conf配置文件里的type字段一致

创建完成后再点 Discover

1日志展示
2为界面展示的type名称
3展示的字段
4未展示的字段
5日志的柱状图
6收集日志的数量
7为日志内容

Logstash 的多行合并 --用于日志有多行显示时,做的合并

codec的multiline插件

input {
stdin {
codec => multiline {
pattern => "pattern, a regexp" //使用正则,什么情况下把多行合并起来
negate => "true" or "false" //正向匹配和反向匹配
what => "previous" or "next"` //合并到当前行还是下一行
}
}
}