本文介紹使用Docker安裝部署Filebeat與Elasticsearch、Logstash、Kibana(簡稱ELK)全家桶7.5.1。如果熟悉框架的話,直接copy配置文件與docker命令,簡單刪減和修改路徑,即可快速啟動整個鏈路。
簡單的ELK數據平臺是這樣的流程:

由于Kafka并不是ELK中必須的組件,所以本博客跳過部署Kafka,直接將Filebeat數據打到logstash上。關于Kafka的相關知識,以后再作詳細講解。
本文中的配置環境是這樣的:
Filebeat在A機器上采集日志,ELK部署在B機器上。其中Elasticsearch與Logstash都采用的是單節點安裝。
版本選擇
寫此文的時候,Filebeat和ELK最新的版本為7.6.1,不過筆者看了Filebeat 7.6.1的發布日志,發現該版本屬于一個緊急bugfix版本——因為7.6.0的bug導致k8s pods的標簽/注解存在問題。但是7.6.1的穩定性依舊不敢保證,畢竟筆者的項目接下來service mesh化是要結合k8s的,為了減小風險,退而求其次,選擇7.5.2。后來因為踩坑又換到7.5.1,原因在下面說明。
filebeat7.5.2在搭建之后運行幾小時之后,會出現filebeat io timeout的問題。官方論壇有人提出從7.5.1升級到7.5.2之后也出現了同樣的問題,但是筆者并沒有找到官方給出有效的解決方案。另外出于時間成本考慮沒有時間去查找問題,所以選擇版本為7.5.1。目前數據流已經穩定運行兩周了。
按照官方說明,只要全家桶不是升級到8.0,都是可以輕松升級的。所以系統穩定后隨時可以升級。
安裝Elasticsearch
Elasticsearch是一個分布式、高擴展、高實時的搜索與數據分析引擎。它能很方便地使大量數據具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸縮性,能使數據在生產環境變得更有價值。
# 創建自定義的網絡(用于連接到連接到同一網絡的其他服務(例如Logstash和Kibana))
docker network create somenetwork
# 運行 elasticsearch
docker run --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.5.1
# 查看容器狀態
docker ps
# 檢測 elasticsearch 是否啟動成功
curl 127.0.0.1:9200
安裝Logstash
Logstash作為Elasicsearch常用的實時數據采集引擎,可以采集來自不同數據源的數據,并對數據進行處理后輸出到多種輸出源,是Elasticstack的重要組成部分。
增加logstash的聲明文件,logstash.yml。編輯內容如下
# 配置文件讀取路徑
path.config: /home/ec2-user/docker_config/logstash/conf.d/*.conf
# 日志輸出路徑
path.logs: /var/log/logstash
在上面配置文件讀取路徑中,增加一個測試文件test.conf,內容如下:
input {
beats {
port => 5044
}
}
filter {
if "JAVA-logs" in [tags]{
grok {
# grok正則化會按照順序許匹配送進來的日志,當碰到第一個匹配成功的日志就break掉這個循環。
match => {
# 分別是服務器記錄行為日志,不帶參數參數的請求,帶參的get請求,帶參的post請求,兼容舊版的記錄行為日志。這里的格式就跟具體業務的日志有關了
"message" => ["%{TIMESTAMP_ISO8601:logtime} %{DATA} %{LOGLEVEL:loglevel} %{DATA:classpath} - %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{word:logdata}",
"%{TIMESTAMP_ISO8601:logtime} %{DATA} %{LOGLEVEL:loglevel} %{DATA:classpath} - REQUEST DATA : uri=%{URIPATHPARAM:request};client=%{IP:clientIp}];&&&&%{DATA:common_param}&&&&;耗時:%{NUMBER:costtime}ms",
"%{TIMESTAMP_ISO8601:logtime} %{DATA} %{LOGLEVEL:loglevel} %{DATA:classpath} - REQUEST DATA : uri=%{URIPATH:request}?%{DATA:get_param};client=%{IP:clientIp}];&&&&%{DATA:common_param}&&&&;耗時:%{NUMBER:costtime}ms",
"%{TIMESTAMP_ISO8601:logtime} %{DATA} %{LOGLEVEL:loglevel} %{DATA:classpath} - REQUEST DATA : uri=%{URIPATHPARAM:request};client=%{IP:clientIp};payload=%{DATA:payload}];&&&&%{DATA:common_param}&&&&;耗時:%{NUMBER:costtime}ms",
"%{TIMESTAMP_ISO8601:logtime} %{LOGLEVEL:loglevel} %{DATA} %{DATA:classpath} : %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{DATA:logcontent} %{WORD:logdata}"]
}
# 過濾完成之后刪除多余字段,節約磁盤空間。
remove_field => ["@version","host.name"]
}
# 拆分common_param字段(采用ruby插件)
ruby {
code => "
if !event.get('common_param').nil? then
array1 = event.get('common_param').split('%')
array1.each do |temp1|
if temp1.nil? then
next
end
array2 = temp1.split('=')
key = array2[0]
value = array2[1]
if key.nil? then
next
end
event.set(key, value)
end
end
"
# 移除message字段
remove_field => [ "message" ]
}
# 如果是debug級別日志,直接拋棄掉這條日志
if [loglevel] !~ "(ERROR|WARN|INFO)" {
drop { }
}
# 拋棄掉grok解析失敗的日志
if "_grokparsefailure" in [tags] {
drop { }
}
# 使用日志時間替換logstash的時間戳
date {
match => ["logtime", "yyyy-MM-dd HH:mm:ss.SSS"]
target => "@timestamp"
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "filebeat-logstash-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
grok過濾的message對應的五種日志形式示例:
2020-03-04 13:25:27.488 [http-nio-9000-exec-11] INFO com.xxx.classpath - oper log b peron login 231148
2020-03-04 14:19:34.428 [http-nio-9000-exec-8] INFO com.xxx.classpath - REQUEST DATA : uri=/url;client=10.13.180.91];&&&®ion=TW%platform=2%version=unknown%mobileModel=unknown%osVersion=unknown%connectType=unknown%uuid=unknown&&&&;耗時:6ms
2020-03-07 08:09:51.890 [http-nio-9000-exec-3] INFO com.xxx.classpath - REQUEST DATA : uri=/url?offset=10&playerUserUuid=231002;client=10.13.180.36];&&&®ion=unknown%platform=1%version=unknown%mobileModel=unknown%osVersion=unknown%connectType=unknown%uuid=unknown&&&&;耗時:126ms
2020-03-02 09:55:28.196 [http-nio-9000-exec-4] INFO com.xxx.classpath - REQUEST DATA : uri=/url;client=10.13.180.91;payload={“ticket”:“xxx”}];&&&®ion=TW%platform=3%version=unknown%mobileModel=unknown%osVersion=unknown%connectType=unknown%uuid=unknown&&&&;耗時:45ms
2020-03-03 03:05:33.634 INFO 13175[io-9000-exec-12] com.xxx.classpath : oper log c peron login 254264
記得要映射logstash.yml中的兩個路徑。
docker run --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 -it -d -p 5044:5044 --name logstash --net somenetwork -v /home/ec2-user/docker_config/logstash/logstash.yml:/usr/share/logstash/config/logstash.yml -v /home/ec2-user/docker_config/logstash/conf.d/:/home/ec2-user/docker_config/logstash/conf.d/ -v /home/ec2-user/docker_logs/logstash:/var/log/logstash logstash:7.5.1
查看容器運行狀態
docker ps
寫logstash配置,grok插件是必須要學會的。
安裝Kibana
Kibana是一個開源的分析與可視化平臺,設計出來用于和Elasticsearch一起使用的。你可以用Kibana搜索、查看、交互存放在Elasticsearch索引里的數據,使用各種不同的圖表、表格、地圖等Kibana能夠很輕易地展示高級數據分析與可視化。
# 在本例中,Kibana使用默認配置
# 運行 Kibana
docker run --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 -d --name kibana --net somenetwork -p 5601:5601 kibana:7.5.1
# 查看容器啟動狀態
docker ps
1
安裝Filebeat
Filebeat是本地文件的日志數據采集器,可監控日志目錄或特定日志文件,并將它們轉發給Elasticsearch或Logstatsh進行索引、Kafka等。帶有內部模塊(Apache,Nginx,System和MySQL等),可通過一個指定命令來簡化通用日志格式的收集,解析和可視化。
filebeat.yml配置,更多配置選項可以查看官網。
filebeat.inputs:
- type: log
enabled: true
# 需要收集的日志所在的位置,可使用通配符進行配置
paths:
- /home/ec2-user/jenkins/logs/server-api/*.log
# 這個文件記錄日志讀取的位置,如果容器重啟,可以從記錄的位置開始取日志
registry_file: /home/ec2-user/docker_config/filebeat_registry
# 為每個項目標識,或者分組,可區分不同格式的日志
tags: ["java-logs"]
exclude_lines: ['.*uri=/basic/time/current;.*']
# 日志輸出配置
output.logstash:
# 內網B機器的ip:port
hosts: ['10.13.180.42:5044']
enabled: true
docker運行filebeat,映射需要的配置文件
docker run --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name filebeat -d -v /home/ec2-user/docker_config/filebeat.docker.yml:/usr/share/filebeat/filebeat.yml -v /home/ec2-user/jenkins/logs/server-api/:/home/ec2-user/jenkins/logs/server-api/ -v /home/ec2-user/filebeat_collect/:/home/ec2-user/filebeat_collect/ -v /home/ec2-user/docker_config/filebeat_registry:/home/ec2-user/docker_config/filebeat_registry docker.io/store/elastic/filebeat:7.5.1
啟動Kibana查看數據
如果沒有配置Kibana所在服務器域名的話,可以瀏覽器訪問"ip:5601"來訪問,不過值得注意的是Kibana自身沒有安全限制,一般采用網關鑒權限制或者第三方安全插件,可以谷歌搜索下。
進入Kibana,點擊下面Discover菜單。

作為初學者,直接輸入"*",然后點擊"next step"。先別理會是什么,看看數據建立初始成就感很重要。

選擇@timestamp作為時間坐標。點擊"Create index pattern"。然后再次查看Discover菜單,就發現日志數據輸出到kibana了。

Kibana常用功能說明:
- Discover 數據搜索查看
- Visualize 圖標制作
- Dashboard 儀表盤制作
- Timelion (新版本在Visualize下)時序數據的高級可視化分析
- DevTools 開發者工具
- Management 配置
總結
本文采用最簡單粗暴的docker命令行進行構建,更好的構建方式是采用docker compose方式