2

被一位读者赶超,手摸手 Docker 部署 ELK Stack - 悟空聊架构

 2 years ago
source link: https://www.cnblogs.com/jackson0714/p/docker_elk.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

被一位读者赶超,容器化部署 ELK Stack

你好,我是悟空。

被奇幻“催更”

最近有个读者,他叫“老王“,外号“茴香豆泡酒”,找我崔更 ELK 的文章。

因之前我用的是软件安装 Logstash + Filebeat 的方式:

7000 字 | 20 图 | 一文带你搭建一套 ELK Stack 日志平台

他想知道如何用容器化部署 ELK,于是我先写了一半,因为要写其他文章所以耽搁了。没想到过了几天后,老王说他已经部署好了,还写了篇文章,恐怖如斯啊!

那可不行,我不能输给他,必须自己安排一篇。那么我写的这篇有哪些特色内容呢?

  • 支持离线环境部署 ELK。
  • 支持离线安装 Logstash 多行插件。
  • 生产级别 Logstash 配置。
  • 生产级别 Filebeat 配置。
  • Filebeat 如何做到重新同步导入。
  • 一步一图,手摸手教程了。

本文主要内容如下:

目录

这次我们演示在单机上用 Docker 部署 ELK Stack,大家可以参照这个教程部署在集群环境中。

ELK Stack 整体的工作流程如下:

4f874434b6b3350fb0b0a2131a5e2b40.png

流程如下:

  • 1、微服务写入日志到本地文件中。
  • 2、Filebeat 组件监控日志文件变化,将日志收集起来。
  • 3、Filebeat 把数据传给 Logstash 组件。
  • 4、Logstash 具有强大的数据清洗和过滤功能,然后写入到 Elasticsearch 中。
  • 5、Kibana 可视化工具从 Elasticsearch 中查询数据并展示出来。

演示环境:

  • Ubuntu 18.04 虚拟机一台
  • Elasticsearch、Logstash、Kibana、Filebeat、容器的版本为 7.6.2

最后启动了 5 个容器:

ea5590ff340dab28d6ab810ca0172bf2.png

一、Docker 方式部署 Elasticsearch 数据库

1.1 安装 Elasticsearch

方案一:从互联网下载 Elasticsearch 镜像

docker pull elasticsearch:7.6.2

方案二:离线安装加载 Elasticsearch 镜像

# 从有互联网的机器上下载 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

43b4fbed83d80b12ac3447cdaa68d4e2.png

1.2 配置 ES

创建挂载目录

mkdir -p /data/elk/es/{config,data,logs,plugins}
636821e49d8998eb06ad854efff1276d.png
sudo chown -R 1000:1000 /data/elk/es

创建配置文件

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 容器

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

e7956cd36bb9237269bc0765e5d719b3.png

1.4 验证 elasticsearch 是否启动成功

curl http://localhost:9200
2f18adbf6093507e0a4a34d754d56fd0.png

1.5 安装 ES 辅助工具

这个工具安装好了后,相当于启动了一个服务,这个服务是一个站点,通过在站点里面访问 ES 的 API,就可以获取到 ES 的当前信息了。

安装步骤如下:

  • 下载 elasticsearch-head 镜像
sudo docker pull mobz/elasticsearch-head:5

  • 运行 elasticsearch-head 容器

docker run -d -p 9100 9100 mobz/elasticsearch-head:5

  • 用浏览器访问 elasticsearch-head 网址
http://192.168.56.11:9100/
  • 修改网站中的 ES 的连接地址
http://192.168.56.11:9200/
b173e54a67ec7f912d1d64df44552743.png

就可以看到 ES 的集群和索引信息了,这个要比在 Kibana 中用 DevTools 查看更方便。

1.6 IK 分词器

https://github.com/medcl/elasticsearch-analysis-ik/releases

选择 ES 对应版本的 IK 分词器,我的 ES 版本为 7.6.2。

a5fa22f1da3b8c3698e2882721d70f8e.png

解压后,拷贝到 /data/elk/es/plugins/ik/ 目录

18cd265cb528f346e771424c348314c3.png

二、Docker 方式部署 Kibana 可视化工具

2.1 安装 Kibana

获取 kibana 镜像

docker pull kibana:7.7.1

获取elasticsearch容器 ip

docker inspect --format '{{ .NetworkSettings.IPAddress }}' es01

结果:172.17.0.2

创建 kibana 配置文件

mkdir -p /data/elk/kibana/
vim /data/elk/kibana/kibana.yml

配置内容:

#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

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 按钮就可以了。

9a04cf5f696a14f045b078dc632d3811.png

Kibana 界面上会提示你是否导入样例数据,选一个后,Kibana 会帮你自动导入,然后就可以进入到 Discover 窗口搜索日志了。

8ebd69727dc31f8dc4e8409d64609a41.png

离线方式安装 Kibana 方式

sudo docker save -o kibana.tar kibana
sudo chmod 777 kibana.tar
sudo docker load -i kibana.tar
1f85dbb2154c24ba8b1931f22ff3d655.png

三、Docker 方式安装 Logstash

3.1 拉取 Logstash 镜像

方案一:从互联网下载镜像

sudo docker pull logstash:7.6.2

方案二:离线安装镜像

# 从有互联网的机器上下载 logstash 镜像
sudo docker save -o logstash.tar logstash
# 设置 logstash 镜像的权限,保证能有权限拷贝到其他机器
sudo chmod 777 logstash.tar
# 在离线的机器上加载 logstash 镜像
sudo docker load -i logstash.tar

临时方式启动,主要是为了映射整个 Logstash 目录,后面方便安装 logstash 插件

docker run -d --name=logstash logstash:7.6.2

将容器内的文件夹拷贝到宿主机磁盘上

