被奇幻“催更”
最近有个读者,他叫“老王“,外号“茴香豆泡酒”,找我催更 ELK 的文章。
因之前我用的是软件安装 Logstash + Filebeat 的方式:
他想知道如何用容器化部署 ELK,于是我先写了一半,因为要写其他文章所以耽搁了。没想到过了几天后,老王说他已经部署好了,还写了篇文章,恐怖如斯啊!
那可不行,我不能输给他,必须自己安排一篇。那么我写的这篇有哪些特色内容呢?
- 支持离线环境部署 ELK。
- 支持安装 ES ik 分词器。
- 支持离线安装 Logstash 多行插件。
- 生产级别 Logstash 配置。
- 生产级别 Filebeat 配置。
- Filebeat 如何做到重新同步导入。
- 一步一图,手摸手教程。
本文主要内容如下:
目录
前言
这次我们演示在单机上用 Docker 部署 ELK Stack,大家可以参照这个教程部署在集群环境中。
ELK Stack 整体的工作流程如下:
- 1、微服务写入日志到本地文件中。
- 2、Filebeat 组件监控日志文件变化,将日志收集起来。
- 3、Filebeat 把数据传给 Logstash 组件。
- 4、Logstash 具有强大的数据清洗和过滤功能,然后写入到 Elasticsearch 中。
- 5、Kibana 可视化工具从 Elasticsearch 中查询数据并展示出来。
演示环境:
- Ubuntu 18.04 虚拟机一台
- Elasticsearch、Logstash、Kibana、Filebeat、容器的版本为 7.6.2
最后启动了 5 个容器:
一、Docker 方式部署 Elasticsearch 数据库
1.1 安装 Elasticsearch
方案一:从互联网下载 Elasticsearch 镜像
1
|
docker pull elasticsearch:7.6.2
|
方案二:离线安装加载 Elasticsearch 镜像
1
|
# 从有互联网的机器上下载 Elasticsearch 镜像 sudo docker pull elasticsearch:7.6.2 # 从有互联网的机器上保存 logstash 镜像 sudo docker save -o es.tar es # 设置 logstash 镜像的权限,保证能有权限拷贝到其他机器 sudo chmod 777 es.tar # 在离线的机器上加载 logstash 镜像 sudo docker load -i es.tar
|
1.2 配置 ES
创建挂载目录
1
|
mkdir -p /data/elk/es/{config,data,logs,plugins}
|
赋予权限
1
|
sudo chown -R 1000:1000 /data/elk/es
|
创建配置文件
1
|
cd /data/elk/es/config sudo touch elasticsearch.yml -----------------------配置内容---------------------------------- cluster.name: "my-es" network.host: 0.0.0.0 http.port: 9200 http.cors.enabled: true http.cors.allow-origin: "*"
|
1.3 启动 elasticsearch 容器
1
|
docker run -it -d \ -p 9200:9200 \ -p 9300:9300 \ --name es01 \ -e ES_JAVA_OPTS="-Xms1g -Xmx1g" \ -e "discovery.type=single-node" \ --restart=always \ -v /data/elk/es/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \ -v /data/elk/es/data:/usr/share/elasticsearch/data \ -v /data/elk/es/logs:/usr/share/elasticsearch/logs \ -v /data/elk/es/plugins:/usr/share/elasticsearch/plugins \ elasticsearch:7.6.2
|
1.4 验证 elasticsearch 是否启动成功
1
|
curl http://localhost:9200
|
1.5 安装 ES 辅助工具
这个工具安装好了后,相当于启动了一个服务,这个服务是一个站点,通过在站点里面访问 ES 的 API,就可以获取到 ES 的当前信息了。
安装步骤如下:
1
|
sudo docker pull mobz/elasticsearch-head:5
|
docker run -d -p 9100 9100 mobz/elasticsearch-head:5
- 用浏览器访问 elasticsearch-head 网址
1
|
http://192.168.56.11:9100/
|
1
|
http://192.168.56.11:9200/
|
就可以看到 ES 的集群和索引信息了,这个要比在 Kibana 中用 DevTools 查看更方便。
1.6 IK 分词器
ES IK 分词器可以看悟空写的这篇: ES 终于可以搜到”悟空哥“了!
安装步骤如下:
1
|
https://github.com/medcl/elasticsearch-analysis-ik/releases
|
选择 ES 对应版本的 IK 分词器,我的 ES 版本为 7.6.2。
解压后,拷贝到 /data/elk/es/plugins/ik/ 目录。
二、Docker 方式部署 Kibana 可视化工具
2.1 安装 Kibana
获取 kibana 镜像
获取elasticsearch容器 ip
1
|
docker inspect --format '{{ .NetworkSettings.IPAddress }}' es01
|
结果:172.17.0.2
创建 kibana 配置文件
1
|
mkdir -p /data/elk/kibana/ vim /data/elk/kibana/kibana.yml
|
配置内容:
1
|
#Default Kibana configuration for docker target server.name: kibana server.host: "0" elasticsearch.hosts: ["http://172.17.0.2:9200"] xpack.monitoring.ui.container.elasticsearch.enabled: true
|
2.2 运行 kibana
1
|
docker run -it -d --restart=always \ --name kibana -p 5601:5601 -v /data/elk/kibana/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:7.6.2
|
访问 http://192.168.56.10:5601 。这个 IP 是服务器或虚拟机的 IP。Kibana 控制台的界面如下所示,打开 kibana 时,首页会提示让你选择加入一些测试数据,点击 try our sample data 按钮就可以了。
Kibana 界面上会提示你是否导入样例数据,选一个后,Kibana 会帮你自动导入,然后就可以进入到 Discover 窗口搜索日志了。
离线方式安装 Kibana 方式
1
|
sudo docker save -o kibana.tar kibana sudo chmod 777 kibana.tar sudo docker load -i kibana.tar
|
三、Docker 方式安装 Logstash
3.1 拉取 Logstash 镜像
方案一:从互联网下载镜像
1
|
sudo docker pull logstash:7.6.2
|
方案二:离线安装镜像
1
|
# 从有互联网的机器上下载 logstash 镜像 sudo docker save -o logstash.tar logstash # 设置 logstash 镜像的权限,保证能有权限拷贝到其他机器 sudo chmod 777 logstash.tar # 在离线的机器上加载 logstash 镜像 sudo docker load -i logstash.tar
|
临时方式启动,主要是为了映射整个 Logstash 目录,后面方便安装 logstash 插件
1
|
docker run -d --name=logstash logstash:7.6.2
|
将容器内的文件夹拷贝到宿主机磁盘上
1
|
sudo docker cp logstash:/usr/share/logstash /data/elk
|
添加 logstash 文件夹的权限
1
|
cd /data/elk/ sudo chmod 777 logstash -R
|
3.2 创建采集配置文件
创建 logstash.conf 采集配置文件
1
|
sudo mkdir -p /data/elk/logstash/conf.d cd /data/elk/logstash/conf.d sudo vim logstash.conf
|
配置内容如下:
1
|
input { beats { port => 5044 } } filter { grok { match => [ "message", "(?<logTime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{3})\s+\[(?<thread>.*)\]\s+(?<level>\w*)\s{1,2}+(?<class>\S*)\s+-\s+(?<content>.*)\s*"] match => [ "message", "(?<logTime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{3})\s{1,2}+(?<level>\w*)\s{1,2}+.\s---+\s\[(?<thread>.*)\]+\s(?<class>\S*)\s*:+\s(?<content>.*)\s*"] match => [ "source", "/home/passjava/logs/(?<logName>\w+)/.*.log" ] overwrite => [ "source"] break_on_match => false } mutate { convert => { "bytes" => "integer" } remove_field => ["agent","message","@version", "tags", "ecs", "_score", "input", "[log][offset]"] } useragent { source => "user_agent" target => "useragent" } date { match => ["logTime", "MMM d HH:mm:ss", "MMM dd HH:mm:ss", "ISO8601"] timezone => "Asia/Shanghai" } } output { stdout { } elasticsearch { hosts => ["192.168.56.11:9200"] index => "passjava_log" } }
|
3.3 创建 logstash 配置文件
创建 logstash.yml 配置文件
1
|
cd /data/elk/logstash/config sudo vim logstash.yml
|
配置内容如下:
1
|
# 指定管道配置的目录,在此目录下的所有管道配置文件都将被 logstash 读取,除管道配置外,不要放任何文件 path.config: /usr/share/logstash/conf.d/*.conf # logstash 日志目录位置,默认为 logstash 路径下的 logs path.logs: /var/log/logstash http.host: "0.0.0.0" xpack.monitoring.elasticsearch.hosts: [ "http://192.168.56.11:9200" ]
|
3.4 启动 logstash 容器
1
|
# 删除 logstash 容器 docker rm -f logstash # 启动 logstash 容器 docker run -it -d \ -p 5044:5044 \ --name logstash \ --restart=always \ -v /data/elk/logstash:/usr/share/logstash \ logstash:7.6.2
|
查看日志
3.5 安装 multiline 插件
还有一个坑的地方是错误日志一般都是很多行的,会把堆栈信息打印出来,当经过 logstash 解析后,每一行都会当做一条记录存放到 ES,那这种情况肯定是需要处理的。这里就需要使用 multiline 插件,对属于同一个条日志的记录进行拼接。
3.5.1 安装 multiline 插件
multiline 不是 logstash 自带的,需要单独进行安装。我们的环境是没有外网的,所以需要进行离线安装。
介绍在线和离线安装 multiline 的方式:
在 logstash 根目录执行以下命令进行安装。
1
|
bin/logstash-plugin install logstash-filter-multiline
|
在有网的机器上在线安装插件,然后打包。
1
|
bin/logstash-plugin install logstash-filter-multiline bin/logstash-plugin prepare-offline-pack logstash-filter-multiline
|
拷贝到服务器,/data/elk/logstash/mutiline
进入到容器中
1
|
docker exec -it logstash /bin/bash
|
执行安装命令
1
|
cd /usr/share/logstash bin/logstash-plugin install file:///usr/share/logstash/mutiline/logstash-offline-plugins-7.6.2.zip
|
安装插件需要等待 2 分钟左右的时间,控制台界面会被 hang 住,当出现 Install successful
表示安装成功。
检查下插件是否安装成功,可以执行以下命令查看插件列表。当出现 multiline 插件时则表示安装成功。
3.5.2 添加 mutiline 配置
编辑 logstash.conf 配置文件
1
|
cd /data/elk/logstash/conf.d/ sudo vim logstash.conf
|
filter 节点下添加 mutiline 配置。
1
|
input { beats { port => 5044 } } filter { multiline { pattern => "^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}.\d{3}" negate => true what => "previous" } grok { match => [ "message", "(?<logTime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{3})\s+\[(?<thread>.*)\]\s+(?<level>\w*)\s{1,2}+(?<class>\S*)\s+-\s+(?<content>.*)\s*"] match => [ "message", "(?<logTime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}.\d{3})\s{1,2}+(?<level>\w*)\s{1,2}+.\s---+\s\[(?<thread>.*)\]+\s(?<class>\S*)\s*:+\s(?<content>.*)\s*"] match => [ "source", "/home/passjava/logs/(?<logName>\w+)/.*.log" ] overwrite => [ "source"] break_on_match => false } mutate { convert => { "bytes" => "integer" } remove_field => ["agent","message","@version", "tags", "ecs", "_score", "input", "[log][offset]"] } useragent { source => "user_agent" target => "useragent" } date { match => ["logTime", "MMM d HH:mm:ss", "MMM dd HH:mm:ss", "ISO8601"] timezone => "Asia/Shanghai" } } output { stdout { } elasticsearch { hosts => ["192.168.56.11:9200"] index => "passjava_log" } }
|
关于 Logstash 如何配置的内容,请查看这篇:
深入理解 ELK 中 Logstash 的底层原理 + 填坑指南
3.5.4 重新启动 logstash 容器
四、Docker 方式安装 Filebeat
4.1 拉取 filebeat 镜像
1
|
docker pull elastic/filebeat:7.6.2
|
临时方式启动,主要是为了映射整个 filebeat 目录,后面可以修改同步进度以及查看日志文件。
1
|
docker run -d --name=filebeat elastic/filebeat:7.6.2
|
将容器内的文件夹拷贝到宿主机磁盘上
1
|
docker cp filebeat:/usr/share/filebeat /data/elk
|
创建日志目录作为测试
1
|
sudo mkdir -p /data/passjava/logs
|
4.2 配置 filebeat
创建日志目录作为测试
1
|
sudo mkdir -p /data/passjava/logs
|
创建 filebeat 配置文件
1
|
vim /data/elk/filebeat/filebeat.yml
|
配置内容如下:
1
|
filebeat.inputs: - type: log enabled: true paths: - /usr/share/filebeat/passjava/logs/*/info*.log - /usr/share/filebeat/passjava/logs/*/warn*.log - /usr/share/filebeat/passjava/logs/*/error*.log fields: log_catagory: service fields_under_root: true multiline.type: pattern multiline.pattern: '^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}.\d{3}' multiline.negate: true multiline.match: after multiline.max_lines: 52 output.logstash: hosts: ["192.168.56.11:5044"]
|
这里配置的 paths 日志文件路径用来映射到宿主机上的日志文件。
1
|
paths: - /usr/share/filebeat/logbeat/*.log
|
设置权限
1
|
sudo chmod 777 -R /data/elk/filebeat sudo chmod go-w /data/elk/filebeat/filebeat.yml
|
启动 filebeat
1
|
# 删除 filebeat 容器 docker rm -f filebeat # 启动 filebeat 容器 docker run -d \ --name=filebeat \ --restart=always \ -v /data/passjava/logs:/usr/share/filebeat/passjava/logs/ \ -v /data/elk/filebeat:/usr/share/filebeat \ elastic/filebeat:7.6.2
|
查看启动日志
4.3 Filebeat 重新同步日志文件
当我们想要完全重新同步日志文件时,可以将 Filebeat 这个文件夹删掉:
1
|
/data/elk/filebeat/data/registry/filebeat
|
这个目录下的 data.json 文件会记录同步的进度,删掉后,重启 Filebeat 后就会重新开始同步。
五、测试日志文件写入 ES
5.1 创建日志文件
1
|
sudo vim /data/passjava/logs/wukong/error.log
|
模拟后端输出的日志:
5.2 观察 logstash 容器中的日志
可以看到 logstash 收集到了 filebeat 传输的日志。
5.3 观察 Filebeat 容器中的日志
可以看到 Filebeat 采集日志文件,并同步到 Logstash 的日志。
5.4 创建 ES 索引
当 Logstash 将日志同步到 Elasticsearch 中后,就会自动在 Elasticsearch 中创建索引。然后我们需要在 Kibana 可视化控制台中创建一个对应的索引来查看日志。步骤如下所示:
5.5 查询日志
在 Kibana 搜索 大楼
关键字,可以查到日志输出。需要注意的是,要选择对应的过滤时间段。
六、报错问题排查
Filebeat 出现报错,但是过一会 Filebeat 和 Logstash 又成功建立了连接,而且日志也输出到了 Logstash 了。暂时未找到原因。
1
|
Failed to publish events caused by: EOF
|