理解OpenShift(6):集中式日志處理


 

理解OpenShift(1):網絡之 Router 和 Route

理解OpenShift(2):網絡之 DNS(域名服務)

理解OpenShift(3):網絡之 SDN

理解OpenShift(4):用戶及權限管理

理解OpenShift(5):從 Docker Volume 到 OpenShift Persistent Volume

理解OpenShift(6):集中式日志處理

 

** 本文基於 OpenShift 3.11,Kubernetes 1.11 進行測試 ***

1. Docker 容器日志處理的幾種方式

(1)由應用自己處理日志,而不需要容器引擎參與

比如一個使用Log4j2 日志組件的Java應用, 它通過日志組件將日志發往一個遠端日志服務器。此時,不利用容器引擎的日志功能。

(2)使用數據卷(Data volume)

使用數據卷,容器內應用將日志寫入數據卷中。此時,也不利用容器引擎的日志功能。

(3)使用 Docker 日志驅動(logging driver)

Docker 日志驅動會讀取容器中主進程的 stdout(標准輸出) 和 stderr(錯誤輸出),然后將內容寫入容器所在的宿主機上的文件中。

Docker 支持多種日志驅動。

(圖片來源:https://jaxenter.com/docker-logging-gotchas-137049.html

幾個比較常見的:

  • json-file: 這是默認驅動。容器主進程(PID 為1的進程)的 stdout 和 stderr 會被輸出到宿主機上的 JSON 文件。該文件可以在 docker inspect 命令的"LogPath"輸出中看到,比如 "LogPath": "/var/lib/docker/containers/a44b41506dc48a469fd69ddbdf84ad16d14f16191164361a69606c579c506a2c/a44b41506dc48a469fd69ddbdf84ad16d14f16191164361a69606c579c506a2c-json.log"。
  • syslog: 將日志信息發送到 syslog 服務器
  • journald: 將容器日志信息寫入journald (journald 是 systemd 提供的一個日志服務)
  • gelf: 將日志消息寫入一個 GELF 端點,比如 Logstash
  • fluentd: 將日志信息發送到 Fluentd 服務 

更多日志驅動,可以查看 https://docs.docker.com/config/containers/logging/configure/#supported-logging-drivers。 

Docker 還支持插件形式的更多日志驅動,具體請看 https://docs.docker.com/config/containers/logging/plugins/

(4)使用專門的日志容器

Docker 日志驅動這種實現方式有一些限制:

  • 只支持日志轉發,不會做日志解析和處理
  • 只支持容器內應用發到 stdout 和 stderr 的日志,不支持其它日志,比如日志文件內的日志

對於這些不支持的場景,比如應用有將日志寫到日志文件,此時可以利用在同一個Pod中的專門日志容器。它會以邊車(sidecar)形式讀取應用容器中的日志產生,然后做處理和轉發,比如轉發到 stdout 和 stderr。

另外,某些這種場景還有另外一種更簡單的處理方式。以 Nginix 為例,它默認寫入日志文件,然后通過下面的方式,將日志也輸出到 stdout 和 stderr。這種方式有一些限制,具體可參考 https://github.com/moby/moby/issues/19616

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

2. Kubernetes/OpenShfit 日志處理

2.1 EFK 概述

OpenShift/Kubernetes 環境的日志處理可分為三個發展階段,或三種處理類型:

類型 說明 使用方式
容器本地日志(container local logging) 寫到容器內部的標准輸出(standard output)和標准錯誤流(stand error),或者容器內日志文件。這種日志的問題是當容器死掉后,日志也會丟失,也就無法再訪問了。 需登錄進容器查看日志文件,或使用容器命令獲取日志。OpenShift 提供 oc rsh 命令以進入容器,oc logs 命令以獲取日志。
節點本地日志(node-level logging) 容器引擎將容器中所有的標准輸出和標准錯誤輸出都轉發到容器所在的本地節點上。Docker 可利用其日志驅動(logging driver)。為了避免容器中的日志將節點撐爆,可以做 log rotation。這種方式比 local logging 方式要好,但是還不是非常好,因為日志會保存在本地節點上。 需登錄宿主機,查看本地日志文件
集群集中日志(cluster-level-loggin) 這需要另外的后端來存儲、分析和查詢日志。后端可以在集群內,也可在集群外。一個  node-level 日志處理插件(比如 Fluentd)會運行在每個節點上,將節點上的日志發到集中的日志處理后端。還有一個可視化組件,讓用戶可以可視化地查看日志。 可通過瀏覽器或其它可視化界面在線查看日志

EFK(ElasticSearch - Fluentd - Kibana)是一種能夠實現集群集中日志處理的開源套件。其中,

三個組件中,Fluentd 會直接和Docker/K8S/OKD打交道,而 ES 和 Kibana 則相對獨立,不和容器集群有直接關系,除了用戶校驗以外。Fluentd 致力於解決多種日志來源和多種日志存儲之間的復雜問題。它作為日志和日志存儲之間的中間件,負責日志的收集、過濾和轉發工作。

 

Fluentd 采用插件形式的架構,支持為了滿足各種需求的日志采集、過濾、緩存和輸出等功能。其v0.12 版本架構如下:

其中:

  • Input: 告訴 Fluentd 引擎待收集的日志
  • Engine:  主引擎,實現核心功能,比如緩存(buffering)、錯誤處理、消息路由等
  • Output:  告訴 Fluentd 將輸出的日志發往何處,通過插件支持多種目的,比如 ElasticSearch、MongoDB 或數據庫等。 

2.2 OpenShift 環境中的EFK

2.2.1 EFK 部署

2.2.2 Fluentd

在 K8S/OKD 環境中,Fulentd 以 DeamonSet 形式運行在每個節點上。它會以 Volume 形式將所在宿主機上的多個保存日志的目錄或文件掛載進容器,以被容器中的Fluentd進程所讀取:

  • /run/log/journal:這是系統 systemd 輸出日志的目錄。
  • /var/log:這是系統所有日志的根目錄。
  • /var/lib/docker:Docker 容器引擎通過日志驅動將本機上所有容器的標准輸出和標准錯誤輸出保存在該目錄中,每個容器一個文件。

Fluentd 的配置文件被創建了一個 OpenShfit ConfigMap 對象(名為logging-fluentd),然后該對象被以 Volume 形式掛載為Fluentd容器目錄 /etc/fluent/configs.d/user。其中的配置文件 fluentd.conf 指定了Fluentd 所使用的 input、filter 和 output 插件及其配置:

其中

  • input 指定了將被收集的日志,主要包括 audit log、容器 log 和 systemd log 等。
  • filter 部分則指定了各種過濾和處理被收集到的日志的方式。
  • output 定義了目標 ElasticSerach。K8S/OKD EFK 允許存在兩個 ES 集群,一個用於保存容器中應用的日志,一個用於保存系統日志。 

ES 環境的信息以環境變量的形式保存在 Fluentd pod 上:

 

2.3 采用EFK后的好處和影響

被影響人員 影響(好的方面) 影響(不好的方面)/要求
容器雲平台運維人員
  • 對平台所有有價值的日志能做到統一收集、統一存儲和查詢
  • 統一了日志處理的技術棧
  • 為將來進一步數據處理做准備
  • 會引入一套新的技術棧和工具,需要有學習成本
容器應用開發人員
  • 可以在統一的瀏覽器界面(Kibana)上查詢所有容器的應用
  • 要求將容器中應用的日志都輸出到標准輸出和標准錯誤輸出
  • 需要改變傳統的登錄到環境中查看日志的習慣,改為在Kibana界面上查看日志
  • 需要有Kibana 界面使用的一些技能和知識
容器雲平台研發團隊
  • 集中式日志是容器雲平台不可或缺的一個重要組件
  • 需要考慮具體的實現架構和部署架構,做到穩定、可靠、彈性
  • 需要考慮在瀏覽器中查看日志這種新方式對應用開發人員的影響,需要注意用戶體驗,讓用戶接受這種新方式

3. 日志系統的集中部署模式

備注:本部分內容引用自 http://blog.51cto.com/13527416/2051506

3.1 簡單架構

這種架構只適合於開發測試環境,以及小型生產環境。

3.2 集群架構

這種架構適合於較大型但是日志產生量不大及頻率不高的環境。

3.3 引入消息隊列

在日志產生量大頻率高的情況下,需要引入消息隊列,以減輕對后端日志存儲的壓力,減少日志丟失概率。

3.4 多機房部署 - 獨立部署

采用單元化部署的方式來解決 ELK 多機房中遇到的問題(延時、專線流量過大等),從日志的產生、收集、傳輸、存儲、展示都是在同機房里面閉環消化,不存在跨機房傳輸與調用的問題。因為交互緊密的應用盡量部署在同機房,所以這種方案並不會給業務查詢造成困擾。
Logstash、Elasticsearch、Kafka、Kibana 四個集群都部署到同一機房中,每個機房都要每個機房自己的日志服務集群,比如A機房業務的日志只能傳輸給本機房 Kafka ,而A機房 Indexer 集群消費並寫入到A機房 Elasticsearch 集群中,並由A機房 Kibana 集群展示,中間任何一個步驟不依賴B機房任何服務。
該架構比較簡單直接,但問題是用戶需要在多個 Kibana 上查看部署在各個數據中心的應用產生的日志。

3.5 多機房部署 - 跨機房部署

目前沒有特別成熟的方案,估計大部分的架構還是前面的架構,這種跨機房架構更多地在大型互聯網公司有落地。通常有幾種方案供參考:

方案一,雙寫。技術可行。
在數據寫入ES時,通過MQ或者其他方式實現數據雙寫或者多寫,目前很多MQ都有數據持久化功能,可以保障數據不丟;再結合ES各種狀態碼來處理數據重復問題,即可實現多中心數據的最終一致。
 
方案二,第三方數據同步。基本上不可行。
例如使用mysql的主從同步功能,在不同數據中心之間,從本機房的mysql同步數據到ES,依托mysql數據一致性來保障ES數據一致。datax,StreamSet均提供了類似功能。
 
方案三,基於ES translog同步。基本上不可行。
讀取translog,同步並重放,類似於mysql binlog方式。看起來這種方式最干凈利落,但涉及到ES底層代碼修改,成本也較高,目前已有的實踐。
 
方案4,ES 正在實現新的 CCR(當前為beta版本)。期待將來可行。
cross cluster replication, 基於底層 sequence id 機制,實現的 Changes API,一個集群可被另外一個集群或是本集群“訂閱”,從而可以實現數據復制,進行同步,可以是跨數據中心集群也可以本地集群的數據同步。
 
方案5,ElasticSearch Tribe 方案。這種方案在 ES 前面放置一個集中式中間件,用於 Kibana 訪問。好像也不是特別靠譜。

 

參考連接:

感謝您的閱讀,歡迎關注我的微信公眾號:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM