一、背景及环境准备:
1、背景:
线上服务是SpringBoot服务,随着业务发展,产生的日志越来越多,排查越来越不方便。且如果跨服务调用,出现错误排查起来要花费大量时间,即使有trace_id也不是很方便。所以日志服务应运而生。
2、环境准备:
目前有项目服务器(project-server),就是跑着线上服务的服务器。日志服务器(log-server),用来搭建elk日志服务。在项目服务器上安装filebeat,用来采集日志数据,主要是两个日志文件:app-info.log和app-error.log文件。在日志服务器上安装logstash+elasticsearch+kibana,其中logstash负责过滤日志格式,elasticsearch负责存储和查找日志,kibana负责可视化操作日志。安装版本选择8.4.1版本。由于日志服务器上很干净,没有安装JDK,所以elasticsearch和logstash依赖的JDK直接使用它们自带的就可以。
3、整体架构图:
二、环境安装与配置:
1、下载安装包:
目前官网最新的稳定发布版本是8.4.1
2、上传安装包到服务器:
上传至/usr/local/elk并创建一个新用户senior,将安装包解压后重命名后将解压后的文件夹赋予senior用户,elk组件需以非root用户运行。如图:(由于本来就有一个非root的用户senior,且属于root组,所以不需要创建,也可以使用)
解压重命名命令(以logstash为例):
tar -zxvf logstash-8.4.1-linux-x86_64.tar.gz ./
mv logstash-8.4.1-linux-x86_64 ./logstash-8.4.1
更改文件所有者命令:以logstash为例
sudo chown -R senior logstash-8.4.1
-R代表递归文件夹,表示该文件夹下内容都归指定用户所有。
3、调整配置:
需要先修改elasticsearch、再修改logstash、filebeat、kibana的配置,然后进行启动。为什么先搞elasticsearch,因为elasticsearch是核心,它正常启动,可以避免好多问题。
3.1、修改elasticsearch配置并启动:
进入elasticsearch安装目录,进入config文件夹下,编辑jvm.options和elasticsearch.yml两个文件,前者是因为elasticsearch依赖了JDK,所以需要配一些基本参数,看个人机器的配置进行调整,目前日志服务器作为测试版,它的配置是2核4G+40G磁盘。
3.1.1、修改虚拟内存:
具体就是不修改启动会报错虚拟内存不足的错,因为单个进程默认的虚拟内存就是65530KB,这对于es来说不够:
ERROR: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]**
修改:
sudo vim /etc/sysctl.conf
在配置文件末尾添加:
vm.max_map_count=262144
保存退出后刷新:
sudo sysctl -p
3.1.2、编辑jvm.options:
两个参数,将jvm需要的最大内存和最小内存设置为一样大小,可以让jvm一开始就申请足够的内存,防止因为内存不足而不停申请内存,影响速度。
-Xms1g
-Xmx1g
3.1.3、编辑elasticsearch.yml:
# 集群名称(单节点也要配)
cluster.name: sn-pub-elasticsearch
# 节点名称(单节点也要配)
node.name: sn-node-1
# 允许外部访问
network.host: 0.0.0.0
# es的端口
http.port: 9200
# 集群主节点
cluster.initial_master_nodes: ["sn-node-1"]
# 配置不开启安全认证,不开启账号密码登录
xpack.security.enabled: false
3.1.4、启动:
后台启动: 进入到elasticsearch的bin目录下
./elasticsearch -d
查看进程
ps -ef | grep elasticsearch
至此,一个es其实已经启动了。想要需要登录才能查看索引的es,那么接着配置。
编辑elasticsearch.yml添加用户认证,也就是账号密码登录
xpack.security.enabled: true
xpack.security.http.ssl:
enabled: false
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
使用kill -9 pid杀死elasticsearch进程后再次后台启动,启动完成后,修改密码(不需要用户认证的可跳过),修改elastic用户和kibana的密码,默认elastic是管理员权限。
使用如下命令按提示操作即可(以elastic用户为例,对kibana用户操作也是一样的):
./elasticsearch-reset-password -u elastic -i
上面的是单个配置 下面是挨个为elasticsearch拥有的用户配置密码:
在elasticsearch的bin目录下执行
./elasticsearch-setup-passwords interactive
遇到如图提示:输入y
然后按照提示输入自己想要的密码即可,密码会有二次确认。
3.2、修改logstash的配置并启动:
进入logstash的安装目录,进入config文件夹下,创建conf.d文件夹,进入conf.d文件夹,创建文件logstash.conf。
3.2.1、编辑logstash.conf文件
# 采集:
input {
beats {
host => "0.0.0.0"
# logstash监听的端口,filebeat会将数据从此端口发送进来
port => 5044
}
}
# 过滤:
filter {
# filebeat采集日志时会打标签,
if "sn-nb-test-api-info" in [tags]{
# 过滤日志信息,从日志中解析出需要的字段
grok {
match => {
"message" => "\[%{TIMESTAMP_ISO8601:time}\]\[%{DATA:trace_id}\]\[%{DATA:thread_name}\]\[%{LOGLEVEL:level}\]\[%{JAVACLASS:class}\]\[%{INT:line_no}\]%{GREEDYDATA:msg}"
}
}
# 处理日志生成的时间,日志产生的时间是北京时间,减去8小时,先处理成utc时间
date {
match => ["time","yyyy-MM-dd HH:mm:ss.SSS"]
target => "@timestamp"
timezone => "Etc/GMT-8"
}
# es会搜集许多组件的信息,这里将它们删除掉,否则到时候发送kibana太多多余的字段
mutate {
remove_field => ["@version","message","host","agent","ecs","cloud","input","log","event","time"]
}
}
if "sn-nb-test-api-error" in [tags]{
grok {
match => {
"message" => "\[%{TIMESTAMP_ISO8601:time}\]\[%{DATA:trace_id}\]\[%{DATA:thread_name}\]\[%{LOGLEVEL:level}\]\[%{JAVACLASS:class}\]\[%{INT:line_no}\]%{GREEDYDATA:msg}"
}
}
date {
match => ["time","yyyy-MM-dd HH:mm:ss.SSS"]
target => "@timestamp"
timezone => "Etc/GMT-8"
}
mutate {
remove_field => ["@version","message","host","agent","ecs","cloud","input","log","event","time"]
}
}
}
# 输出:
output {
if "sn-nb-test-api-info" in [tags]{
elasticsearch {
hosts => ["x.x.x.x:9200"]
# elasticsearch按索引文档进行数据存储,所以这里将每天的日志建立索引存储
index => "sn-nb-test-api-info-%{+yyyy-MM-dd}"
user => "elastic"
password => "******"
}
}
if "sn-nb-test-api-error" in [tags]{
elasticsearch {
hosts => ["x.x.x.x:9200"]
index => "sn-nb-test-api-error-%{+yyyy-MM-dd}"
user => "elastic"
password => "******"
}
}
}
将输出部分的x.x.x.x替换成elasticsearch所在服务器的ip即可,密码就是自己设置的密码。elasticsearch没有设置用户认证也就不用user和password了。 grok为什么要这么处理,这和filebeat采集到的日志格式有关,springboot服务产生的日志格式是这样的:
[2022-09-13 00:01:04.504][][Thread-41][INFO][com.senior.cloud.system.schedule.VehicleEatSchedule][41]每天1:01生成作业效率报表数据:timeStr:20220912
每一对[ ]之间都是固定的日志格式,是springboot服务里logback.xml里设置的。 后面安装了kibana,可以通过kibana里的dev Tools对日志进行grok调试,效果如图:
3.2.2、编辑config目录下jvm.options:
logstash运行也是依赖JVM,不多赘述,目前配置如下:
-Xms512m
-Xmx512m
3.2.3、编辑config目录下的logstash.yml:
在行末添加
path.config: /usr/local/elk/logstash-8.4.1/config/conf.d
path.logs: /usr/local/elk/logstash-8.4.1/logs
3.2.4、启动:
进入到logstash安装的bin目录下,执行(后台运行):
nohup ./logstash > ../logs/logstash.log &
3.3、修改kibana配置并启动:
使用命令cd /opt进入opt目录下,使用命令sudo mkdir kibana创建kibana目录,然后使用 sudo chown -R senior kibana/更改kibana目录所有者为senior
进入kibana安装目录,进入config目录下
3.3.1、编辑kibana.yml:
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://x.x.x.x:9200"]
elasticsearch.username: "kibana"
elasticsearch.password: "*****"
i18n.locale: "zh-CN"
logging.appenders.default:
type: file
fileName: /opt/kibana/logs/kibana.log
layout:
type: json
其它配置注释掉,是关于安全认证的。同理x.x.x.x替换成elasticsearch所在的服务器ip,密码就是自己设置的那个。
3.3.2、启动:
nohup ./kibana &
由于kibana是node.js编写的,所以查看kibana进程号需要这样:
sudo netstat -tunlp|grep 5601
查看启动日志:
tail -f /opt/kibana/logs/kibana.log
3.4、修改filebeat配置并启动:
filebeat安装在需要采集日志的服务器上,上传解压不再赘述,这个使用root账号测试也是可以启动的。
3.4.1、编辑filebeat.yml:
# ============================== Filebeat inputs ===============================
filebeat.inputs:
# Each - is an input. Most options can be set at the input level, so
# you can use different inputs for various configurations.
# Below are the input specific configurations.
# filestream is an input for collecting log messages from files.
# 新版推荐使用filestream代理log
- type: filestream
# Unique ID among all inputs, an ID is required.
# id是必须的,名字随意
id: sn-api-info-test
# 这块采集的是info信息,所以tag标记就取名叫这个
tags: ["sn-nb-test-api-info"]
# Change to true to enable this input configuration.
enabled: true
#encoding
encoding: utf-8
# Paths that should be crawled and fetched. Glob based paths.
# linux上服务产生的日志的绝对路径
paths:
- /home/senior/app/logs/app-info.log
#- c:\programdata\elasticsearch\logs\*
#multiline
# 配置多行解析,为了将error日志里的堆栈信息放在一行显示,否则会很恶心
# 表示将匹配到不以[开头的行追加到以[开头的行之后构成一行
parsers:
- multiline:
type: pattern
pattern: '^\['
negate: true
match: after
- type: filestream
# Unique ID among all inputs, an ID is required.
id: sn-api-error-test
tags: ["sn-nb-test-api-error"]
# Change to true to enable this input configuration.
enabled: true
#encoding
encoding: utf-8
# Paths that should be crawled and fetched. Glob based paths.
paths:
- /home/senior/app/logs/app-error.log
#- c:\programdata\elasticsearch\logs\*
#multiline
parsers:
- multiline:
type: pattern
pattern: '^\['
negate: true
match: after
# ============================== Filebeat modules ==============================
filebeat.config.modules:
# Glob pattern for configuration loading
path: ${path.config}/modules.d/*.yml
# Set to true to enable config reloading
reload.enabled: false
# Period on which files under path should be checked for changes
#reload.period: 10s
# ======================= Elasticsearch template setting =======================
setup.template.settings:
index.number_of_shards: 1
#index.codec: best_compression
#_source.enabled: false
output.logstash:
# The Logstash hosts
hosts: ["x.x.x.x:5044"]
# ================================= Processors =================================
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~
3.4.2、启动:
nohup ./filebeat -e -c filebeat.yml > filebeat.log &
3.4.3、访问界面:
x.x.x.x:5601。访问kibana,有密码需要使用elastic账号密码,然后对时间进行设置:
4、最终效果:
4.1、需要登录,使用elastic账号密码
否则使用kibana账号会这样:
4.2、登录成功,配置好discover中的data view就可以了
4.3、优化kibana显示
如果不想每次都得在data view选择field作为右侧展示的列,可以做一个默认设置,在kibana设置里配置:
以后打开默认就会变成这样: