ELK 日志采集系統(tǒng)搭建
“ ELK是Elasticsearch+Logstash+Kibana簡稱。”

一般我們需要進行日志分析場景:直接在日志文件中 grep、awk 就可以獲得自己想要的信息。但在規(guī)模較大的場景中,此方法效率低下,面臨問題包括日志量太大如何歸檔、文本搜索太慢怎么辦、如何多維度查詢。需要集中化的日志管理,所有服務(wù)器上的日志收集匯總。
常見解決思路是建立集中式日志收集系統(tǒng),將所有節(jié)點上的日志統(tǒng)一收集,管理,訪問。一般大型系統(tǒng)是一個分布式部署的架構(gòu),不同的服務(wù)模塊部署在不同的服務(wù)器上,問題出現(xiàn)時,大部分情況需要根據(jù)問題暴露的關(guān)鍵信息,定位到具體的服務(wù)器和服務(wù)模塊,構(gòu)建一套集中式日志系統(tǒng),可以提高定位問題的效率。ELK提供了一整套解決方案,并且都是開源軟件,之間互相配合使用,完美銜接,高效的滿足了很多場合的應用。目前主流的一種日志系統(tǒng)。
1. 架構(gòu)
ELK是Elasticsearch+Logstash+Kibana簡稱.
Elasticsearch 是一個分布式的搜索和分析引擎,可以用于全文檢索、結(jié)構(gòu)化檢索和分析,并能將這三者結(jié)合起來。Elasticsearch 基于 Lucene 開發(fā),現(xiàn)在是使用最廣的開源搜索引擎之一。
Logstash 簡單來說就是一根具備實時數(shù)據(jù)傳輸能力的管道,負責將數(shù)據(jù)信息從管道的輸入端傳輸?shù)焦艿赖妮敵龆耍c此同時這根管道還可以讓你根據(jù)自己的需求在中間加上濾網(wǎng),Logstash提供了很多功能強大的濾網(wǎng)以滿足你的各種應用場景。
Kibana 是一個開源的分析與可視化平臺,設(shè)計出來用于和Elasticsearch一起使用的。你可以用kibana搜索、查看、交互存放在Elasticsearch索引里的數(shù)據(jù),使用各種不同的圖標、表格、地圖等,kibana能夠很輕易的展示高級數(shù)據(jù)分析與可視化。
一個簡單的 ELK 架構(gòu)圖如下:

在這種架構(gòu)中,Logstash 通過輸入插件從多種數(shù)據(jù)源(比如日志文件、標準輸入 Stdin 等)獲取數(shù)據(jù),再經(jīng)過濾插件加工數(shù)據(jù),然后經(jīng) Elasticsearch 輸出插件輸出到 Elasticsearch,通過 Kibana 進行可視化展示。
這種架構(gòu)非常簡單,使用場景也有限。初學者可以搭建這個架構(gòu),了解 ELK 工作模式, 但是生產(chǎn)環(huán)境中并不推薦. 如要有以下問題:
Logstash 依賴 java、在數(shù)據(jù)量大的時候,Logstash 進程會消耗過多的系統(tǒng)資源,這將嚴重影響業(yè)務(wù)系統(tǒng)的性能。因此官網(wǎng)現(xiàn)已經(jīng)推薦通過 filebeat 代替 Logstash Agent。
Logstash 將資源耗盡系統(tǒng)或者其自身出故障的問題時,日志數(shù)據(jù)將會出現(xiàn)丟失等問題,因此引入 Kafka 集群作為消息緩沖隊列以提高數(shù)據(jù)傳輸?shù)目煽啃院头€(wěn)定性。
如此一來, 此架構(gòu)特別適合大型集群、海量數(shù)據(jù)的業(yè)務(wù)場景,它通過將前端 Logstash Agent 替換成 filebeat,有效降低了收集日志對業(yè)務(wù)系統(tǒng)資源的消耗。同時,消息隊列使用kafka集群架構(gòu),有效保障了收集數(shù)據(jù)的安全性和穩(wěn)定性,而后端Logstash和Elasticsearch均采用集群模式搭建,從整體上提高了ELK系統(tǒng)的高效性、擴展性和吞吐量。推薦的架構(gòu)圖如下:

2. 環(huán)境搭建
本文首先采用最簡單的架構(gòu)方式進行搭建, 后續(xù)博文將一步一步完善到生產(chǎn)環(huán)境集成消息隊列的架構(gòu)方式. 本次環(huán)境采用
Docker或者DockerCompose搭建, 如果還不能熟練使用麻溜去看帥帥之前發(fā)布的Docker 全家桶系列視頻教程:版本如下:
Elasticsearch: 6.8.16
Logstash: 6.8.16
Kibana: 6.8.16
2.1 拉取鏡像創(chuàng)建網(wǎng)絡(luò)
docker pull elasticsearch:6.8.16
docker pull kibana:6.8.16
docker pull docker.elastic.co/logstash/logstash:6.8.16
# 創(chuàng)建 ELK 運行的網(wǎng)絡(luò)
docker network create elastic
2.2 ElasticSearch
配置
elasticsearch.yml
cluster.name: "es-docker-cluster"
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"
安裝與啟動
通過如下 Docker 命令:
docker run -d --name elasticsearch --network elastic \
-p 9200:9200 -p 9300:9300 \
-e node.name=esNode -e cluster.name=es-docker-cluster -e discovery.type=single-node \
-e bootstrap.memory_lock=true -e "ES_JAVA_OPTS=-Xms1024m -Xmx1024m" \
-v ${CONF_DIR}/es:/usr/share/elasticsearch/config \
-v ${VOLUME_DATA_DIR}/es:/usr/share/elasticsearch/data \
-v ${LOGS_DIR}/es:/usr/share/elasticsearch/logs \
elasticsearch:6.8.16
其中,
CONF_DIR,VOLUME_DATA_DIR,LOGS_DIR是我本地配置的環(huán)境變量, 指向一個固定的文件夾用于掛載 Docker 容器的配置文件, 數(shù)據(jù)卷和日志文件.
測試
訪問 http://localhost:9200/ 看到如下界面就表示 Elasticsearch 啟動成功.

2.3 Kibana
配置
kibana.yml
server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
安裝
docker run -d --name kibana --network elastic \
-p 5601:5601 \
--link elasticsearch:elasticsearch \
-e ELASTICSEARCH_URL=http://elasticsearch:9200 \
-e ELASTICSEARCH_HOSTS='["http://elasticsearch:9200"]' \
-v ${CONF_DIR}/kibana:/usr/share/kibana/config \
kibana:6.8.16
測試
訪問 http://localhost:5601/ 看到如下界面就表示 Kibana 啟動成功.

2.4 Logstash
配置
logstash.yml
http.host: "0.0.0.0"
xpack.monitoring.elasticsearch.hosts: [ "http://elasticsearch:9200" ]
xpack.monitoring.enabled: true
配置
pipeline/logstash.conf指定 logstash 輸入輸出
# Sample Logstash configuration for creating a simple
# Beats -> Logstash -> Elasticsearch pipeline.
input {
tcp {
id => "toEs"
mode => "server"
host => "0.0.0.0"
port => 9600
codec => json_lines
}
}
filter {
}
output {
stdout {
codec => rubydebug
}
elasticsearch {
hosts => ["elasticsearch:9200"]
action => "index"
index => "applog"
}
}
從 9600 端口獲取數(shù)據(jù)并做兩個輸出, 一個輸出到標準輸出, 一個是通過 Elasticsearch 插件寫入 Elasticsearch, 且寫入 Elasticsearch 時索引名為 <applog>
啟動
docker run -d --name logstash --network elastic \
-p 5044:5044 -p 9600:9600 \
--link elasticsearch:elasticsearch \
-v ${CONF_DIR}/logstash/config/:/usr/share/logstash/config/ \
-v ${CONF_DIR}/logstash/pipeline/:/usr/share/logstash/pipeline/ \
docker.elastic.co/logstash/logstash:6.8.16
檢查是否啟動成功
通過 logstash 啟動日志查看

