1. 程式人生 > >EFK 日誌實踐

EFK 日誌實踐

一、前言

      一提到日誌收集方案,大家第一個想到的肯定是ELK(Elasticsearch、Logstash、Kibana ),但Logstash依賴於JVM不管是效能還是簡潔性,都不是日誌收集agent的首選。

      個人感覺一個好的agent應該是資源佔用少,效能好,不依賴別的元件,可以獨立部署。而Logstash明顯不符合這幾點要求,也許正是基於這些考慮elastic推出了一個新的元件Filebeat

二、需求

      我們這邊收集日誌應對的場景主要是:文字日誌、docker日誌、k8s日誌,恰恰這些EFK全家桶都支援。

      我們希望日誌收集產品可以滿足以下幾個需求:

  1. 按照專案、應用、例項維度檢索日誌並支援搜尋關鍵字高亮(因為大家檢索日誌的時候,肯定是檢索某個應用、某個例項的日誌)
  2. 支援檢索出某條想要的日誌後,可以檢視上下文(檢視該日誌所在日誌檔案的前後多少條)
  3. 支援日誌下載(目前支援兩種場景:搜過結果下載、上下文下載;支援兩種方式:線上下載、離線下載)
  4. 支援自動化批量部署、解除安裝Filebeat,部署、解除安裝過程視覺化
  5. 單例項支援多elasticsearch叢集
  6. 支援文字日誌、docker日誌、k8s日誌並能與將日誌與其業務意義對應上。(即不管是哪種日誌形式、來源,最終都需要與業務意義上的專案、應用、例項對應起來,因為對於日誌的使用者來說,查詢日誌的出發點肯定是查詢某個專案、某個應用(可以不選)、某個例項(可以不選)、某段時間的日誌。

三、具體實現

      基於需求及ELK套件,梳理我們場景中特有的東西:

  1. docker日誌的場景比較單一,都是通過之前一個產品A釋出部署的,其docker命名規則比較統一,可以通過擷取docker.container.name來獲取應用名字;同時在部署的時候,可以知道部署目標機器的ip,這樣就可以通過應用+ip來作為例項名稱。
  2. k8s場景也比較統一,都是通過之前一個產品B釋出部署的,其pod命名規則比較統一,可以通過擷取kubernetes.pod.name來獲取應用名字(但需要通過namespaces關聯到tenant,再通過tenant與專案一一對應);k8s中的pod.name就是唯一的,以此來作為例項名稱即可。
  3. 文字日誌:因為文字日誌主要的場景是已經裸機部署的應用,這種場景下,不存在應用自動遷移的情況,所以文字日誌的應用名稱、例項名稱可以在部署的時候打上標籤即可。

具體規則及解析見下圖(例項部分處理暫未標註):
在這裡插入圖片描述

其實,我們不太推薦寫日誌,寫到文字檔案中,使用標準輸出就好。

      到這裡可以發現我們可以選擇Filebeat來作為日誌的收集端,Elasticsearch來儲存日誌並提供檢索能力。

      那麼,日誌的清洗在哪裡做呢?

      日誌的清洗一般有兩種方式:

  1. 先把日誌收集到kafka,再通過Logstash消費kafka的資料,來清洗資料
  2. 直接通過Elasticsearch的[Ingest Node]來清洗資料,因為Ingest Node也支援Grok表示式

      對於,我們的場景而言,我們需要清洗資料的要求比較簡單,主要是應用、例項名稱的擷取還有文字日誌中日誌時間的處理(@timestamp重置,時區處理),所以我們選擇了方案2。

其實,選擇方案二還有個原因就是:系統在滿足需求的同時,儘量保持簡單,減少依賴的元件。

四、整體架構

      到這裡可以,可以看出我們的架構基本如下:
這裡寫圖片描述

上圖只展示了一個elasticsearch叢集,提供檢索功能的log-search單例項是支援多elasticsearch叢集的。

      在我們的方案中,並沒有提供Kibana 的介面直接給使用者用,而是我們自己根據公司業務獨立開發的。

      程式碼架構:
在這裡插入圖片描述

      log-search提供的功能可以參見github:log-search

如果日誌需要清洗的比較多,可以採用方案1,或者先不清洗,先把資料落到Elasticsearch,然後在查詢的時候,進行處理。比如在我們的場景中,可以先把日誌落到Elasticsearch中,然後在需要檢索應用名稱的時候,通過程式碼來處理並獲取app名字。

個人微信公眾號:
這裡寫圖片描述