文章目录
一:背景
随着系统拆分越来越多或者集群的部署,之前通过登录服务器查询日志定位问题的方法有如下弊端
- 问题排查困难,查询一个服务的日志,需要登录多台服务器;
- 日志串接困难,一个流程有多个节点,要把整个流程的日志串接起来工作量大;
- 运维管理困难,不是每个同事都有登录服务器查看日志的权限,但又需要根据日志排查问题,就需要有权限的同事下载日志后给到相应负责的同事。
- 系统预警困难,无法实现服务出现异常后,及时通知到相应的负责人。
二:解决方案-ELK
ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana ,
- Elasticsearch是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等
- Logstash主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。一般工作方式为c/s架构,client端安装在需要收集日志的主机上,server端负责将收到的各节点日志进行过滤、修改等操作在一并发往elasticsearch上去。
- Kibana可以为 Logstash 和 ElasticSearch 通过报表、图形化数据进行可视化展示 Web
界面,可以帮助汇总、分析和搜索重要数据日志。
三:部署方案
部署方案主要有两种方案
1.生产日志的主机部署客户端收集日志,发送到kafka 然后 kafka-》logstash-》Elasticsearch-》Kibana
优点:
- 生产日志的服务不需要做任何改变
- 可以收集任何类型的日志文件,不一定非是web服务
- 之前的服务不需要改造,只需要修改收集客户端配置就可以了
缺点:
- 每台机子需要部署日志收集客户端,
- 如果有新日志要收集,需要修改收集客户端的配置文件
2.生产日志的服务使用logback直接输出日志到kafaka然后 kafka-》logstash-》Elasticsearch-》Kibana
优点:
- 新增加的服务,不需要做其他的配置,就可以直接输出日志到kafka
缺点:
- 仅仅支持使用logback等日志框架的服务来发送日志
- 老的服务需要改造,加入新的appender,才能收集
四:环境搭建
主机IP:192.168.100.17
我们这里采用第一种方案,对服务没有改造的需求,并且可以收集nginx等其他类型的日志。
日志客户端目前有两种:
- logstash agent
- filebeat
logstash agent 运行占用资源多,有可能影响服务器上其他的服务,而filebeat更轻量,占用资源更少,故我们采用filebeat。
准备
由于elasticsearch不允许以root身份运行,所以我们需要创建一个运行elasticsearch的用户(如:elssearch)
1)新建linux用户elssearch ,密码elssearch
[root@deappa17 ~]# groupadd elssearch
[root@deappa17 ~]# useradd elssearch -g elssearch
[root@deappa17 ~]# passwd elssearch
2)修改/etc/security/limits.conf文件,增加以下配置:
* soft nofile 65536
* hard nofile 131072
* soft nproc 2048
* hard nproc 4096
3 )修改/etc/sysctl.conf文件,增加以下配置
vm.max_map_count=655360
然后执行sysctl -p使之生效
4)为elssearch赋权,在文件/etc/sudoers中增加如下新增用户的配置
##Allow root to run any commands anywhere
root ALL=(ALL) ALL
elssearch ALL=(ALL) ALL
4)切换用户登录
1.elasticsearch安装
[elssearch@deappa17 ~]$ mkdir soft
[elssearch@deappa17 ~]$ cd soft/
[elssearch@deappa17 soft]$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ ll
total 289532
-rw-rw-r-- 1 elssearch elssearch 296477546 Mar 31 23:35 elasticsearch-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ tar -xzvf elasticsearch-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ vi ./elasticsearch-7.6.2/config/elasticsearch.yml
node.name: node-1
network.host: 192.168.100.17
http.port: 9200
cluster.initial_master_nodes: ["node-1"]
启动
[elssearch@deappa17 soft]$ ./elasticsearch-7.6.2/bin/elasticsearch
出现如下提示说明启动成功
[2020-04-09T13:53:15,238][INFO ][o.e.n.Node ] [deappa17.yufu99.com] started
或者后台启动
[elssearch@deappa17 soft]$ ./elasticsearch-7.6.2/bin/elasticsearch -d
访问http://192.168.100.17:9200/,如下说明启动成功
停止es:用jps找到进程号,kill 1174
2.Kibana安装
[elssearch@deappa17 soft]$ wget https://artifacts.elastic.co/downloads/kibana/kibana-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ ll
total 533240
drwxr-xr-x 10 elssearch elssearch 167 Apr 9 13:20 elasticsearch-7.6.2
-rw-rw-r-- 1 elssearch elssearch 296477546 Mar 31 23:35 elasticsearch-7.6.2-linux-x86_64.tar.gz
-rw-rw-r-- 1 elssearch elssearch 249555386 Mar 31 23:38 kibana-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ tar -zxvf kibana-7.6.2-linux-x86_64.tar.gz
[elssearch@deappa17 soft]$ vi kibana-7.6.2-linux-x86_64/config/kibana.yml
server.port: 5601
server.host: "192.168.100.17"
elasticsearch.hosts: ["http://192.168.100.17:9200"]
[elssearch@deappa17 soft]$ nohup ./kibana-7.6.2-linux-x86_64/bin/kibana &
访问http://192.168.100.17:5601/,出现如下页面说明成功
停止kibana:通过 ps aux | grep kibana找到进程号,杀掉 kill 进程号
3.logstash安装
[elssearch@deappa17 soft]$ wget https://artifacts.elastic.co/downloads/logstash/logstash-7.6.2.tar.gz
[elssearch@deappa17 soft]$ ll
total 702012
drwxr-xr-x 10 elssearch elssearch 167 Apr 9 13:20 elasticsearch-7.6.2
-rw-rw-r-- 1 elssearch elssearch 296477546 Mar 31 23:35 elasticsearch-7.6.2-linux-x86_64.tar.gz
drwxrwxr-x 13 elssearch elssearch 266 Apr 9 14:10 kibana-7.6.2-linux-x86_64
-rw-rw-r-- 1 elssearch elssearch 249555386 Mar 31 23:38 kibana-7.6.2-linux-x86_64.tar.gz
-rw-rw-r-- 1 elssearch elssearch 172679447 Mar 31 23:40 logstash-7.6.2.tar.gz
-rw------- 1 elssearch elssearch 136917 Apr 9 14:51 nohup.out
[elssearch@deappa17 soft]$ tar -zxvf logstash-7.6.2.tar.gz
[elssearch@deappa17 soft]$ vi logstash-7.6.2/config/kafka-logstash.conf
input{
kafka{
#logstash导出数据的解码方式,logstash输出的数据是json,es正好也是存json,
#如果不这样指定,进入es的数据,将会转义成普通字符串,进入source.message属性
codec =>"json"
#消费组
group_id => "kafka_elk_group"
#消费者标识
client_id => "kafka_logstash"
#消费的主题,如果不存在,logstash启动后会自动在kafka中创建
topics => ["elk-kafka-topic"]
#连接的kafka集群配置
bootstrap_servers => "192.168.100.17:9092"
#消费的起始位置
auto_offset_reset => "earliest"
#消费的线程数
consumer_threads => 5
}
#这里可以配置第二个输入
#beats {
# port => "5044"
#}
}
output{
elasticsearch{
hosts => ["192.168.100.17:9200"]
index => "testlog-elk-index-%{+YYYY.MM.dd}"
}
# 这里可以配置第二个输出
#elasticsearch{#}
}
启动,如果kafka没有启动,则等kafka安装完并启动后,再来启动logstash
[elssearch@deappa17 soft]$ logstash-7.6.2/bin/logstash -f logstash-7.6.2/config/kafka-logstash.conf
#或者后台启动, -r:会自动检查配置文件的变更,并自动加载,默认3秒一次
[elssearch@deappa17 soft]$ nohup logstash-7.6.2/bin/logstash -f logstash-7.6.2/config/kafka-logstash.conf -r &
停止logstash:通过jps找到进程号,杀掉,kill 进程号,不要强制杀,那样有可能会丢失事件
4.kafka安装
[elssearch@deappa17 soft]$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.4.1/kafka_2.12-2.4.1.tgz
[elssearch@deappa17 soft]$ ll
total 762912
drwxr-xr-x 10 elssearch elssearch 167 Apr 9 13:20 elasticsearch-7.6.2
-rw-rw-r-- 1 elssearch elssearch 296477546 Mar 31 23:35 elasticsearch-7.6.2-linux-x86_64.tar.gz
-rw-rw-r-- 1 elssearch elssearch 62358954 Mar 12 02:49 kafka_2.12-2.4.1.tgz
drwxrwxr-x 13 elssearch elssearch 266 Apr 9 14:10 kibana-7.6.2-linux-x86_64
-rw-rw-r-- 1 elssearch elssearch 249555386 Mar 31 23:38 kibana-7.6.2-linux-x86_64.tar.gz
drwxr-xr-x 13 elssearch elssearch 267 Apr 9 15:13 logstash-7.6.2
-rw-rw-r-- 1 elssearch elssearch 172679447 Mar 31 23:40 logstash-7.6.2.tar.gz
-rw------- 1 elssearch elssearch 136917 Apr 9 14:51 nohup.out
[elssearch@deappa17 soft]$ tar -zxvf kafka_2.12-2.4.1.tgz
#启动zookeeper,-daemon 表示后台启动
[elssearch@deappa17 soft]$ kafka_2.12-2.4.1/bin/zookeeper-server-start.sh -daemon kafka_2.12-2.4.1/config/zookeeper.properties
#配置kafka
[elssearch@deappa17 soft]$ vi kafka_2.12-2.4.1/config/server.properties
listeners=PLAINTEXT://192.168.100.17:9092
num.partitions=5
zookeeper.connect=192.168.100.17:2181
#启动kafka
[elssearch@deappa17 soft]$ kafka_2.12-2.4.1/bin/kafka-server-start.sh -daemon kafka_2.12-2.4.1/config/server.properties
[elssearch@deappa17 soft]$ jps
8308 Jps
7558 QuorumPeerMain
3577 Elasticsearch
8185 Kafka
停止kafka:bin/kafka-server-stop.sh
kafka其他常用命令
#列出所有的topic
kafka_2.12-2.4.1/bin/kafka-topics.sh --zookeeper 192.168.100.17:2181 --list
# 查看某个topic
kafka_2.12-2.4.1/bin/kafka-topics.sh --zookeeper 192.168.100.17:2181 --describe --topic elk-kafka-topic
# 生产消息
kafka_2.12-2.4.1/bin/kafka-console-producer.sh --broker-list 192.168.100.17:9092 --topic elk-kafka-topic
# 消费消息
kafka_2.12-2.4.1/bin/kafka-console-consumer.sh --bootstrap-server 192.168.100.17:9092 --topic elk-kafka-topic --from-beginning
5.测试kafka->logstash->es->kibana
测试之前别忘记先启动logstash,启动后,如果监听的topic没有,会自动创建
向kafka插入数据
[elssearch@deappa17 soft]$ kafka_2.12-2.4.1/bin/kafka-console-producer.sh --broker-list 192.168.100.17:9092 --topic elk-kafka-topic
>test1
>test2
>test3
先在kibana中为索引建立一个pattern(es和kibana操作可以自行百度,后面会介绍一些日志分析常用的操作)
如下图所示,说明数据已经从kafka传到到了es,之前的配置都已经成功
6.继续安装filebeat
[elssearch@deappa17 soft]$ wget https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.6.2-x86_64.rpm
[elssearch@deappa17 soft]$ sudo yum install filebeat-7.6.2-x86_64.rpm
#修改配置,并注释掉 Logstash output的内容
[elssearch@deappa17 soft] sudo vi /etc/filebeat/filebeat.yml
- type: log
enabled: true
paths:
- /home/elssearch/tomcat/logs/*
output.kafka:
hosts: ["192.168.100.17:9092"]
topic: "elk-kafka-topic"
keep_alive: 10s
[elssearch@deappa17 soft]sudo systemctl start filebeat
rpm安装后的命令使用说明
- systemctl start filebeat #启动
- systemctl stop filebeat #停止
- systemctl enable filebeat #开机启动,安装后已经是开机启动了
- systemctl disable filebeat #开机不启动
- systemctl status filebeat #查看状态
- journalctl -u filebeat.service #查看日志
- systemctl restart filebeat.service #重启
rpm安装后的文件目录结构
7.继续验证,在相应的位置放入.log结尾的文件,然后在kibana可以看到,说明成功
此为filebeat为log文件中每行记录生成的json数据,message字段为log中的内容,其他都是filebeat附加的:
{ “ecs”: { “version”: “1.4.0” }, “input”: { “type”: “log” }, “agent”: { “ephemeral_id”: “6340678d-5a71-4b16-a21b-08225b750314”, “type”: “filebeat”, “hostname”: “demysd23.yufu99.com”, “id”: “9073972c-e8a4-40c5-88b2-706780e581ef”, “version”: “7.6.2” }, “host”: { “hostname”: “demysd23.yufu99.com”, “id”: “d63b1b80122d419fa2ca831122bc38ec”, “containerized”: false, “os”: { “codename”: “Core”, “family”: “redhat”, “platform”: “centos”, “name”: “CentOS Linux”, “version”: “7 (Core)”, “kernel”: “3.10.0-957.el7.x86_64” }, “name”: “demysd23.yufu99.com”, “architecture”: “x86_64” }, “message”: “郭阳1”, “log”: { “offset”: 0, “file”: { “path”: “/root/soft/tomcat/test.log” } } }
五:思考问题
1.如何把每个服务或应用的日志,在es中建成单独的index
1). 在filebeat中可以通过两种方法来为每一个消息来附加字段
tags: ["springboottest"]
fields: {project: "myproject", instance-id: "574734885120952459"}
这样可以在logstash中使用,来识别创建动态的index,或者在kibana中作为过滤条件来使用,添加后输出如图
2). 可以通过如下方式,为不同的输入文件配置单独的附加属性,假设不同的文件是不同的服务生成的
filebeat.inputs:
- type: log
paths:
- /var/log/system.log
- /var/log/wifi.log
- type: log
paths:
- "/var/log/apache2/*"
fields:
apache: true
fields_under_root: true
3). 最终filebeat配置如下
filebeat.inputs:
- type: log
enabled: true
paths:
- /home/elssearch/tomcat/logs/*
tags: ["springboottest"]
fields: {service: "merservice", port: "8080"}
- type: log
enabled: true
paths:
- /home/elssearch/tomcat2/logs/*
tags: ["springboottest"]
fields: {service: "apiservice", port: "8082"}
4). 修改logstash配置
input{
kafka{
#logstash导出数据的解码方式
codec =>"json"
#消费组
group_id => "kafka_elk_group"
#消费者标识
client_id => "kafka_logstash"
#消费的主题
topics => ["elk-kafka-topic"]
#连接的kafka集群配置
bootstrap_servers => "192.168.100.17:9092"
#消费的起始位置
auto_offset_reset => "earliest"
#消费的线程数
consumer_threads => 5
}
}
output{
elasticsearch{
hosts => ["192.168.100.17:9200"]
index => "%{[host][name]}-%{[fields][service]}-%{[fields][port]}-%{+YYYY.MM.dd}"
}
}
5). es中验证
2.日志时间问题
默认filebeat会为event生成@timestamp,但是这个时间是读取日志的时间,所以我们还要解析日志文件中的日志时间,并设置为@timestamp,比如消息格式为
2020-04-10 09:57:04.856 [main] INFO o.s.scheduling.concurrent.ThreadPoolTaskExecutor - Initializing ExecutorService 'taskExecutor'
在logstash的配置文件中加入filter
filter {
# 用正则表达式匹配message中的时间,格式为yyyy-MM-dd HH:mm:ss.SSS,并放入logdate字段
grok {
match => { "message" => "(?<logdate>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\.\d{3})"}
}
# 解析logdate字段,并设置到@timestamp字段
date {
match => [ "logdate", "yyyy-MM-dd HH:mm:ss.SSS" ]
#时区问题
#原因:elk(es和logstash和kibana)都是使用utc作为内部时区(无法修改),经过logstash或存入es的时
#间,会使用elk服务器的时区,比如在中国,东八区,存入上午点,经过logstash会转为utc时区的时间,就是
#上午1点,就是说es中存入的是1点;
#通过kibana查询时,查询条件的时间段kibana会自动转为utc时间,发送到es,kibana显示数据时也会转为当
#前的时区,上午9点,所以都没有问题;但是你通过自己查询,查出的数据是1点,需要自己转为当前时区9点,
#并且查询的时间区间条件也需要自己先转为utc时间,才能正确匹配;
#基于上面原因,我们可以设置,也可以不设置如下参数,看个人方便了,设置后elk会做调整,进入的时间elk
#就认为已经是utc时间了,所以不会做转换,你存入的是什么,es中就是什么;比如存的是9点,es中存的就是9点
#这样做在kibana中显示会有问题,但可以通过配置系统时区为utc也解决,而查询的时间区间条件,kibana还是会先转位utc时间,比如你查询8-10点,
#之间的数据,kibana会转为UTC时间0-2点,所以无法匹配数据了,无法解决(修改源码把kibana时区改为utc估计可以解决)
#言而总之,总而言之:
#设 置:存入时间时elk不会转换,kibana显示不好使,但可以通过上面方法解决;而查询不好使了,无法解决。
#但自己通过restfulApi查询时,好使;
#不设置:进入elk的时间会转换,kibana显示时会转换没啥问题,但自己通过restfulApi查询时,需要自己做转换
#timezone => "+00:00"
}
}
3.像logback这种有滚动的日志文件,是否可以正常处理
filebeat配置如下
paths:
- /home/elssearch/tomcat/logs/mposgw-all-log.log
#- c:\programdata\elasticsearch\logs\*
tags: ["springboottest"]
mposgw-all-log.2020-04-13.0文件日志输出到 日志数据>>>196591,其他的进入mposgw-all-log.log
但是es数据如下,确实有问题,丢失了100000-196591之间的数据,该如何解决?
经过验证如果做如下配置,则消息不会丢失(就是配置读取某个应用生成的所有文件)
paths:
- /home/elssearch/tomcat/logs/*
#- c:\programdata\elasticsearch\logs\*
tags: ["springboottest"]
4.日志排序问题
不管是是使用filebeat生成的@timestamp,还是解析日志中的时间作为@timestamp,都存在一个问题:如果两条日志的记录时间一模一样,那么无法按照真实产生日志的情况排序
个人认为需要通过在日志中增加输出序列来解决,这样系统要改造,成本大,最主要的是就算发生了这种情况,对分析日志的影响也不大,如果确实需要,可以通过拉取原始日志文件来解决,所以暂不考虑
六:参考网站
https://www.cnblogs.com/jiyuyun/p/9141148.html
https://www.elastic.co/guide/index.html