通過 KIbana: 進入 Kibana 的
monitoring視圖


當在 Kibana 中看到 Elasticsearch, Kibana, Logstash 都啟動成功就表明我們 ELK 環(huán)境搭建就完成了.
3. 集成 SpringBoot, 并將日志寫入 ELK
準備一個 SpringBoot 測試環(huán)境:
SpringBoot 版本: 2.4.1
logback 版本: 1.2.4
3.1 引入依賴
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
需要特別注意的是 Spring boot web 環(huán)境中攜帶了
spring-boot-starter-logging,logback-core,logback-classic,logback-access這幾個必要包, 但是版本可能和 Logstash 不匹配, 因此最好是在dependencyManagement中對版本進行管理控制.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
3.2 配置 logback
在 類路徑
resources下新建logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<include resource="org/springframework/boot/logging/logback/base.xml" />
<contextName>logback</contextName>
<!-- 指定日志寫入本機 9600 端口 -->
<appender name="stash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:9600</destination>
<!-- encoder必須配置,有多種可選 -->
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level="info">
<appender-ref ref="stash" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
3.3 編寫測試方法
@RestController
public class TestLoggingController {
@GetMapping("/logging")
public void testLogging() {
LOGGER.info("Come in test logging...");
LOGGER.debug("這是一個 Debug 級別的日志");
LOGGER.info("這是一個 INFO 級別的日志");
LOGGER.warn("這是一個 WARN 級別的日志");
LOGGER.error("這是一個 ERROR 級別的日志");
LOGGER.error("這是一個 ERROR 級別的日志, 并攜帶了一個 Exception.",
new UnsupportedOperationException("暫不支持操作的異常!"));
}
3.4 測試
訪問 http://localhost/logging (端口改為了 80)
Logstash 后臺可以看到如下輸出(因為
logstash.conf引入了標準輸出組件)
Kibana/Management可以看到索引applog已經(jīng)被創(chuàng)建, 加入Index Pattern



進入
Discover即可看到日志已經(jīng)在 Kibana 中可以可視化

至此, ELK 日志采集系統(tǒng)便已經(jīng)成功搭建完成.
4. 下一步
后面我們會對這個架構(gòu)所存在的問題逐一進行驗證和解決, 最終達到一個生產(chǎn)環(huán)境高可用的架構(gòu)模式. 大家持續(xù)關(guān)注!
既然大俠已經(jīng)看到這里了, 那小弟也不藏著掖著了, 公眾號后臺回復ELK 即可拿到帥帥整理好的 ELK docker compose 配置文件, 一個 up 命令啟動 ELK, 一個 down 命令停止 ELK, 它 不香嗎?

如果有任何相關(guān)的問題都可以加入 QQ/微信群一起討論, 學習, 進步. 此外如果有任何對于本公眾號的意見和建議也歡迎大家留言積極批評指正, 最后, 愿你我都能成為更好的自己.
我是帥帥, 一個集帥氣, 幽默與內(nèi)涵, 并且熱愛編程, 擁抱開源, 喜歡烹飪與旅游的暖男, 我們下期再見. 拜了個拜!
老規(guī)矩別忘了哦, 點擊原文鏈接跳轉(zhuǎn)到我們官方的博客平臺哦.
悄悄話
————
每文一句
————
Don't aim for success if you really want it. Just stick to what you love and believe in, and it will come naturally.
少一些功利主義的追求, 多一些不為什么的堅持.
日常求贊
————
你們白漂的力量就是我拖更的史詩級動力, 點贊, 評論, 再看, 贊賞, 看都看到這了, 隨便點一個咯.
關(guān)注加好友
拉你進大佬交流群
————————————————
