日誌服務架構設計

最近想把以前作過的日誌項目及我的的思考梳理一下,因而有了本文。前端

背景

咱們這邊應用部署的環境比較複雜,主要有如下幾種:git

  • 機器直接部署
  • 經過原生docker部署
  • 經過kubernates集羣部署

部署環境不統一,致使查看應用日誌很不方便。github

業務需求

與部署環境對應,對於日誌收集需求分爲如下幾類:docker

  • 機器上的文本日誌(直接運行在物理機或者虛擬機中的應用日誌)
  • 運行在docker容器中的應用日誌
  • 運行在kubernates集羣中的應用日誌

具體業務需求能夠拆分爲:後端

  • 按照項目、應用、實例維度檢索日誌並支持搜索關鍵字高亮(由於你們檢索日誌的時候,確定是檢索某個項目、某個應用、某個實例的日誌)
  • 支持檢索出某條想要的日誌後,能夠查看上下文(查看該日誌所在日誌文件的日誌上下文)
  • 支持日誌下載(目前支持兩種場景:搜索結果下載、上下文下載;支持兩種方式:在線下載、離線下載)
  • 支持自動化批量部署、卸載Agent,部署、卸載過程可視化
  • 單實例支持多elasticsearch集羣
  • 支持文本日誌、docker日誌、k8s日誌並能與將日誌與其業務意義對應上。(即不論是哪一種日誌形式、來源,最終都須要與業務意義上的項目、應用、實例對應起來,由於對於日誌的使用者來講,查詢日誌的出發點確定是查詢某個項目、某個應用(能夠不選)、某個實例(能夠不選)、某段時間的日誌。)
  • 支持部署到業務本身的集羣中

需求已經明確了,下面看一下業界方案。安全

業界日誌系統架構

  • Collector的做用是:
    • 清洗、匯聚數據,減小對於後端集羣的壓力。
    • 安全,不容許Agent直連kafka等內部集羣,保證必定的安全性,即便後端發生調整也能保證對於Agent鏈接、認證方式的穩定。
  • MQ的做用是削峯填谷、解耦、屢次消費。

上圖的架構是業界比較通用的一種架構,對於各類場景都考慮的比較全。微信

既然業界的架構已經這麼完備,那麼咱們是否就直接採用呢?網絡

對於咱們而言,有如下幾個問題:架構

  • 涉及的組件比較多,鏈路比較長,運維比較麻煩
  • 這一整套架構,不利於單獨部署(好比某個業務應用部署機房網絡是隔離的,並且項目又不大,只能提供有限的幾臺機器,這時候若是須要部署業界這套架構的話,資源就會比較受限,若是想作到即支持業界架構組件的可插拔(好比可靈活的決定是否須要Collector、MQ),那麼就須要運維幾套配置或代碼)
  • 最關鍵的就是其中組件提供的功能,咱們目前用不到。好比MQ的削峯填谷、屢次消費。

組件選擇

選擇組件,咱們這邊主要是從如下幾個方面進行考量的:app

  1. 組件對應的開源生態完整、活躍度高
  2. 對應的技術棧是咱們所熟悉的,咱們這邊語言技術棧主要是Java、Go,若是組件語言是C、Ruby,應該就被排除了。
  3. 運維成本
  4. 易部署、性能好

Agent

一提到日誌收集方案,你們第一個想到的確定是ELK(Elasticsearch、Logstash、Kibana ),但Logstash依賴於JVM不論是性能仍是簡潔性,都不是日誌收集agent的首選。

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

Collector、MQ

Elasticsearch集羣在部署的時候,通常都是提早估計好容量、機器、shard等信息,由於Elasticsearch集羣運行後,再水平拓展,比較麻煩,而咱們這邊因爲業務及成本限制沒法很好的預估容量,因此就結合公司實際要求:使用日誌服務的業務方自帶機器,也就是業務方會有獨立的Elasticsearch集羣。

每一個業務方都使用本身的Elasticsearch集羣,因此集羣壓力不會很大,從而Collector、MQ這兩個組件對於咱們的做用也就很小了。

ETL

由於Elasticsearch Ingest Node徹底能夠知足咱們的解析需求,因此就沒有必要再引入Logstash等相關組件了。

