1:日志方案介绍
通常日志被分散存储到不同的设备上,如果你管理多台服务器,你可能还在使用依次登陆每台机器的做法来查看日志,这样效率比较低下。当务之急我们使用集中化的日志管理,开源实时日志分析ELK平台能够完美的解决我们上述的问题。具体流程如下图1。
图1 ELK方案
2:ELK介绍
ELK由ElasticSearch、Logstash和Kiabana三个开源工具组成。
Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
Logstash是一个完全开源的工具,他可以对你的日志进行收集、过滤,并将其存储供以后使用(如,搜索)。
Kibana 也是一个开源和免费的工具,它Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。
画了一个ELK工作的原理,如下图2:
图2 ELK工作原理图
如图:Logstash收集AppServer产生的Log,并存放到ElasticSearch集群中,而Kibana则从ES集群中查询数据生成图表,再返回给Browser。
3:单机器Linux搭建ELK
官网下载安装包 https://www.elastic.co/downloads。
ElasticSearch: 2.4.1
Logstash: 2.4.0
Kibana: 4.6.0
Java: version "1.7.0_65"
注:
a:由于Logstash的运行依赖于Java环境, 而Logstash 1.5以上版本不低于java 1.7,因此推荐使用最新版本的Java。因为我们只需要Java的运行环境,请自行搜索安装。
3.1:安装Elasticsearch
在安装Elasticsearch前,需要创建一个非ROOT用户,因为Elasticsearch只能由非root用户来进行操作。具体步骤如下:
1:解压:tar -zxvf elasticsearch-2.4.1.tar.gz
将解压后的整个文件授权给非root用户
2:修改配置文件:vi elasticsearch-2.4.1/config/elasticsearch.yml
cluster.name: my-application (集群名字,随意)
node.name : node-0 (节点名字 随意)
network.host: 192.168.56.101 (自己IP)
http.port: 9200 (端口不需要修改)
3:插件安装
在bin目录下。安装head插件,主要是用来观看节点状态以及索引等等。
联网状态下:
head插件:./bin/plugin install mobz/elasticsearch-head
bigdesk插件:./bin/plugin install AIsaac08/bigdesk (只适合2.0以上版本)
不联网可以直接从svn上下载
http://10.112.1.225:7080/svn/Speed4J/company_doc/学习资料/ELK/ELK_linux软件
然后新建一个plugins目录。放进去就可以了。
4: 启动检测 (必须用非root用户启动)
启动 ./bin/elasticsearch & (&代表了后台启动)
a:正常启动(9200端口必须开通)
b:head效果
ip:9200/_plugin/head
c:bigdesk效果
ip:9200/_plugin/bigdesk
5:注意事项
对配置文件修改时,建议开头不要保留空格,有时候会出现奇怪错误。
3.2:安装logstash
Logstash安装比较简单:
1:解压,。tar -zxvf logstash-2.4.0 tar.gz
2:编写配置文件conf( 文件名和存放位置随意)
在这里我存放在新建的conf文件夹下,名字为001.conf
3:进行配置
目前是在单机版本上部署,简单说明下各个配置,file代表的是文件输入,path代表的是文件路径。Type代表了自定义的文件类型,可以修改。start_position 代表了从哪里开始读取文件。Elasticserach暂时照抄这个配置,只要把hosts代表的ip修改为自己的就好。
input {
file {
path =>"E:/SOFTALL/ELKoldlogs/filelog.txt"
type =>"logs"
start_position =>"beginning"
}
}
filter {
}
output {
elasticsearch {
hosts =>"192.168.56.101" (换成自己的ip)
index =>"logstash-%{type}-%{+YYYY.MM.dd}"
document_type =>"%{type}"
workers => 10
template_overwrite => true
}
}
4 启动测试
./bin/logstash agent -f config/001.conf --configtest
出现ok字样,就说明你的配置文件的基本格式没错误,但具体语法还无法检测。
./bin/logstash agent -f config/001.conf & 后台启动
3.3 安装Kibana
Kibana安装和logstash有点类似,具体步骤:
1:解压压缩包 tar -zxvf kibana-4.6.1-linux-x86_64.tar.gz
2:修改配置文件
vi config/kibana.yml
server.port: 5601
server.host: “192.168.56.101”
elasticsearch.url: http://192.168.56.101:9200
kibana.index: “.kibana”
3:结果展示:
出现这个画面后,点击create,然后再点击Discover:
4:注意事项
在elasticsearch.url: 这里,冒号后面必须存在空格。非常重要
对配置进行修改时,开头不能存在空格。
到此,单机器版安装部署ELK已经成功了。
关闭kibana操作 fuser -n tcp 5601 然后杀掉对应端口就好了。
4:logstash详解
Logstash主要是用来读取日志,解析日志,输出日志。其中还有对日志的编码,格式等一些设置。
下图3是logstash工作原理图。
图3 logtsahs工作流程
4.1:input讲解
在介绍input配置前,我们可以在logstash目录下输入这样一串命令
./logstahs -e ‘’
然后在窗口下手动输入hello world。等下
就会出现下面类似效果
刚才的./logstahs -e ‘’其实完整命令就是
logtshash -e 'input{stdin{}} output {stdout{ codec => rubydebug }}'
4.1.1 文件输入 file
在本次平台建设中,只使用了file作为input的输入源。特对部分参数进行详细介绍。
l codec => #可选项,codec,默认是plain,
可通过这个参数设置编码方式
l discover_interval => #可选项,number,
logstash 每隔多久去检查一次被监听的 path 下是否有新文件。默认值是 15 秒。
l exclude =>... #可选项,array
不想被监听的文件可以排除出去,这里跟 path 一样支持 glob 展开。
l sincedb_path =>... #可选项,string,
如果你不想用默认的$HOME/.sincedb(Windows平台上在C:WindowsSystem32configsystemprofile.sincedb),可以通过这个配置定义 sincedb 文件到其他位置。
l sincedb_write_interval => #可选项, number,
logstash 每隔多久写一次 sincedb 文件,默认是 15 秒。
l stat_interval => #可选项, number,
logstash 每隔多久检查一次被监听文件状态(是否有更新),默认是 1 秒。
l start_position => #可选项string
logstash 从什么位置开始读取文件数据,默认是结束位置,也就是说 logstash 进程会以类似 tail -F 的形式运行。如果你是要导入原有数据,把这个设定改成 “beginning”,logstash 进程就从头开始读取,有点类似cat,但是读到最后一行不会终止,而是继续变成 tail –F;默认值end
l path => # 必选项, array
定需处理的文件路径, 可以定义多个路径
l tags => # 可选项, array
在数据处理过程中,由具体的插件来添加或者删除的标记
l type =># 可选项, string
自定义将要处理事件类型,可以自己随便定义,比如处理的是linux的系统日志,可以定义为"syslog"
参考配置:
file{
codec => plain{ charset =>"UTF-8" } 编码格式
type =>"cluster" 文件类型
path =>"/home/logstash-2.4.0/logtest/1025/004.log" 文件路径
start_position =>"beginning" 从什么地方读取
}
4.1.2 multiline多行事件编码
在日志记录中,有的时候会出现报错日志例如java的异常日志,这个时候我们可以把报错部分当作一个整体,合并为一行来进行输出。此时就涉及到multiline的具体用法。
参考配置:
codec => multiline{
charset =>"UTF-8"
pattern =>"^d{4}-d{2}"
negate => true
what =>"previous"
}
Charset :指定编码
pattern =>... # string 类型,设置匹配的正则表达式 ,必选
negate =>... # boolean类型,设置正向匹配还是反向匹配,默认是false,可选
what =>... # 设置未匹配的内容是向前合并还是向后合并,previous, next 两个值选择,必选
previous是指这段异常文字和前面的合并为一行输出了。Next是指与后面的合并为一行输出了。
4.1.3 add_field介绍
add_field 就是添加一个字段,这个是个很有用的。使用上比较简单
add_field=>{
"append"=>"runtime-cop"
}
具体效果就是增加了一个append的字段,它的值是runtime-cop。
4.2 filter讲解 ★★★★★
Logstash的强大能力的突出一点就在filter中。它扩展了进入过滤器的原始数
据,进行复杂的逻辑处理,甚至可以无中生有的添加新的 logstash 事件到后续的流程中去。后续学习,可以去参考官方文档,根据具体业务需求,增加不同的解析手段:https://www.elastic.co/guide/en/logstash/2.4/input-plugins.html。
4.2.1 Grok讲解
Grok是logstash里面自带的正则语法。是一种非常强大的解析各种非结构化的日志数据的工具,官方罗列出来的有120多种,极大程度上方便了开发人员或运维人员来对特定的日志进行解析,具体网址如下:https://github.com/logstash-plugins/logstash-patterns-core/tree/master/patterns。
USERNAME [a-zA-Z0-9._-]+
USER %{USERNAME}
INT (?:[+-]?(?:[0-9]+))
BASE10NUM (?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:.[0-9]+)?)|(?:.[0-9]+)))
NUMBER (?:%{BASE10NUM})
BASE16NUM (?<![0-9A-Fa-f])(?:[+-]?(?:0x)?(?:[0-9A-Fa-f]+))
BASE16FLOAT (?<![0-9A-Fa-f.])(?:[+-]?(?:0x)?(?:(?:[0-9A-Fa-f]+(?:.[0-9A-Fa-f]*)?)|(?:.[0-9A-Fa-f]+)))
用法: %{USERNAME :name}
这个name就是自定义的随意单词,用来匹配符合这个 [a-zA-Z0-9._-]+
例子:
55.3.244.1 GET /index.html 15824 0.043
%{IP:ip}%{WORD:method}%{URIPATHPARAM:request}%{NUMBER:bytes}%{NUMBER:duration}
在解析日志的过程中,一般采用官方的正则都可以来满足解析要求。当然也能进行自定义正则。
(?<queue_id>[0-9A-F]{10,11}) (?<className>[[sS]*]) 这个就是自定义的正则,<className>里面的className 是自定义正则名字 [[sS]*] 是格式
2016-09-29 10:26:31,652 [cn.xulei.elk.ElkDemo02]
%{TIMESTAMP_ISO8601:logdate}s?(?<className>[[sS]*])?"]
当然,也能采用%{}这样的用法,这时候就需要把自定义的正则放在一个文件中该文件名随意,地址随意,
参考配置:
2016-09-29 10:26:31,652 [cn.xulei.elk.ElkDemo01][140] [main] - Info log [20000].
grok{
patterns_dir => ["./patterns/test01.txt"]
match=>["message","%{TIMESTAMP_ISO8601:logdate}s?[%{className:class}]s?[%{classLine:line}]s?[%{threadName:thread}]s?-s?%{LOGLEVEL:logLevel}s?(?<sss>[sS]*)?"]
}
上面的patterns_dir是指规则路径。可以使用相对路径。
分别匹配:
2016-09-29 10:26:31,652 %{TIMESTAMP_ISO8601:logdate}
[cn.xulei.elk.ElkDemo01] [%{className:class}]
[140] [%{classLine:line}]
[main] [%{threadName:thread}]
Info %{LOGLEVEL:logLevel}
log [20000]. (?<sss>[sS]*)?
4.2.2 条件判断
==(等于), !=(不等于), <(小于), >(大于), <=(小于等于), >=(大于等于)
=~(匹配正则), !~(不匹配正则)
in(包含), not in(不包含)
and(与), or(或), nand(非与), xor(非或)
():复合表达式, !():对复合表达式结果取反
参考配置:
if [append] =="runtime-cop" {
grok{
patterns_dir => ["/home/logstash-2.4.0/patterns/test01.txt"]
match=> ["message","%{TIMESTAMP_ISO8601:logdate}s?[%{moduleName:moduleName}]s?[%{threadName:thread}]s?[%{tradeNo:tradeNo}]s?[%{LOGLEVEL:logLevel}]s?(?<sss>[sS]*)?" ]
}
}else if [append] =="runtime-framework" {
grok{
patterns_dir => ["/home/logstash-2.4.0/patterns/test01.txt"]
match=> ["message","%{TIMESTAMP_ISO8601:logdate}s?[%{className:className}]s?[%{threadName:thread}]s?[%{tradeNo:tradeNo}]s?[%{LOGLEVEL:logLevel}]s?(?<sss>[sS]*)?" ]
}
}
4.3 output讲解
Output作为输出,可以有不同的输出源,例如file,es,tcp等等.本次运行的数据全部输出到ES中.就以ES来作为讲解
elasticsearch {
hosts =>"192.168.56.102"
index =>"logstash-logs-%{+YYYY.MM.dd}"
document_type =>"%{type}"
workers => 10
}
1:hosts 代表了es所在的机器IP。
里面可以为数组。[“192.168.56.102:9200”,”192.168.56.101:9200”],
这代表了一个logstash发送到了2个es中。
2:index =>"logstash-logs-%{+YYYY.MM.dd}"
代表了这个创建的索引,是根据日期来创建的,其中的logs其实就是自己随便写的,
其余的都不是必须的,可以照抄
5:Elasticsearch 详解
5.1 Elasticsearch数据存储分片原理介绍
对传入的每一条数据,es都会采用一定的计算规则来处理,最后获取到一个routing参数,默认情况下,就使用其_id值。将其_id值计算哈希后,对索引的主分片数取余,就是数据实际应该存储到的分片 ID。由于取余这个计算,完全依赖于分母,所以导致 ES 索引有一个限制,索引的主分片数,不可以随意修改。因为一旦主分片数不一样,所以数据的存储位置计算结果都会发生改变,索引数据就完全不可读了。我们只需要默认配置不修改就好了。
作为一个分布式存储日志的工具,创建数据副本是必需的,ES 数据写入流程,自然也涉及到副本。在有副本配置的情况下,数据从发向 ES 节点,到接到 ES 节点响应返回,流程图如下:
1. 客户端请求发送给 Node 1 节点,注意图中 Node 1 是 Master 节点,实际完全可以不是。
2. Node 1 用数据的 _id 取余计算得到应该讲数据存储到 shard 0 上。通过cluster state 信息发现 shard 0 的主分片已经分配到了 Node 3 上。Node 1 转
发请求数据给 Node 3。
3. Node 3 完成请求数据的索引过程,存入主分片 0。然后并行转发数据给分配有shard 0 的副本分片的 Node 1 和 Node 2。当收到任一节点汇报副本分片数据写入成功,Node 3 即返回给初始的接收节点 Node 1,宣布数据写入成功。
Node 1 返回成功响应给客户端。
elasticsearch的config文件夹里面有两个配置文件:elasticsearch.yml和logging.yml 配置集群主要是看elasticsearch.yml的配置。
cluster.name:elasticsearch
配置es的集群名称,默认是elasticsearch,es会自动发现在同一网段下的es,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集群。
node.name:"FranzKafka"
节点名,默认随机指定一个name列表中名字,
node.master:true
指定该节点是否有资格被选举成为node,默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master。
node.data:true
指定该节点是否存储索引数据,默认为true。
1:master:true data:false 只为主节点 但不存储数据
2:master: true data:true 这个是默认配置 就是自主选择主节点,都存储数据
network.bind_host:192.168.0.1
设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0。
http.port:9200
设置对外服务的http端口,默认为9200。
transport.tcp.port:9300
设置节点间交互的tcp端口,默认是9300。这个是多个node节点之间的通信端口
5.2 主节点不存储数据
此时。Node-17是主节点,不存储数据,
对应配置为
node.master:true
node.data:false
其他节点配置为:
node.master:false
node.data:true
下面是主节点不存储数据的head插件图。
访问主节点17的head页面
从图可知:
1:每个索引都被分为了5个分片
2:每个分片都有一个副本。
3:5个分片都随机分配到2个数据节点上。
注意分片的边框(border)有粗有细,具体区别是:
粗边框代表:primary(true)细边框 就是false。一个代表了副分片,一个是主分片
提前介绍点集群,在页面左边上,有个集群健康值
这个值有3种表现形式:
1:green 路灯 所有分片都正常运行,
2:yellow 黄灯 所有主分片都正常运行,但是副分片有缺失,这意味着当前的es是可以运行的,但是有一定的风险。
3:red红灯,有主分片缺少,这部分数据不可用。
5.3 自主选择主节点
默认配置
这个就是自主选择主节点。Fox和fox2都可以随便变为主节点,
配置是默认配置
node.master : true
node.data: true
5.4 Elasticsearch集群配置
在elasticsearch中,集群配置比较简单
discovery.zen.ping.unicast.hosts: ["192.168.56.101:9300","192.168.56.102:9300"]
这句话是说设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点,好,到此,你就成功了。
5.4.1集群unicast连接
ES 是一个 P2P 类型(使用 gossip 协议)的分布式系统,除了集群状态管理以外,其他所有的请求都可以发送到集群内任意一台节点上,这个节点可以自己找到需要转发给哪些节点,并且直接跟这些节点通信。从配置上来看,很简单,只需要写同一个cluster.name。那么就会自动归属到同一个集群中。
ES从2.0开始。从以前的自动发现方式改变为支持一种unicast模式(单播方式),在这里只需要配置几个具体的节点值。Es就能够把它视为处入整个集群传播途径中,通过他们来组建集群。所以处入unicast模式下的集群,只需要配置相同的几个节点就可以了。
参考配置1
network.host: "192.168.0.2"
discovery.zen.ping.timeout: 100s
discovery.zen.fd.ping_timeout: 100s
discovery.zen.ping.unicast.hosts: ["10.19.0.97","10.19.0.98","10
.19.0.99","10.19.0.100"]
discovery.zen.ping.timeout 参数仅在加入或者选举 master 主节点的时候才起
作用;
discovery.zen.fd.ping_timeout 参数则在稳定运行的集群中,master 检测所有
节点,以及节点检测 master 是否畅通时长期有用。
当ES集群发展到一定规模的时候,可能会出现多个集群,随之而来的是数据分配到多个集群中,但数据还是需要一起使用,为了解决这个问题,我们需要使用到一个配置tribe节点。目前,我们的需求还没达到,感兴趣的同学可以去自己研究研究。
全部配置:
# ---------------------------------- Cluster -----------------------------------
# Use a descriptive name for your cluster:
cluster.name: linux
# ------------------------------------ Node ------------------------------------
# Use a descriptive name for the node:
node.name: node-17 节点名字
node.master: true 主节点配置
node.data: false 数据节点配置
# Add custom attributes to the node:
#
# node.rack: r1
# ----------------------------------- Paths ------------------------------------
# Path to directory where to store the data (separate multiple locations by comma):
#
# path.data: /path/to/data
设置配置文件的存储路径,默认是es根目录下的config文件夹。
#
# Path to log files:
#
# path.logs: /path/to/logs
设置日志文件的存储路径,默认是es根目录下的logs文件夹
# ----------------------------------- Memory -----------------------------------
# Lock the memory on startup: 是否锁定内存。
# bootstrap.memory_lock: true
# Make sure that the `ES_HEAP_SIZE` environment variable is set to about half the memory
# available on the system and that the owner of the process is allowed to use this limit.
# Elasticsearch performs poorly when the system is swapping the memory.
# ---------------------------------- Network -----------------------------------
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 192.168.10.17 设置绑定的ip地址,
#
# Set a custom port for HTTP:
http.port: 9200 设置对外服务的http端口,默认为9200。
# For more information, see the documentation at:
<http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-network.html>
# --------------------------------- Discovery ----------------------------------
# Pass an initial list of hosts to perform discovery when new node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
discovery.zen.ping.unicast.hosts:["192.168.10.17:9300","192.168.10.23:9300","192.168.10.10:9300"]
#
# Prevent the "split brain" by configuring the majority of nodes (total number of nodes / 2 + 1):
#
# discovery.zen.minimum_master_nodes: 3
#
# For more information, see the documentation at:
# <http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html>
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
# gateway.recover_after_nodes: 3
#gateway.recover_after_nodes:1
设置集群中N个节点启动时进行数据恢复,默认为1。
#
# For more information, see the documentation at:
#
# ---------------------------------- Various -----------------------------------
#
# Disable starting multiple nodes on a single system:
#
# node.max_local_storage_nodes: 1
#
# Require explicit names when deleting indices:
#
# action.destructive_requires_name: true
注意:
在单独的服务器上,建议锁定内存,这样可以提高效率,具体配置是
bootstrap.memory_lock: true。
同时在elasticsearch的bin目录下,修改elasticseach.in.sh的ES_MIN_MEM=
ES_MAX_MEM=具体内存大小
6 kibana介绍
Kibana可以理解为一个展示ES数据的简单页面。
6.1 添加自定义字段解析数据查找数据
当对数据进行解析后,可以重新刷新来建立索引,操作流程
1:打开主页 http://ip:5601
2:点击Setting 然后再点击creat。
3:
6.1.1怎么查询指定交易号的记录
JSON数据展示
6.2 kibana普通查询语法
1:按页面左侧显示的字段搜索
例如左边有message host等等字段。
限定字段全文搜索:message:value
精确搜索:关键字加上双引号 message:"value"
如果要根据id来插叙 _id : 123456 等等
2:通配符模式
? 匹配单个字符
* 匹配0到多个字符
例如 *cn 前面的有47条记录 。或者是cn*这个就有70多条记录
3:时间定位
有quick Relative Absolute 等,等级越来越高。可以具体到几分几秒
点击右边
出现quick Relative Absolute
3:多条件组合搜索
多个检索条件的组合:- 代表了不能含有 +代表了必须含有
+ Checking 代表必须还有Checking - Checking:不能含有此项
And 表示和 or表示或者 Checking And to
4:近似搜索:
" Checking if "~2 表示 Checking 和 if 中间隔着2个单词以内
在查询的过程中,记得写空格。
6.3 kibana对应集群配置介绍
Kibana就是一个网页应用,数据是在es中,kibana上的操作不会存在损坏数据的问题,但是有延迟等缺点。
6.3.1:es采用自主选择主节点方式
A:只采用一个kibana情况
这个可以使用一个kibana对应2个es。前提是2个es必须都启动起来
但是出问题后坏掉。
B:采用2个kibana来读取es
每个kibana都对应一个es。配置好就可以了。
这个情况下,数据都不会被丢失,
实际查看的时候,如果2个es都是好的,那随便打开一个就可以。
如果一个坏了,那就只能打开es状态好的。
6.3.2 es采用单主节点模式
很简单,就是用一个kibana只连接到es的主节点上。