被一位讀者趕超,手摸手 Docker 部署 ELK Stack

2022-08-31 21:01:00

被一位讀者趕超,容器化部署 ELK Stack

你好,我是悟空。

被奇幻「催更」

最近有個讀者,他叫「老王「,外號「茴香豆泡酒」,找我崔更 ELK 的文章。

因之前我用的是軟體安裝 Logstash + Filebeat 的方式:

7000 字 | 20 圖 | 一文帶你搭建一套 ELK Stack 紀錄檔平臺

他想知道如何用容器化部署 ELK,於是我先寫了一半,因為要寫其他文章所以耽擱了。沒想到過了幾天後,老王說他已經部署好了,還寫了篇文章,恐怖如斯啊!

那可不行,我不能輸給他,必須自己安排一篇。那麼我寫的這篇有哪些特色內容呢?

  • 支援離線環境部署 ELK。
  • 支援離線安裝 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 映象

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

1.2 設定 ES

建立掛載目錄

mkdir -p /data/elk/es/{config,data,logs,plugins}

賦予許可權

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

1.4 驗證 elasticsearch 是否啟動成功

curl http://localhost:9200

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/

就可以看到 ES 的叢集和索引資訊了,這個要比在 Kibana 中用 DevTools 檢視更方便。

1.6 IK 分詞器

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 映象

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

Kibana 介面上會提示你是否匯入樣例資料,選一個後,Kibana 會幫你自動匯入,然後就可以進入到 Discover 視窗搜尋紀錄檔了。

離線方式安裝 Kibana 方式

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

三、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

新增 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

檢視紀錄檔

3.5 安裝 multiline 外掛

還有一個坑的地方是錯誤紀錄檔一般都是很多行的,會把堆疊資訊列印出來,當經過 logstash 解析後,每一行都會當做一條記錄存放到 ES,那這種情況肯定是需要處理的。這裡就需要使用 multiline 外掛,對屬於同一個條紀錄檔的記錄進行拼接。

3.5.1 安裝 multiline 外掛

multiline 不是 logstash 自帶的,需要單獨進行安裝。我們的環境是沒有外網的,所以需要進行離線安裝。

介紹線上和離線安裝 multiline 的方式:

  • 線上安裝外掛。

在 logstash 根目錄執行以下命令進行安裝。

bin/logstash-plugin install logstash-filter-multiline

  • 離線安裝外掛。

在有網的機器上線上安裝外掛,然後打包。

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

拷貝到伺服器,/data/elk/logstash/mutiline

進入到容器中

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 表示安裝成功。

檢查下外掛是否安裝成功,可以執行以下命令檢視外掛列表。當出現 multiline 外掛時則表示安裝成功。

bin/logstash-plugin list

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

臨時方式啟動,主要是為了對映整個 filebeat 目錄,後面可以修改同步進度以及檢視紀錄檔檔案。

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

將容器內的資料夾拷貝到宿主機磁碟上

docker cp filebeat:/usr/share/filebeat /data/elk

建立紀錄檔目錄作為測試

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

啟動 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

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 傳輸的紀錄檔。

5.3 觀察 Filebeat 容器中的紀錄檔

docker logs filebat

可以看到 Filebeat 採集紀錄檔檔案,並同步到 Logstash 的紀錄檔。

5.4 建立 ES 索引

當 Logstash 將紀錄檔同步到 Elasticsearch 中後,就會自動在 Elasticsearch 中建立索引。然後我們需要在 Kibana 視覺化控制檯中建立一個對應的索引來檢視紀錄檔。步驟如下所示:

  • 開啟 Kibana 控制檯

  • 建立 passjava_log 索引

5.5 查詢紀錄檔

在 Kibana 搜尋大樓 關鍵字,可以查到紀錄檔輸出。需要注意的是,要選擇對應的過濾時間段。

六、報錯問題排查

Filebeat 出現報錯,但是過一會 Filebeat 和 Logstash 又成功建立了連線,而且紀錄檔也輸出到了 Logstash 了。暫時未找到原因。

 Failed to publish events caused by: EOF