1、ELK简介
ELK是Elasticsearch+Logstash+Kibana的简称
ElasticSearch是一个基于Lucene的分布式全文搜索引擎,可以用于全文检索、结构化检索和分析,并能将这三者结合起来,
提供 RESTful API进行数据读写,现在是使用最广的开源搜索引擎之一。
Logstash 简单来说就是一根具备实时数据传输能力的管道,负责将数据信息从管道的输入端传输到管道的输出端,与此同时这根
管道还可以让你根据自己的需求在中间加上滤网,Logstash提供了很多功能强大的滤网以满足你的各种应用场景,在这里是一个收集,
处理和转发事件和日志消息的工具
Kibana是Elasticsearch的开源数据可视化插件,为查看存储在ElasticSearch提供了友好的Web界面,可以用kibana搜索、查看、交
互存放在Elasticsearch索引里的数据,并提供了条形图,线条和散点图,饼图和地图等分析工具
总的来说,ElasticSearch负责存储数据,Logstash负责收集日志,并将日志格式化后写入ElasticSearch,Kibana提供可视化
访问ElasticSearch数据的功能。
2、ELK工作流
应用将日志按照约定的Key写入Redis,Logstash从Redis中读取日志信息写入ElasticSearch集群。
Kibana读取ElasticSearch中的日志,并在Web页面中以表格/图表的形式展示。
1、服务器&软件环境说明服务器一共准备3台CentOS7 Server
服务器名 IP 说明
es1 192.168.1.20 部署ElasticSearch主节点
es2 192.168.1.21 部署ElasticSearch从节点
elk 192.168.1.22 部署Logstash + Kibana + Redis
这里为了节省,只部署2台Elasticsearch,并将Logstash + Kibana + Redis部署在了一台机器上。
如果在生产环境部署,可以按照自己的需求调整。
软件环境
项 说明
Linux Server CentOS 7
Elasticsearch 6.3.0
Logstash 6.3.0
Kibana 6.3.0
Redis 4.0.2
JDK 1.8
2、ELK环境准备
由于Elasticsearch、Logstash、Kibana均不能以root账号运行。
但是Linux对非root账号可并发操作的文件、线程都有限制。
所以,部署ELK相关的机器都要调整:
#修改系统文件
vi /etc/security/limits.conf
#增加的内容
* soft nofile 65536
* hard nofile 65536
* soft nproc 2048
* hard nproc 4096
#修改系统文件
vi /etc/security/limits.d/20-nproc.conf
#调整成以下配置
* soft nproc 4096
root soft nproc unlimited
#修改系统文件
vi /etc/sysctl.conf
#增加的内容
vm.max_map_count=655360
fs.file-max=655360
reboot
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
#(1)下载之后FTP到服务器
#(2)获取到下载链接后,用wget命令下载
#(3)本次下载版本为: jdk-8u172
2、解压到指定目录
sudo mkdir -p /usr/java
sudo tar zxf jdk-8u172-linux-x64.tar.gz -C /usr/java
3、配置环境变量
vi /etc/profile
# 在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL下添加
export JAVA_HOME=/usr/java/jdk1.8.0_172#(需要配置多JDK版本共存时可注释该行)
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
4、使环境变量生效
source /etc/profile
5、检查是否配置成功
java -version
useradd elk
#创建ELK APP目录
mkdir /home/elk/elk
#创建ELK 数据目录
mkdir /home/elk
#更改目录Owner
chown -R elk:elk /home/elk/elk
chown -R elk:elk /home/elk
#打开文件夹
cd /home/download
#下载
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.0.tar.gz
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.3.0.tar.gz
wget wget https://artifacts.elastic.co/downloads/kibana/kibana-6.3.0-linux-x86_64.tar.gz
#解压
tar -zvxf elasticsearch-6.3.0.tar.gz
tar -zvxf logstash-6.3.0.tar.gz
tar -zvxf kibana-6.3.0-linux-x86_64.tar.gz
本次一共要部署两个Elasticsearch节点,所有文中没有指定机器的操作都表示每个Elasticsearch机器都要执行该操作
1、准备工作
#移动目录
mv /home/download/elasticsearch-6.3.0 /home/elk/elk
#赋权
chown -R elk:elk /home/elk/elk/elasticsearch-6.3.0/
#增加端口
firewall-cmd --add-port=9200/tcp --permanent
firewall-cmd --add-port=9300/tcp --permanent
#重新加载防火墙规则
firewall-cmd --reload
#账号切换到 elk
su - elk
创建Elasticsearch主目录
mkdir /home/elk/es
#创建Elasticsearch数据目录
mkdir /home/elk/es/data
#创建Elasticsearch日志目录
mkdir /home/elk/es/logs
2、Elasticsearch 配置
#打开目录
cd /home/elk/elk/elasticsearch-6.3.0
#修改配置
vi config/elasticsearch.yml
cluster.name: es
node.name: es1
path.data: /home/elk/es/data
path.logs: /home/elk/es/logs
network.host: 192.168.1.20
http.port: 9200
transport.tcp.port: 9300
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["192.168.1.20:9300","192.168.1.21:9300"]
discovery.zen.minimum_master_nodes: 1
cluster.name: es
node.name: es2
path.data: /home/elk/es/data
path.logs: /home/elk/es/logs
network.host: 192.168.1.21
http.port: 9200
transport.tcp.port: 9300
node.master: false
node.data: true
discovery.zen.ping.unicast.hosts: ["192.168.1.20:9300","192.168.1.21:9300"]
discovery.zen.minimum_master_nodes: 1
项 说明
cluster.name 集群名
node.name 节点名
path.data 数据保存目录
path.logs 日志保存目录
network.host 节点host/ip
http.port HTTP访问端口
transport.tcp.port TCP传输端口
node.master 是否允许作为主节点
node.data 是否保存数据
discovery.zen.ping.unicast.hosts 集群中的主节点的初始列表,当节点(主节点或者数据节点)启动时使用这个列表进行探测
discovery.zen.minimum_master_nodes 主节点个数
2、Elasticsearch 启动&健康检查
#进入elasticsearch根目录
cd /home/elk/elk/elasticsearch-6.3.0
#后台启动
nohup ./bin/elasticsearch > elasticsearch.log &
curl http://192.168.1.20:9200/_cluster/health
如果返回status=green表示正常
{
"cluster_name": "esc",
"status": "green",
"timed_out": false,
"number_of_nodes": 2,
"number_of_data_nodes": 2,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100.0
}
1、准备工作
#安装基础依赖包
sudo yum install -y gcc gcc-c++ make jemalloc-devel epel-release
下载Redis( https://redis.io/download )
#从官网获取最新版本的下载链接,然后通过wget命令下载
wget http://download.redis.io/releases/redis-4.0.2.tar.gz
#创建目录
sudo mkdir /home/redis
#解压
sudo tar -zvxf redis-4.0.2.tar.gz -C /home/redis
#进入目录
cd /home/redis/redis-4.0.2
#编译&安装
sudo make & make install
#进入src目录
cd /home/redis/redis-4.0.2/src
#启动服务端
sudo ./redis-server
#进入src目录
cd /home/redis/redis-4.0.2/src
#启动客户端
sudo ./redis-cli
设置:set key1 value1
获取:get key1
#修改配置文件
sudo vi /home/redis/redis-4.0.2/redis.conf
#更换绑定
#将bind 127.0.0.1 更换为本机IP,例如:192.168.1.22
这里我改为了所有机器都可以连接的方式
bind 0.0.0.0
#关闭保护模式
protected-mode no
#增加redis端口:6379
sudo firewall-cmd --add-port=6379/tcp --permanent
#重新加载防火墙设置
sudo firewall-cmd --reload
#进入目录
cd /home/redis/redis-4.0.2
#指定配置文件启动
sudo ./src/redis-server redis.conf
#进入目录
cd /home/redis/redis-4.0.2
#连接指定Redis Server
sudo ./src/redis-cli -h 192.168.1.22
2、配置Redis开机启动
将Redis配置成为系统服务,以支持开机启动
#创建服务文件
sudo vi /usr/lib/systemd/system/redis.service
#文件内容
[Unit]
Description=Redis Server
After=network.target
[Service]
ExecStart=/home/redis/redis-4.0.2/src/redis-server /home/redis/redis-4.0.2/redis.conf --daemonize no
ExecStop=/home/redis/redis-4.0.2/src/redis-cli -p 6379 shutdown
Restart=always
[Install]
WantedBy=multi-user.target
#设置Redis服务开机启动
sudo systemctl enable redis
#启动Redis服务
sudo systemctl start redis
安装Logstash
#移动目录
mv /home/download/logstash-6.3.0 /usr/elk
#赋权
chown -R elk:elk /home/elk/elk/logstash-6.3.0/
#账号切换到 elk
su - elk
#创建Logstash主目录
mkdir /home/elk/logstash
#创建Logstash数据目录
mkdir /home/elk/logstash/data
#创建Logstash日志目录
mkdir /home/elk/logstash/logs
2、Logstash配置
#打开目录
cd /home/elk/elk/logstash-6.3.0
#修改配置
vi config/logstash.yml
#增加以下内容
path.data: /home/elk/logstash/data
path.logs: /home/elk/logstash/logs
vi config/input-output.conf
#配置内容
input {
redis {
data_type => "list"
key => "logstash"
host => "192.168.1.22"
port => 6379
threads => 5
codec => "json"
}
}
filter {
}
output {
elasticsearch {
hosts => ["192.168.1.20:9200","192.168.1.21:9200"]
index => "logstash-%{type}-%{+YYYY.MM.dd}"
document_type => "%{type}"
}
stdout {
}
}
该配置就是从redis中读取数据,然后写入指定的elasticsearch
Redis核心配置项说明:
配置项 说明
data_type => “list” 数据类型为list
key => “logstash” 缓存key为:logstash
codec => “json” 数据格式为:json
#进入Logstash根目录
cd /home/elk/elk/logstash-6.3.0
#后台启动方式
nohup ./bin/logstash -f config/input-output.conf > logstash.log &
[INFO ][logstash.pipeline ] Pipeline started {"pipeline.id"=>"main"}
[INFO ][logstash.agent ] Pipelines running {:count=>1, :pipelines=>["main"]}
#移动目录
mv /home/download/kibana-6.3.0-linux-x86_64 /home/elk/elk/kibana-6.3.0
#赋权
chown -R elk:elk /home/elk/elk/kibana-6.3.0/
#增加端口
firewall-cmd --add-port=5601/tcp --permanent
#重新加载防火墙规则
firewall-cmd --reload
#账号切换到 elk
su - elk
#进入kibana-6.3.0根目录
cd /home/elk/elk/kibana-6.3.0
#修改配置
vi config/kibana.yml
#增加以下内容
server.port: 5601
server.host: "192.168.1.22"
elasticsearch.url: "http://192.168.1.20:9200"
#进入kibana-6.0.0根目录
cd /home/elk/elk/kibana-6.0.0
#后台启动方式
nohup ./bin/kibana > kibana.log &
浏览器访问: 192.168.1.22:5601
警告提示:No default index pattern. You must select or create one to continue.
错误提示:Unable to fetch mapping. do you have indices matching the pattern?
这是因为还没有写入日志
1、日志写入
日历写入的话,写入到logstash监听的redis即可。
数据类型之前在/usr/elk/logstash-6.0.0/config/input-uput.conf中有配置
#启动redis客户端
#执行以下命令
lpush logstash '{"host":"127.0.0.1","type":"logtest","message":"hello"}'
Jedis jedis = new Jedis("192.168.1.22", 6379);
for (int i = 0; i < 1000; i++) {
jedis.lpush("logstash", "{\"host\":\"127.0.0.1\",\"type\":\"logtest\",\"message\":\"" + i + "\"}");
}
2、Kibana使用
浏览器访问:192.168.1.22:5601
此时会提示: Configure an index pattern
Configure an index pattern
直接点击create即可
浏览器访问:192.168.1.22:5601/app/kibana#/discover 即可查看日志
在有日志的每台服务器都安装Logstash作为收集工具收集日志和上面的安装步骤一样进行安装
因为我们流程是:
Logstash将日志按照约定的Key写入Redis,Logstash从Redis中读取日志信息写入ElasticSearch集群。
Kibana读取ElasticSearch中的日志,并在Web页面中以表格/图表的形式展示。
(当然也可以直接由Logstash往Elasticsearch写数据,因为我们采用分布式部署)
操作过程遇到的问题:(如果安装的Logstash在有权限限制的用户下Logstash不能正常在文件中进行读写操作不能正常运行因此切换到root用户下操作)
Logstash & redis写入数据配置文件如下:
java的异常日志通常是多行的,使用logstash和filebeat收集的时候每行就会当成一条日志(事件),这样是不连贯的。所以,我们需要对这种日志进行合并.
增加一个匹配java日志的partten文件,目的是匹配以 “2017-11-15 08:04:23:889” 这种时间格式开头的日志
# vim /home/elk/elk/logstash-6.3.0/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-4.1.2/patterns/catalina
WORDS [a-zA-Z]{3}
CATALINAOUT ^(\s*%{YEAR}|%{MONTHDAY})-(%{MONTHNUM}|%{WORDS})-(%{MONTHDAY}|%{YEAR}) %{HOUR}:?%{MINUTE}(?::?%{SECOND})
通过codec的mutiline插件将多行合并成一行
添加配置文件
#打开目录
cd /home/elk/elk/logstash-6.3.0/
#添加编辑新的配置文件
vi config/input-output.conf
#新增测试配置:
input {
file {
id => "input-file"
type => "javalog"
path => ["/home/ruijie/diagon/log/*.log"]
codec => multiline { # 使用codec/multiline插件
pattern => "%{CATALINAOUT}" # 指定匹配的表达式
negate => true # 是否匹配到
what => "previous" # 可选previous或next, previous是合并到匹配的上一行末尾
max_lines => 1000 # 最大允许的行
max_bytes => "10MiB" # 允许的大小
auto_flush_interval => 60 # 如果在规定时候内没有新的日志事件就不等待后面的日志事件
}
}
}
filter { #过滤规则,将日志级别为INFO,DEBUG的过滤掉
grok {
match => ["message","\s*%{TIMESTAMP_ISO8601}\s+(?(\S+)).*"]
}
if [Level] == "DEBUG" {
drop {}
}
if [Level] == "INFO" {
drop {}
}
}
output {
stdout { codec => rubydebug }
if [type] == "javalog" {
redis {
host => "192.168.1.22"
port => 6379
data_type => "list"
key => "logstash"
}
}
}
添加SpringBoot配置
在pom文件中添加依赖
net.logstash.logback
logstash-logback-encoder
4.11
并在 resources中配置logback.xml的配置,添加如下内容
127.0.0.1:4560
%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
springboot整合方式只需添加pom依赖和再logback.xml做配置即可代替在服务中安装logstash,项目直接可以将日志通过
tcp协议传输到服务部署的loastash中,然后通过自定义格式和过滤规则直接写入ElasticSearch中
在/opt/springboot/elasticsearch/delete-es目录下创建es-del.sh文件
文件内容:
#!/bin/bash
# @Author: richard
# @Date: 2017-08-11 17:27:49
# @Last Modified by: richard
# @Last Modified time: 2017-08-11 18:04:58
#保留近 N 天
KEEP_DAYS=7
# 删除前 N的所有天到 前N+10天==>每天执行
function get_todelete_days()
{
# declare -A DAY_ARR
# DAY_ARR=""
for i in $(seq 1 10);
do
THIS_DAY=$(date -d "$(($KEEP_DAYS+$i)) day ago" +%Y.%m.%d)
DAY_ARR=( "${DAY_ARR[@]}" $THIS_DAY)
done
echo ${DAY_ARR[*]}
}
# 返回数组的写法
TO_DELETE_DAYS=(`get_todelete_days`)
for day in "${TO_DELETE_DAYS[@]}"
do
echo "$day will be delete"
curl -XDELETE 'http://192.168.1.89:9200/*-'${day}
done
在目录下启动定时任务执行此文件,
输入:crontab -e
30 23 * * 7 /opt/springboot/elasticsearch/delete-es/es-del.sh
然后按Esc输入 :wq 即可。
每周日晚上23:30执行一次。
定时任务执行log文件地址:/var/spool/mail/root 可查看执行错误信息。
搭建elk工作完成!