ELK的优势和部署调研
一. ELK是什么
1.传统项目日志查看的痛点
在项目初期的时候,大家都是赶着上线,一般来说对日志没有过多的考虑,当然日志量也不大,所以用log4j就够了,随着应用的越来越多,日志散落在各个服务器的logs文件夹下,确实有点不大方便。
当我们需要日志分析的时候你大概会这么做:直接在日志文件中 grep、awk 就可以获得自己想要的信息。
那你们想过这种方式的问题吗?
1.日志量太大如何归档、文本搜索太慢怎么办、如何多维度查询
2.应用太多,面临数十上百台应用时你该怎么办
3.随意登录服务器查询log对系统的稳定性及安全性肯定有影响
4.如果使用人员对Linux不太熟练那面对庞大的日志简直要命。
2.elk的解决的问题
那么为什么要用ELK呢?ELK又能给我们解决哪些问题呢?
1.日志统一收集,管理,访问。查找问题方便安全:收集放到搜索引擎中。也就就是ELK中的E表示es:分布式搜索引擎存储库。是一个Nosql。其核心是倒排索引库。可存TB级的数据。
2.使用简单,可以大大提高定位问题的效率:一个页面搞定所有查询。K:kibana。
3.可以对收集起来的log进行分析。L:Logstash,就是用收集日志。会部署到应用服务器上面。还可以提供过滤功能。
4.能够提供错误报告,监控机制。
二. ELK架构设计
ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件
1. LogStash
官方介绍:Logstash is an open source data collection engine with real-time pipelining capabilities。简单说logstash就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端;与此同时这根管道还可以让你根据自己的需求在中间加上滤网,Logstash提供里很多功能强大的滤网以满足你的各种应用场景。Logstash常用于日志关系系统中做日志采集设备 它可以流放到各自的服务器上收集Log文件日志,通过内置的ElasticSearch插件解析后输出到ES中
2.ElasticSearch
这是一个基于Lucene的分布式全文搜索框架,可以对logs进行分布式存储。此为ELK的核心组件,日志的分析以及存储全部由es完成,所以elk中es是最重要的角色。
3.Kibana
它可以多维度的展示es中的数据。可提供图表展示,造出一些非常炫酷的页面。这也解决了用mysql存储带来了难以可视化的问题。他提供了丰富的UI组件,简化了使用难度,数据在es中的展示是比较让人头疼的,后面展示es的时候让大家看看。
目前ELK主要有两种框架:
1.普通框架:
这一套框架不会影响生成应用。唯一形象的就是logstash会耗一点系统资源。
logstash部署到服务的每台机器上收集日志信息,es搜索引擎库会根据logstash的信息建立索引
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4E41fc3F-1604038012171)(D:\ext.dengyongliang\Desktop\elk\2222.png)]
1.1.普通轻量级框架(维护成本高)
filebeat是非常轻量级的日志收集软件,通过filebeat收集发到logstash做一些日志过滤处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjK5z6wy-1604038012177)(D:\ext.dengyongliang\Desktop\elk\666.png)]
2.个性化扩展框架
(针对日志数据需要二次处理以及多方使用的场景):kafka(不建议用比较耗资源,除非针对TB数据):
- 使用RabbitMQ、Kafka的原因,日志量巨大的时候
logstash、redis(一般是用LIST)都是队列,起到缓冲作用,也就是削峰填谷。
如果直接写到ES的话,由于ES的HTTP API处理能力有限,在日志写入频繁的情况下可能会超时、丢失,所以用队列来做缓冲。
还有些公司是用RabbitMQ、Kafka,以及一些更先进的消息队列来缓冲日志的。
- Shipper,indexer, 配置Redis:
配置博客:https://www.cnblogs.com/zhaoyangjian724/p/6199335.html
LogStash的Shipper和Indexer自身没有什么角色,只是根据不同的功能、不同的配置给出不同的称呼而已。
- Shipper
Shipper主要是安装在需要收集的日志服务器上,其input为实际的日志源,output一般来说都是redis(你要是不想用redis做缓存也可以用其他的)
- Indexer
Indexer则是单独部署(可以集群),其input是redis(shipper的output),output则是elasticSearch搜索引擎。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fFqAZGVg-1604038012179)(D:\ext.dengyongliang\Desktop\elk\444.png)]
三.elk安装
1.es安装
1).官方下载 :https://www.elastic.co/cn/products/4.6.1
2)liunux系统:
-
安装jdk1.7+ ,
-
新建用户和组:注意安装es不能用root安装
groupadd apps(新建组)
useradd -m -g apps apps(新建组下的用户)
3).上传安装包并解压:
tar -zxvf elasticsearch-2.4.6.tar.gz
4)***安装的核心,修改配置文件(重要)
```java
配置文件:
cluster.name: my-es #注意一个集群里面的机器一定要保持一致
node.name: node-01 #集群需要改名字 同一个集群里面的名字不能相同
node.master: true #尽量配置机器差作为主节点 注意只有两个节点的话第二个请配置为false
node.data: true
http.port: 9200
transport.tcp.port: 9300
network.host: 0.0.0.0 #外网访问
#单播(unicast)协议,指定要发现的节点信息了,可以不指定端口[默认9300]
discovery.zen.ping.unicast.hosts: [“192.168.50.12”,“192.168.50.12:8300”]
#默认是1看到的具有master节点资格的最小数量,然后才能在集群中做操作。官方的推荐值是(N/2)+1,如果只有2个节点设为1
discovery.zen.minimum_master_nodes: 1
discovery.zen.ping.timeout:3s #ping的超时时间,如果网络差则延长
discovery.zen.ping.timeout:180s #设置集群中自动发现其他节点时ping连接的超时时间
http.cors.enabled: true
http.cors.allow-origin: “*”
bootstrap.system_call_filter: false
```
问题一:外网访问不了:防火墙,端口开放。
问题二:es集群连不上,或者启动报错。请注意如果是直接复制的es文件夹则一定要先去删除es文件夹下面的data目录下所有的文件。否则启动必报错。
5)启动
[apps@localhost bin]$ ./elasticsearch
[2020-10-28 19:33:25,924][INFO ][node ] [node-01] version[2.4.6], pid[1597], build[5376dca/2017-07-18T12:17:44Z]
[2020-10-28 19:33:25,924][INFO ][node ] [node-01] initializing ...
.....
[2020-10-28 19:33:35,545][INFO ][http ] [node-01] publish_address {192.168.50.12:9200}, bound_addresses {[::]:9200}
[2020-10-28 19:33:35,545][INFO ][node ] [node-01] started
[2020-10-28 19:33:35,641][INFO ][gateway ] [node-01] recovered [0] indices into cluster_state
6)访问
http://192.168.50.12:9200/
{
"name" : "node-01",
"cluster_name" : "my-es",
"cluster_uuid" : "7BQYmZxLSyS_68CqkyMpDg",
"version" : {
"number" : "2.4.6",
"build_hash" : "5376dca9f70f3abef96a77f4bb22720ace8240fd",
"build_timestamp" : "2017-07-18T12:17:44Z",
"build_snapshot" : false,
"lucene_version" : "5.5.4"
},
"tagline" : "You Know, for Search"
}
2.Es-head插件安装(es图像化界面插件)
1).用命令安装
[apps@localhost elasticsearch-2.4.6]$ cd bin
[apps@localhost bin]$ ./plugin install mobz/elasticsearch-head
2).安装成功plugins文件夹会有head目录
/home/apps/services/temp_elk/elasticsearch-2.4.6/plugins
[apps@localhost plugins]$ ls
head
3)后台重新启动es,-d表示后台启动
[apps@localhost elasticsearch-2.4.6]$ ./bin/elasticsearch -d
tail -f logs/my-es.log
4)图形界面访问
查看集群的配置信息,数据信息
http://192.168.50.12:9200/_plugin/head/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6btTNQnT-1604038012184)(D:\ext.dengyongliang\Desktop\elk\微信截图_20201028135001.png)]
3.安装logstash
1)下载logstash-2.4.0
2)在新建的用户下解压,tar -zxvf logstash-2.4.0.tar.gz
3) 新建目录mkdir config,新建logstash.conf
如果是日志格式不同如.log的或者.out的可以建多个,如建logstash-log.conf 和logstash-out.conf 里面path路径和规则稍微改一下就可以了
[apps@localhost config]$ cat logstash.conf
input { # 收集标志
file {
type => "log"
path => "[/home/apps/svr/*/logs/*.log]" #注意此为logstash机器的路径,收集日志的地方,注意不能远程收取
start_position => "end" # 如果log文件已经很大了 不要配start,如果服务挂了,重启第二次会有记录
ignore_older => 0 #忽略最后修改时间时大于s的
codec=> multiline { #重点,配置log换行问题
pattern => "^%{TIMESTAMP_ISO8601}"
negate => true
what => "previous"
}
}
beats {
port => 5044
}
}
}
output {
if [type] == "log" { # type和上面的收集type一致
elasticsearch {
hosts => ["http://127.0.0.1:9200"]
index => "log-%{+YYYY.MM}" # 表示的是索引库(自动在es里面建的) 按日期分,也可按数据量大也可以按日分"log-%{+YYYY.MM.dd}"
# user => user #配置ngnix用的,安全登录
# password => pwd
}
}
}
4)启动
[apps@localhost logstash-2.4.0]$ ./bin/logstash -f config/logstash.conf
后台启动:nohup ./bin/logstash -f config/log.conf > log.log &
5)成功,在/home/apps/svr/test/log目录下放一些日志,可以看到es中新建索引和收集的日志信息
Settings: Default pipeline workers: 1
log4j:WARN No appenders could be found for logger (io.netty.util.internal.logging.InternalLoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Pipeline main started
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lrXO2Dvp-1604038012188)(D:\ext.dengyongliang\Desktop\elk\微信截图_20201028175216.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tTZVSyUh-1604038012192)(D:\ext.dengyongliang\Desktop\elk\微信截图_20201028173437.png)]
4.安装Kibana(es里面最好先收集一些日志,否则libana的create按钮不会出现)
1)版本kibana-4.6.1-linux-x86_64
2)解压安装:tar -zxvf kibana-4.6.1-linux-x86_64.tar.gz
- 修改配置文件
vim /home/apps/services/temp_elk/kibana-4.6.1-linux-x86_64/config/kibana.yml
放开这段话就可以了
#elasticsearch.url: "http://127.0.0.1:9200"
4)启动
窗口启动:[apps@localhost kibana-4.6.1-linux-x86_64]$ ./bin/kibana
后台启动:nohup ./bin/kibana &
5)登录Kibana,并添加索引库
http://192.168.50.12:5601/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6xB6YEDG-1604038012196)(D:\ext.dengyongliang\Desktop\elk\111.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5or391Ks-1604038012197)(D:\ext.dengyongliang\Desktop\elk\微信截图_20201028181008.png)]
添加好索引库后点击create按钮
6)搜索【ERROR】信息,
-
注意右上角的时间,最好改成一个月的
-
多个微服务用host去区分,配成ip或者机器名
-
多个项目如何区分,type和host可以做一些相应的标志配置,搜索时用左侧的Selected Fields,选择对应的项目的type就可以了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-97SyCDat-1604038012200)(D:\ext.dengyongliang\Desktop\elk\2020-10-29_095935.png)]
四.项目演示
演示项目git地址:
将elk服务都起好,新建项目:elk-restful,日志文件的地址配到我们logstash的收集地址,/home/apps/svr/test/logs
1.发送一个请求成功的请求
http://192.168.50.12:9999/queryPayment
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KgelcE2-1604038012205)(D:\ext.dengyongliang\Desktop\elk\777.png)]
@GetMapping(value = "/queryPayment")
public CommonResponse create(Payment payment) {
int refno=0;
try {
refno=Random.class.newInstance().nextInt();
}catch (Exception e){
}
payment.setRefNO(refno);
payment.setGoodsName("苹果");
payment.setMoney(1);
log.info("*****serverPort:"+serverPort+"payment结果*****"+payment);
return CommonResponse.builder().requestId(MDC.get(ElkConstant.X_REQUEST_ID)).result(payment).build();
}
1.1.根据请求成功的RequestId去查询相应的日志,几乎实时获取到请求成功的服务日志
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TDVaDRzv-1604038012207)(D:\ext.dengyongliang\Desktop\elk\999.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACmcfbaI-1604038012213)(D:\ext.dengyongliang\Desktop\elk\88.png)]
2.发送失败的请求
http://192.168.50.12:9999/queryError
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jkKxyazi-1604038012214)(D:\ext.dengyongliang\Desktop\elk\1010.png)]
@GetMapping(value = "/queryError")
public CommonResponse queryError(Payment payment) {
try {
int i=10/0;
}catch (Exception e){
String request_id=MDC.get(ElkConstant.X_REQUEST_ID);
log.error("elk异常日志queryError 报错了 exception,request_id:{}",request_id , e);
throw new ElkException(ELK_UNKNOWN_ERROR,"elk异常日志queryError 报错了", e.toString());
}
return CommonResponse.builder().requestId(MDC.get(ElkConstant.X_REQUEST_ID)).result("查询成功!").build();
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FoHF4SWX-1604038012216)(D:\ext.dengyongliang\Desktop\elk\1212.png)]
QUEST_ID);
log.error(“elk异常日志queryError 报错了 exception,request_id:{}”,request_id , e);
throw new ElkException(ELK_UNKNOWN_ERROR,“elk异常日志queryError 报错了”, e.toString());
}
return CommonResponse.builder().requestId(MDC.get(ElkConstant.X_REQUEST_ID)).result(“查询成功!”).build();
}
[外链图片转存中...(img-FoHF4SWX-1604038012216)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-stj0q183-1604038012219)(D:\ext.dengyongliang\Desktop\elk\1313.png)]