到這裏,基本能夠看出咱們的架構以下:

架構設計的幾個原則:

  • 合適優於業界領先
  • 簡單優於複雜
  • 演化優於一步到位

具體實現

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

  • docker日誌的場景比較單一,都是經過以前一個產品A發佈部署的,其docker命名規則比較統一,能夠經過截取docker.container.name來獲取應用名字;同時在部署的時候,能夠知道部署目標機器的ip,這樣就能夠經過應用+ip來做爲實例名稱。
  • k8s場景也比較統一,都是經過以前一個產品B發佈部署的,其pod命名規則比較統一,能夠經過截取kubernetes.pod.name來獲取應用名字(但須要經過namespaces關聯到tenant,再經過tenant與項目一一對應);k8s中的pod.name就是惟一的,以此來做爲實例名稱便可。
  • 文本日誌:由於文本日誌主要的場景是已經裸機部署的應用,這種場景下,不存在應用自動遷移的狀況,因此文本日誌的應用名稱、實例名稱能夠在部署的時候打上標籤便可。

具體規則及解析見下圖(實例部分處理暫未標註):

推薦寫日誌到文本文件中,使用標準輸出就好。

到這裏能夠發現咱們選擇Filebeat來做爲日誌的收集端,Elasticsearch來存儲日誌並提供檢索能力。

那麼,日誌的清洗在哪裏作呢?

日誌的清洗通常有兩種方式:

  • 先把日誌收集到kafka,再經過Logstash消費kafka的數據,來清洗數據
  • 直接經過Elasticsearch的[Ingest Node]來清洗數據,由於Ingest Node也支持Grok表達式

對於,咱們的場景而言,咱們須要清洗數據的要求比較簡單,主要是應用、實例名稱的截取還有文本日誌中日誌時間的處理(@timestamp重置,時區處理),因此咱們選擇了方案2。

在咱們的方案中,並無提供Kibana 的界面直接給用戶用,而是咱們本身根據公司業務獨立開發的。

前端界面爲何不採用Kibana,而須要本身開發?

  1. kibana對於業務開發人員有必定的學習成本
  2. kibana界面沒有很好的將日誌內容與業務意義關聯起來(界面選擇總比一次次的輸入要好,這也是咱們將日誌的項目、應用、實例等業務信息解析出來的緣由)
  3. log-search支持Query String,所以對於熟悉kibana的開發人員來講,在咱們本身開發的前端界面檢索效果是同樣的。

log-search提供的功能能夠參見github:github.com/jiankunking…

若是日誌須要清洗的比較多,能夠採用方案1,或者先不清洗,先把數據落到Elasticsearch,而後在查詢的時候,進行處理。好比在咱們的場景中,能夠先把日誌落到Elasticsearch中,而後在須要檢索應用名稱的時候,經過代碼來處理並獲取app名字。

監控、告警

其實基於日誌能夠作不少事情,好比:

  • 基於日誌作監控(Google Dapper)
  • 基於日誌作告警
  • 基於日誌作Machine Learning

具體思路,能夠參見下圖:

前提:能要求使用方,按照某種規則打印日誌。 監控發展:監控基本就是先打通鏈路trace,而後再在上報信息或者日誌信息中,增強業務方面標識,即給監控添加業務維度方面的視角。

其它

DaemonSet

以DaemonSet方式部署Filebeat來收集日誌,其實收集也是宿主機/var/lib/docker/containers目錄下的日誌。 Running Filebeat on Kubernetes

Sidecar

一個POD中運行一個sidecar的日誌agent容器,用於採集該POD主容器產生的日誌。

莫名想起了istio。

Filebeat能夠以sidecar模式來進行容器日誌的收集,也就是filebeat和具體的服務容器部署在同一個pod內,指定收集日誌的路徑或文件,> 便可將日誌發送到指定位置或Elasticsearch這類的搜索引擎。 每一個pod內部署filebeat的模式,好處是和具體的應用服務低耦合,可擴展性強,不過須要在yaml進行額外配置。

我的微信公衆號:

我的github:

github.com/jiankunking

我的博客:

jiankunking.com

相關文章
相關標籤/搜索