轉轉容器日志采集的演進之路
1 裸金屬時代
在裸金屬時代,轉轉業務日志的采集端由大數據部門二次開發的scribe+flume組成。當一臺服務器上部署了A服務后,如果需要對該服務進行日志采集,需要經過以下幾個步驟。
- 由運維部門提交工單,申請在該服務器上,對A服務日志進行采集
- 工單審核通過
- 在該服務器上自動化部署日志采集組件scribe+flume
- 通過工單中該臺主機的日志采集申請數據,渲染出scribe配置文件,指定該服務的日志輸出目錄為采集目錄
- scribe服務根據自身配置文件,采集目錄下的日志文件數據,發送到flume的對應端口,最后由flume將日志分發至kafka,hdfs等組件
在裸金屬時代,服務的部署節點的變化并不大。新服務上線,給該服務分配裸金屬服務器進行部署,一般情況下,很長一段時間,該服務的部署節點都不會發生任何變更。只有在活動大促期間對該服務的擴容,以及某臺裸金屬服務器硬件的損壞,才會導致部署在該主機上的服務,產生部署節點上的變更。
也正是由于在裸金屬時代,服務部署節點的超強粘性,轉轉日志采集的workflow運轉正常。
裸金屬時代日志采集workflow
2 容器時代
2016年,容器技術在中國開枝散葉,鋪天蓋地的技術文獻在網絡上流轉。轉轉是在2018年開始邁入到容器時代。
裸金屬到容器時代的轉變并不容易,轉轉選擇了一條幾乎是“最穩健”的路來完成這場技術革新。這條“最穩健”的路有幾點要求。
- 服務部署形式變化對業務方“無感知”,延用裸金屬時代的發布系統,兼容容器服務的發布與管理
- 服務器/容器終端登錄對業務方“無感知”,延用裸金屬時代的堡壘機登錄形式,兼容容器環境登錄
- 延用裸金屬時代的整體日志處理方式
- and so on
本篇文章我著重討論這場變革中的日志采集系統。由于日志處理體系是一個龐大且復雜的體系,在容器時代對其進行云原生革命,為了推進容器化,先要花大力氣打造日志采集基礎設施, 從時間和成本上,對于轉轉來說都是無法接受的。
容器服務運行特點與條件制約
- 服務容器跨節點調度頻繁
- 微服務框架已標準化日志輸出目錄
- 容器內的服務僅有文本日志輸出,沒有stdout
- 原有的裸金屬時代日志采集流程無法動搖
- 容器運行后會將標準化的日志輸出路徑掛載到宿主機目錄
2.1 log-pilot + flume 二次開發方案
當時的大數據團隊分析了容器服務運行的特點,針對該特點,打造了一套基于裸金屬時代的日志采集兼容方案。在原有日志組件及功能都完全不變的前提下,基于log-pilot+flume二次開發了一套日志轉儲引擎。
利用log-pilot的容器自動發現功能,提取出需要采集日志的容器元數據信息,并渲染出一個 flume 的配置文件,由 flume 將容器內的日志,采集后轉儲到本地宿主機的一個目錄下,最后由二次開發后的 log-pilot 更新宿主機上的scribe配置文件,并重啟 scribe 進程,這樣即對接上了之前裸金屬時代的后續日志采集流程。
log-pilot日志采集方案
為了兼容裸金屬時代不可動搖的日志采集地位,大數據部門貢獻了轉轉過渡到容器化的第一代日志采集系統。
該系統初期運轉良好,但隨著轉轉服務容器化率的提升,日志體量越來越大,這種日志的轉儲模式直接導致了日質量接近翻番,不僅磁盤容量受到巨大考驗,日志保留周期從30天逐漸縮短到了3天,而且 CPU iowait 也開始飆升,集群節點每天的 iotuil 長期在 90% 以上,繁重的 IO 負擔已經成了阻礙業務進一步容器化不容忽視的阻礙。在保留裸金屬時代日志采集流程不變的基礎上,運維針對容器場景做了進一步優化。
2.2 ByteCompass
運維自研的“日志指南者”,主要目的為剔除掉 log-pilot + flume 這個日志轉儲組件。少了一次日志的讀取和寫入,磁盤空間和IO壓力會驟減。ByteCompass 為運維全自研組件,以 systemd 管理運行在宿主機。
bytecompass日志采集方案
ByteCompass 借鑒了 log-pilot 感知容器變化的原理,watch 了 dockerd 的 api 接口,實時接收容器變化的事件信息。當有容器新增時,判斷其是否帶有日志采集標識,如果有,則進一步從容器配置的環境變量信息中讀取日志采集的元數據信息,最后將該容器信息根據模板渲染成新的 scribe.conf 配置文件,直接覆蓋宿主機中的該文件,并對該宿主機的 scribe 進程執行重啟操作。
經過 ByteCompass 對日志采集的優化,剔除掉了冗余的日志轉儲,無縫銜接了容器技術棧中的服務日志特征和裸金屬時代的日志采集流程。與裸金屬時代日志采集流程對比如下:
裸金屬時代與bytecompass日志采集對比
ByteCompass 改造后的日志采集,實現了集群節點平均 iowait 從 10% 降到 1%,波峰從 25%+ 降低到 3%-;ioutil 全天平均值下降到 7%以下,降幅達到92%;本地日志保留時間也從3天恢復到了7天以上。
3 云原生時代
在解決了磁盤瓶頸后,轉轉的容器化進程加速進行。容器時代為了兼容裸金屬時代遺留的用戶習慣,對容器環境做了很大程度上的妥協。隨著服務容器化的逐漸深入,轉轉開始從容器時代這個過渡階段,逐步開啟云原生時代。
以上裸金屬時代和容器時代的日志是按需采集,只有業務申請了日志采集,才會將日志采集走并做數據分析和處理。用戶查詢 info 及 error 日志排錯,依然是很原始的登錄到裸金屬服務器上或登錄到容器中,或通過日志查詢平臺,直接檢索容器服務所在物理機掛載到 hostPath 中的日志文件。
云原生時代給日志采集提出了更高的要求,在保留現有日志分析的基礎之上,還要實現全量日志的集中存儲與檢索。以及考慮到未來 k8s 版本對 dockerd 依賴的剔除和更靈活的宿主機擴縮容,轉轉運維開始規劃全新的日志采集系統以適應云原生時代的需求。
由于轉轉容器默認會將日志目錄掛載到宿主機,開源通用的文本文件采集方案無法將 pod 元數據信息附加到日志中,所以轉轉運維依托于 filebeat 自研了一個 filebeat 的 “助手” --- fb-advisor
3.1 轉轉方案(hostPath volume場景) fb-advisor
轉轉日志采集方案
受益于轉轉內部的容器規范,不管容器的日志是否需要采集,容器的日志目錄都是以 hostPath 機制掛載到宿主機目錄上的。fb-advisor 為轉轉自研組件,watch kube-apiserver 的 pod api,實時接收本節點的 pod 事件。如果為新增 pod 事件,則讀取 pod 元數據信息,識別 pod 中日志目錄掛載的宿主機路徑,將其保存在 filebeat 的配置文件,放在 config.d 目錄下。filebeat 配置自動 reload 即可。
日志采集后,集中生產到 kafka 中間件,再由自研的消費者將日志處理后完成數據的分發,從而替換掉 scribe + flume “黃金組合”。
以下為與 ByteCompass 方案的對比
fb-advisor vs bytecompass
3.2 通用方案(hostPath volume場景)
該通用方案同時適用于 hostPath volume 場景和容器內默認文件系統場景的文本文件日志的采集,并同時附加 pod 元數據信息。
filebeat 中的 add_kubernetes_metadata processor,是專門用來給日志附加 pod 元數據信息用的插件。
- in_cluster: 是否運行在容器環境中
- host: 主機名
- kube_config: kubeconfig 文件絕對路徑
- namespace: 監聽的命名空間,如果不寫,默認監聽所有命名空間
- default_indexers.enabled: 禁用默認的 indexers
- default_matchers.enabled: 禁用默認的 matchers
- sync_period: 指定列出歷史資源的超時時間
- indexers: 使用 pod 元數據為每個 pod 創建唯一標識符
- indexers.pod_uid: 使用 pod 的 UID 標識 pod 元數據
- matchers: 構造與索引創建的標識符匹配的查找鍵
- matchers.logs_path: 使用從存儲在該字段中的日志路徑中提取的標識符查找 pod 元數據
- matchers.logs_path.logs_path: k8s 數據目錄絕對路徑
- matchers.logs_path.resource_type: 根據 pod UID 為查找鍵進行查找
該通用方案中,add_kubernetes_metadata 負責連接 kube-apiserver 獲取元數據信息,并在日志采集路徑中 /var/lib/kubelet/pods/<pod UID>/volumes/<volume name>/... 提取 pod UID 信息,并以此為鍵,進行元數據查找,找到元數據后,將其元數據信息附加到日志條目中。
3.3 對比
對比轉轉方案和通用方案,主要區別在于轉轉方案的定制化程度更高,可以自由選擇需要附加的元數據信息,而通用方案默認會附加上容器所有的 label 信息。
從日志采集安全性來說,轉轉方案也略勝一籌,轉轉利用日志目錄掛載到宿主機的特性,將 filebeat 的日志采集路徑直接指向宿主機路徑。這樣的日志采集,脫離了 pod 數據目錄跟隨 pod 生命周期的特點,避免由于某些問題導致日志采集速率嚴重低于日志產出速率,且 pod 被重新調度后,數據目錄被清理而導致的日志數據丟失。
4 總結
云原生時代的日志采集方案百花齊放,沒有絕對通用的解決方案,沒有絕對完美的解決方案,只有依據自身實際特點,最合適的解決方案,希望本篇文章能帶給讀者關于日志采集方案中的一些不同思路。
轉轉的日志采集從裸金屬時代的 scribe + flume,到容器時代的 log-pilot + flume + scribe + flume,再到 ByteCompass + scribe + flume,最后到云原生時代的 filebeat + fb-advisor,徹底擺脫了裸金屬時代日志采集的影子,并且脫離了 dockerd 的依賴,開始朝著更加云原生的方向繼續披荊斬棘。
本篇文章僅介紹了日志采集的宏觀 workflow,內部細節有其內部特殊性,無法一一展現,歡迎留言進行深入的細節討論。
關于作者
呂瑞,轉轉運維,主要負責轉轉容器技術方向