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