你好,我是悟空。
最近有個讀者,他叫「老王「,外號「茴香豆泡酒」,找我崔更 ELK 的文章。
因之前我用的是軟體安裝 Logstash + Filebeat 的方式:
7000 字 | 20 圖 | 一文帶你搭建一套 ELK Stack 紀錄檔平臺
他想知道如何用容器化部署 ELK,於是我先寫了一半,因為要寫其他文章所以耽擱了。沒想到過了幾天後,老王說他已經部署好了,還寫了篇文章,恐怖如斯啊!
那可不行,我不能輸給他,必須自己安排一篇。那麼我寫的這篇有哪些特色內容呢?
本文主要內容如下:
這次我們演示在單機上用 Docker 部署 ELK Stack,大家可以參照這個教學部署在叢集環境中。
ELK Stack 整體的工作流程如下:
流程如下:
演示環境:
最後啟動了 5 個容器:
方案一:從網際網路下載 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
建立掛載目錄
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: "*"
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
curl http://localhost:9200
這個工具安裝好了後,相當於啟動了一個服務,這個服務是一個站點,通過在站點裡面存取 ES 的 API,就可以獲取到 ES 的當前資訊了。
安裝步驟如下:
sudo docker pull mobz/elasticsearch-head:5
docker run -d -p 9100 9100 mobz/elasticsearch-head:5
http://192.168.56.11:9100/
http://192.168.56.11:9200/
就可以看到 ES 的叢集和索引資訊了,這個要比在 Kibana 中用 DevTools 檢視更方便。
https://github.com/medcl/elasticsearch-analysis-ik/releases
選擇 ES 對應版本的 IK 分詞器,我的 ES 版本為 7.6.2。
解壓後,拷貝到 /data/elk/es/plugins/ik/ 目錄
獲取 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
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
方案一:從網際網路下載映象
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
建立 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"
}
}
建立 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" ]
# 刪除 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
檢視紀錄檔
還有一個坑的地方是錯誤紀錄檔一般都是很多行的,會把堆疊資訊列印出來,當經過 logstash 解析後,每一行都會當做一條記錄存放到 ES,那這種情況肯定是需要處理的。這裡就需要使用 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
編輯 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 的底層原理 + 填坑指南
docker restart logstash
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
建立紀錄檔目錄作為測試
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
當我們想要完全重新同步紀錄檔檔案時,可以將 Filebeat 這個資料夾刪掉:
/data/elk/filebeat/data/registry/filebeat
這個目錄下的 data.json 檔案會記錄同步的進度,刪掉後,重啟 Filebeat 後就會重新開始同步。
sudo vim /data/passjava/logs/wukong/error.log
模擬後端輸出的紀錄檔:
docker logs logstash
可以看到 logstash 收集到了 filebeat 傳輸的紀錄檔。
docker logs filebat
可以看到 Filebeat 採集紀錄檔檔案,並同步到 Logstash 的紀錄檔。
當 Logstash 將紀錄檔同步到 Elasticsearch 中後,就會自動在 Elasticsearch 中建立索引。然後我們需要在 Kibana 視覺化控制檯中建立一個對應的索引來檢視紀錄檔。步驟如下所示:
在 Kibana 搜尋大樓
關鍵字,可以查到紀錄檔輸出。需要注意的是,要選擇對應的過濾時間段。
Filebeat 出現報錯,但是過一會 Filebeat 和 Logstash 又成功建立了連線,而且紀錄檔也輸出到了 Logstash 了。暫時未找到原因。
Failed to publish events caused by: EOF