基于 Golang 的云原生日志采集服務(wù)設(shè)計與實踐

- 背景 -
在這股技術(shù)潮流之中,網(wǎng)易推出了輕舟微服務(wù)云平臺,集成了微服務(wù)、Servicemesh、容器云、DevOps等,已經(jīng)廣泛應(yīng)用于公司集團(tuán)內(nèi)部,同時也支撐了很多外部客戶的云原生化改造和遷移。

但是在云原生容器化環(huán)境下,日志的采集又變得有點不同。

- 容器日志采集的痛點 -
傳統(tǒng)主機模式
業(yè)務(wù)日志直接輸出到宿主機上,服務(wù)運行在固定的節(jié)點上,手動或者拿自動化工具把日志采集agent部署在節(jié)點上,加一下agent的配置,然后就可以開始采集日志了。同時為了方便后續(xù)的日志配置修改,還可以引入一個配置中心,用來下發(fā)agent配置。
Kubernetes環(huán)境
一個Kubernetes node節(jié)點上有很多不同服務(wù)的容器在運行,容器的日志存儲方式有很多不同的類型,例如stdout、hostPath、emptyDir、pv等。由于在Kubernetes集群中經(jīng)常存在Pod主動或者被動的遷移,頻繁的銷毀、創(chuàng)建,我們無法和傳統(tǒng)的方式一樣人為的給每個服務(wù)下發(fā)日志采集配置。另外,由于日志數(shù)據(jù)采集后會被集中存儲,所以查詢?nèi)罩緯r,可以根據(jù)namespace、pod、container、node,甚至包括容器的環(huán)境變量、label等維度來檢索、過濾很重要。
以上都是有別于傳統(tǒng)日志采集配置方式的需求和痛點,究其原因,還是因為傳統(tǒng)的方式脫離了Kubernetes,無法感知Kubernetes,更無法和Kubernetes集成。
隨著最近幾年的迅速發(fā)展,Kubernetes已經(jīng)成為容器編排的事實標(biāo)準(zhǔn),甚至可以被認(rèn)為是新一代的分布式操作系統(tǒng)。在這個新型的操作系統(tǒng)中,controller的設(shè)計思路驅(qū)動了整個系統(tǒng)的運行。controller的抽象解釋如下圖所示:

基于這個思路,對于日志采集來說,一個服務(wù)需要采集哪些日志,需要什么樣的日志配置,是用戶的期望,而這一切,就需要我們開發(fā)一個日志采集的controller去實現(xiàn)。


- 探索與架構(gòu)設(shè)計 -
日志采集agent選型
Logstash基于JVM,分分鐘內(nèi)存占用達(dá)到幾百MB甚至上GB,有點重,首先被我們排除。
Fluentd背靠CNCF看著不錯,各種插件也多,不過基于Ruby和C編寫,對于我們團(tuán)隊的技術(shù)棧來說,還是讓人止于觀望。
雖然Fluentd還推出了存粹基于C語言的Fluentd-bit項目,內(nèi)存占用很小,看著十分誘惑,但是使用C語言和不能動態(tài)reload配置,還是無法令人親近。
Loki推出的時間不久,目前還是功能有限,而且一些壓測數(shù)據(jù)表明性能不太好,暫持觀望。
Filebeat和Logstash、Kibana、Elasticsearch同屬Elastic公司,輕量級日志采集agent,推出就是為了替換Logstash,基于Golang編寫,和我們團(tuán)隊技術(shù)棧完美契合,實測下來個方面性能、資源占用率都比較優(yōu)秀,于是成為了我們?nèi)罩静杉痑gent第一選擇。
agent集成方式

- 整體架構(gòu) -
選擇Filebeat作為日志采集agent,集成了自研的日志controller后,從節(jié)點的視角,我們看到的架構(gòu)如下所示:

日志平臺下發(fā)具體的CRD實例到Kubernetes集群中,日志controller Ripple則負(fù)責(zé)從Kubernetes中List&Watch Pod和CRD實例。 通過Ripple的過濾、聚合最終生成一個Filebeat的input配置文件,配置文件里描述了服務(wù)的采集Path路徑、多行日志匹配等配置,同時還會默認(rèn)把例如PodName、Hostname等配置到日志元信息中。 Filebeat則根據(jù)Ripple生成的配置,自動reload并采集節(jié)點上的日志,發(fā)送至Kafka或者Elasticsearch等。
Ripple能感知到Pod掛載的日志Volume,不管是docker Stdout的日志,還是使用HostPath、EmptyDir、Pv存儲日志,均可以生成節(jié)點上的日志路徑,告知Filebeat去采集。
Ripple可以同時獲取CRD和Pod的信息,所以除了默認(rèn)給日志配置加上PodName等元信息外,還可以結(jié)合容器環(huán)境變量、Pod label、Pod Annotation等給日志打標(biāo),方便后續(xù)日志的過濾、檢索查詢。除此之外,我們還給Ripple加入了日志定時清理,確保日志不丟失等功能,進(jìn)一步增強了日志采集的功能和穩(wěn)定性。

- 基于 Filebeat 的實踐 -
功能擴展
Filebeat目前只提供了像elasticsearch、Kafka、logstash等幾類output客戶端,如果我們想要Filebeat直接發(fā)送至其他后端,需要定制化開發(fā)自己的output。同樣,如果需要對日志做過濾處理或者增加元信息,也可以自制processor插件。無論是增加output還是寫個processor,F(xiàn)ilebeat提供的大體思路基本相同。一般來講有3種方式:
直接fork Filebeat,在現(xiàn)有的源碼上開發(fā)。
output或者processor都提供了類似Run、Stop等的接口,只需要實現(xiàn)該類接口,然后在init方法中注冊相應(yīng)的插件初始化方法即可。
當(dāng)然,由于Golang中init方法是在import包時才被調(diào)用,所以需要在初始化Filebeat的代碼中手動import。
復(fù)制一份Filebeat的main.go,import我們自研的插件庫,然后重新編譯。
本質(zhì)上和方式1區(qū)別不大。
Filebeat還提供了基于Golang plugin的插件機制,需要把自研的插件編譯成.so共享鏈接庫,然后在Filebeat啟動參數(shù)中通過-plugin指定庫所在路徑。
不過實際上一方面Golang plugin還不夠成熟穩(wěn)定,一方面自研的插件依然需要依賴相同版本的libbeat庫,而且還需要相同的Golang版本編譯,坑可能更多,不太推薦。
如果想要了解更多關(guān)于Filebeat的設(shè)計,可以參考這篇文章。 (https://juejin.im/post/6844903888726786055)

- 立體化監(jiān)控 -
但是,真正的困難是在業(yè)務(wù)方實際使用之后,各種采集不到日志,多行日志配置或者采集二進(jìn)制大文件導(dǎo)致Filebeat oom等問題接踵而至。我們又投入了更多的時間在對Filebeat和日志采集的全方位監(jiān)控上,例如:
接入輕舟監(jiān)控平臺,有磁盤io、網(wǎng)絡(luò)流量傳輸、內(nèi)存占用、cpu使用、pod事件報警等,確保基礎(chǔ)監(jiān)控的完善。 加入了日志平臺數(shù)據(jù)全鏈路延遲監(jiān)控。 采集Filebeat自身日志,通過自身日志上報哪些日志文件開始采集,什么時候采集結(jié)束,避免每次都需要ssh到各種節(jié)點上查看日志配置排查問題。 自研Filebeat exporter,接入prometheus,采集上報自身metrics數(shù)據(jù)。

- Golang 的性能優(yōu)化與調(diào)優(yōu) -
從Docker到Kubernetes,從Istio到Knative,基于Golang的開源項目已然是云原生生態(tài)體系的主力軍,Golang的簡潔高效也不斷吸引著新的項目采用它作為開發(fā)語言。
但是很多時候,我們看過太多GC原理、內(nèi)存優(yōu)化、性能優(yōu)化,卻往往在寫完代碼、做完一個項目的時候,無從下手。 實踐是檢驗真理的唯一標(biāo)準(zhǔn)。 所以,親自動手去排查、摸索,才是提升姿勢水平、找到關(guān)鍵問題的捷徑。
對于性能優(yōu)化,Golang貼心的為我們提供了三把鑰匙:
go benchmark go pprof go trace
以sync.Pool為例,sync.Pool一般用于保存和復(fù)用臨時對象,減少內(nèi)存分配,降低GC壓力。有很多的應(yīng)用場景,例如號稱比Golang官方Http快10倍的FastHttp大量使用了sync.Pool,F(xiàn)ilebeat使用sync.Pool將批量日志數(shù)據(jù)聚合成Batch分批發(fā)送,Nginx-Ingress-controller渲染生成nginx配置時,也使用sync.Pool優(yōu)化渲染效率。我們的日志controller Ripple也同樣使用了sync.Pool去優(yōu)化渲染Filebeat配置時的性能。







- 總結(jié)與展望 -
來源:
blog.csdn.net/m0_38110132/article/details/81481454

