前言
我们在项目中排查错误第一时间会去查看日志,日志可以说在开发中起到了很重要的作用。目前很多项目使用的日志收集系统也主要以ELK和EFK这两种为主(EFK中F为Filebeat,和Logstash相比占用资源更少,并且侵入性低,下次有机会也写一篇。又给自己挖了一个坑)。这次还是以ELK为主,来教大家从0来搭一套ELK的日志收集系统。同样,本次我们也使用Docker来完成
ELK是什么?
ELK是由三个开源的中间件组成。是一套分布式日志收集解决方案。其中E指的是Elasticsearch,一个NoSQL数据库,也是我们常用的搜索引擎,主要负责存储日志,L指的是Logstash,主要职责是收集日志,过滤日志,结构格式化,然后将处理好的日志发送到es。 K则是kibana,主要提供一个可视化界面,然后操作es,来帮助我们完成查询操作。
构建网络
首先我们需要创建一个网络,来使这三个容器之间可以互相访问,完成通信。
我们在docker中使用下面这个命令来完成网络的创建
1 2 3 4
| # 创建一个名为mynetwork的网络,指定ip地址为172.19.x.x docker network create --subnet=172.19.0.0/16 mynetwork # 查看docker现有网络 docker network ls
|
Elasticsearch
首先我们创建es的工作目录,这里我放在用户目录下。es目录中有三个文件夹,data(保存es的数据)、plugins(存放插件)、config(es的配置文件)
进入config目录,编辑es的配置文件elasticsearch.yml,其中,host是允许连接的ip,设置为0.0.0.0表示任何人都可以连接,cors是跨域,我们这里放行所有域名
1 2 3
| http.host: 0.0.0.0 http.cors.enabled: true http.cors.allow-origin: "*"
|
继续完成es的安装脚本,这里可能有的同学会有疑问,为什么要放行2个端口号。因为9200是http协议,用于外部通讯。而9300是tcp协议,一般用来完成集群内节点通信,用于内部通信。
-e 设置es使用单机模式,同时设定jvm大小,不然es占用内存太大
–network 指定网络 –ip 分配给一个固定ip,不然以后重启ip都会变
-v 挂载文件,将我们刚刚配置的文件和data目录以及插件目录都挂载到容器内
1 2 3 4 5 6 7 8 9 10
| docker run --name elasticsearch \ --restart=always \ -p 9200:9200 -p 9300:9300 \ -e "discovery.type=single-node" \ --network sora33network --ip 172.19.0.4 \ -e ES_JAVA_OPTS="-Xms84m -Xmx256m" \ -v /Users/sora33/docker/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /Users/sora33/docker/elasticsearch/data:/usr/share/elasticsearch/data \ -v /Users/sora33/docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins \ -d elasticsearch:7.17.0
|
之后给我们的脚本复制可执行权限并执行。可以使用docker ps来查看正在运行的容器。这里我安装了docker的桌面版可以直接查看
网页上访问ip:9200查看es,可以看到es的各种信息,到此es安装完成
Logstash
同样创建Logstash的工作目录,也是config,data,logs。data中的文件不用管,因为我这个是运行过的,所以把容器内的文件就挂载出来了。
logstash.conf内容如下
input模块是设置logstash的端口以及数据格式,这里我们设置为json
filter是过滤器,我们在这里把时间格式改了一下,因为默认是格林尼治时间,我们需要加上8小时
output则是输出的地方,我们在这里设置es对应的地址以及索引名格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| input { tcp { port => 5043 codec => json_lines } } filter { ruby { code => "event.set('timestamp', event.get('@timestamp').time.localtime+8*60*60)" } ruby { code => "event.set('@timestamp',event.get('timestamp'))" } mutate { remove_field => ["timestamp"] } } output { elasticsearch { hosts => ["172.19.0.4:9200"] index => "logstash-%{[server_name]}-%{+YYYY.MM.dd}" } stdout { codec => rubydebug } }
|
然后是安装脚本,这里也和es一样,挂载目录,给一个固定的ip,之后给权限执行就可以
1 2 3 4 5 6 7 8 9 10 11
| docker run -d \ --network sora33network \ --privileged=true \ --ip=172.19.0.6 \ -p 5043:5043 \ -v /Users/sora33/docker/logstash/config/logstash.conf:/usr/share/logstash/pipeline/logstash.conf \ -v /Users/sora33/docker/logstash/data:/usr/share/logstash/data \ -v /Users/sora33/docker/logstash/logs:/usr/share/logstash/logs \ --restart=always \ --name logstash \ logstash:7.17.9
|
Kibana
最后到可视化工具,创建Kibana的目录如下,同样创建config和data两个文件夹,data数据依旧是容器内部的,直接忽略掉
kibana的配置文件如下,这里我们需要关心的配置的有
server.host:主机地址,这里我已经改好了,开放所有连接
server.port:kibana的端口号,默认5601
server.name:kibana服务名
elasticsearch.hosts:这里必须得改成你自己的es地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| # 主机地址,可以是ip,主机名 server.host: 0.0.0.0 # 提供服务的端口,监听端口 server.port: 5601 # 该 kibana 服务的名称,默认 your-hostname server.name: "Sora33-kibana" server.shutdownTimeout: "5s"
# # kibana访问es服务器的URL,就可以有多个,以逗号","隔开 elasticsearch.hosts: [ "http://172.19.0.4:9200" ] monitoring.ui.container.elasticsearch.enabled: true
#
# kibana日志文件存储路径,默认stdout logging.dest: stdout
# 此值为true时,禁止所有日志记录输出 # 默认false logging.silent: false
# 此值为true时,禁止除错误消息之外的所有日志记录输出 # 默认false logging.quiet: false
# 此值为true时,记录所有事件,包括系统使用信息和所有请求 # 默认false logging.verbose: false
#
# 系统和进程取样间隔,单位ms,最小值100ms # 默认5000ms ops.interval: 5000 # kibana web语言 # 默认en i18n.locale: "zh-CN"
|
安装脚本,执行安装
1 2 3 4 5 6 7 8 9
| docker run -d \ --name kibana \ --network sora33network --ip 172.19.0.5 \ --restart=always \ -p 5601:5601 \ -e TZ="Asia/Shanghai" \ -v /Users/sora33/docker/kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml \ -v /Users/sora33/docker/kibana/data:/usr/share/kibana/data \ kibana:7.17.0
|
在浏览器地址输入 ip:5601进去kibana主页
项目引入ELK
现在我们已经凑齐了三大组建,开始引入到项目中。创建一个SpringBoot的项目,引入依赖
1 2 3 4 5
| <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.3</version> </dependency>
|
在项目resources中创建文件,文件名必须为logback-spring.xml
,可以参考我设置的格式。主要看logstash的部分,destination
标签改成ip:端口。customFields这里我们把值改成我们的服务名,这里和我们logstash配置文件中的server_name对应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder charset="UTF-8"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%5p) %magenta(${PID}) [%16.16t] %cyan(%-40.40logger{39}): %msg%n"</pattern> </encoder> </appender>
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>127.0.0.1:5043</destination> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> <inculdeCallerData>false</inculdeCallerData> <timeZone>UTC</timeZone> <customFields>{"server_name":"testName"}</customFields> </encoder> </appender>
<root level="INFO"> <appender-ref ref="logstash"/> <appender-ref ref="CONSOLE"/> </root> </configuration>
|
启动项目,然后去kibana的堆栈监测中查看logstash的状态,第一次进去的话需要安装
可以看到logstash的状态已经启动了,并且收集了近200条日志
在开发工具中可以使用命令查看详情
那么到这里,我们的ELK就正式搭建完成了