sudo docker cp logstash:/usr/share/logstash /data/elk
b5684a258fe5c92558a279680f29c3e2.png

添加 logstash 文件夹的权限

cd /data/elk/
sudo chmod 777 logstash -R

3.2 创建采集配置文件

创建 logstash.conf 采集配置文件

sudo mkdir -p /data/elk/logstash/conf.d
cd /data/elk/logstash/conf.d
sudo vim logstash.conf

配置内容如下:

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 配置文件

cd /data/elk/logstash/config
sudo vim logstash.yml

配置内容如下:

# 指定管道配置的目录,在此目录下的所有管道配置文件都将被 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 容器

# 删除 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

ca2dc172c34b5a9012aa182818c4ab85.png

935957bcec1da69e396b51d13ea206da.png

3.5 安装 multiline 插件

还有一个坑的地方是错误日志一般都是很多行的,会把堆栈信息打印出来,当经过 logstash 解析后,每一行都会当做一条记录存放到 ES,那这种情况肯定是需要处理的。这里就需要使用 multiline 插件,对属于同一个条日志的记录进行拼接。

3.5.1 安装 multiline 插件

multiline 不是 logstash 自带的,需要单独进行安装。我们的环境是没有外网的,所以需要进行离线安装。

介绍在线和离线安装 multiline 的方式:

  • 在线安装插件。

在 logstash 根目录执行以下命令进行安装。

bin/logstash-plugin install logstash-filter-multiline

b5945d436c3763c8630677c9acfa7ee5.png

  • 离线安装插件。

在有网的机器上在线安装插件,然后打包。

bin/logstash-plugin install logstash-filter-multiline
bin/logstash-plugin prepare-offline-pack logstash-filter-multiline

拷贝到服务器,/data/elk/logstash/mutiline

1645140ae898ca371fcbec719b6f2ef6.png

进入到容器中

docker exec -it logstash /bin/bash

执行安装命令

cd /usr/share/logstash
bin/logstash-plugin install file:///usr/share/logstash/mutiline/logstash-offline-plugins-7.6.2.zip

安装插件需要等待 2 分钟左右的时间,控制台界面会被 hang 住,当出现 Install successful 表示安装成功。

c4ac920e85b54ecddfff2204000211a0.png

检查下插件是否安装成功,可以执行以下命令查看插件列表。当出现 multiline 插件时则表示安装成功。

bin/logstash-plugin list
multiline 插件

3.5.2 添加 mutiline 配置

编辑 logstash.conf 配置文件

cd /data/elk/logstash/conf.d/
sudo vim logstash.conf

filter 节点下添加 mutiline 配置。

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 restart logstash

四、Docker 方式安装 Filebeat

4.1 拉取 filebeat 镜像

docker pull elastic/filebeat:7.6.2
a51b3b196657ec393dbfa8e74e705c55.png

临时方式启动,主要是为了映射整个 filebeat 目录,后面可以修改同步进度以及查看日志文件。

docker run -d --name=filebeat elastic/filebeat:7.6.2

将容器内的文件夹拷贝到宿主机磁盘上

docker cp filebeat:/usr/share/filebeat /data/elk
5a726417855b2afbcbade7d76c1cb8f0.png

创建日志目录作为测试

sudo mkdir -p /data/passjava/logs

4.2 配置 filebeat

创建日志目录作为测试

sudo mkdir -p /data/passjava/logs

创建 filebeat 配置文件

vim /data/elk/filebeat/filebeat.yml

配置内容如下:

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 日志文件路径用来映射宿主机上的日志文件。

paths:
    - /usr/share/filebeat/logbeat/*.log
sudo chmod 777 -R /data/elk/filebeat
sudo chmod go-w /data/elk/filebeat/filebeat.yml

d04902d6bd07f4ec28e15a4af24e5810.png

启动 filebeat

# 删除 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

查看启动日志

docker logs -f filebeat
de4e5c8e2a1ee7d70ce60261e62b0a54.png

4.3 Filebeat 重新同步日志文件

当我们想要完全重新同步日志文件时,可以将 Filebeat 这个文件夹删掉:

/data/elk/filebeat/data/registry/filebeat

这个目录下的 data.json 文件会记录同步的进度,删掉后,重启 Filebeat 后就会重新开始同步。

五、测试日志文件写入 ES

5.1 创建日志文件

sudo vim /data/passjava/logs/wukong/error.log

模拟后端输出的日志:

模拟后端输出日志

5.2 观察 logstash 容器中的日志

docker logs logstash

可以看到 logstash 收集到了 filebeat 传输的日志。

ecd11d8b8590efe2bb64ad461ec6f200.png

5.3 观察 Filebeat 容器中的日志

docker logs filebat

可以看到 Filebeat 采集日志文件,并同步到 Logstash 的日志。

80445f9eeef45b030b3727f2c8f8fd19.png

5.4 创建 ES 索引

当 Logstash 将日志同步到 Elasticsearch 中后,就会自动在 Elasticsearch 中创建索引。然后我们需要在 Kibana 可视化控制台中创建一个对应的索引来查看日志。步骤如下所示:

  • 打开 Kibana 控制台
286be6b73bbfbaac210e688318a39f2f.png
  • 创建 passjava_log 索引
8bae0e2caef925855b019980aee1ec77.png

5.5 查询日志

在 Kibana 搜索大楼 关键字,可以查到日志输出。需要注意的是,要选择对应的过滤时间段。

f0b2f852150f488c9c89236ad1adb538.png

六、报错问题排查

Filebeat 出现报错,但是过一会 Filebeat 和 Logstash 又成功建立了连接,而且日志也输出到了 Logstash 了。暂时未找到原因。

 Failed to publish events caused by: EOF

1a54f77374d3fc6b45ef82656f7e97d0.png



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK