翟雅榮,于金剛
1(中國(guó)科學(xué)院大學(xué),北京 100049)
2(中國(guó)科學(xué)院 沈陽(yáng)計(jì)算技術(shù)研究所,沈陽(yáng) 110168)
日志是記錄系統(tǒng)行為的一種方式,具有非常重要的作用.日志信息可作為系統(tǒng)排錯(cuò)和性能優(yōu)化的依據(jù);通過(guò)日志,可以有效的監(jiān)控系統(tǒng)的運(yùn)行狀況,如性能信息、故障檢測(cè)、入侵檢測(cè)等;日志可以用于用戶的行為信息分析,發(fā)現(xiàn)潛在商機(jī);日志可以幫助開發(fā)人員找到bug的來(lái)源,修復(fù)漏洞.并且隨著數(shù)據(jù)挖掘、大數(shù)據(jù)等技術(shù)的不斷發(fā)展,數(shù)據(jù)也愈發(fā)凸顯重要,日志作為數(shù)據(jù)分析的一大來(lái)源,日志收集分析系統(tǒng)也愈發(fā)凸顯重要.但隨著互聯(lián)網(wǎng)、大數(shù)據(jù)等快速發(fā)展,系統(tǒng)應(yīng)用越來(lái)越復(fù)雜,規(guī)模越來(lái)越大,系統(tǒng)產(chǎn)生的日志急劇增加[1],給日志的收集、存儲(chǔ)和分析帶來(lái)很多挑戰(zhàn).
傳統(tǒng)的日志存儲(chǔ)在本機(jī)磁盤上,查看日志時(shí)需要登陸到宿主機(jī)上,用grep等工具進(jìn)行查看分析,這種方式的效率極低,并且隨著機(jī)器數(shù)量的增多,排查問(wèn)題所花費(fèi)的時(shí)間隨之增加,并且這種方式很難進(jìn)行比較復(fù)雜的分析,不能充分利用起日志的價(jià)值.隨著Docker容器技術(shù)的不斷發(fā)展,Docker容器技術(shù)的應(yīng)用范圍也越來(lái)越廣.與傳統(tǒng)的主機(jī)、虛擬機(jī)技術(shù)相比,Docker容器產(chǎn)生的日志分散在不同相互隔離的容器中,并且事先并不知道容器應(yīng)用部署在哪一臺(tái)機(jī)器上,給日志的收集帶來(lái)一定的挑戰(zhàn),這也迫切需要一種方式來(lái)收集存儲(chǔ)日志.容器具有即用即銷的特點(diǎn),容器中的存儲(chǔ)會(huì)隨著容器的關(guān)閉而被刪除,雖然可以將日志文件掛載到宿主機(jī)上,但是容器會(huì)經(jīng)常漂移,給日志的統(tǒng)一查看帶來(lái)挑戰(zhàn).本文采用Kubernetes實(shí)現(xiàn)容器管理、服務(wù)發(fā)現(xiàn)及調(diào)度,使用主流的開源日志收集系統(tǒng)ELK實(shí)現(xiàn)日志的存儲(chǔ)、查看,并通過(guò)緩存技術(shù)Redis消息隊(duì)列提供可靠的數(shù)據(jù)傳輸,將分散在不同容器中的日志統(tǒng)一收集存儲(chǔ),提高運(yùn)維人員的工作效率.
Docker[2]是一個(gè)開源基于Linux操作系統(tǒng)虛擬化技術(shù)的高級(jí)容器引擎,可以將應(yīng)用及開發(fā)環(huán)境打包到一個(gè)可移植的容器中.為了避免啟動(dòng)和維護(hù)虛擬機(jī)的開銷,Docker使用Linux內(nèi)核資源隔離技術(shù)(如cgroups、namespace)、聯(lián)合文件系統(tǒng)(如aufs)等技術(shù)實(shí)現(xiàn)多個(gè)容器在一個(gè)Linux內(nèi)核中相互獨(dú)立[3].與傳統(tǒng)的虛擬機(jī)需要虛擬出一個(gè)完整的操作系統(tǒng)相比,Docker是一種細(xì)粒度、輕量級(jí)的虛擬化技術(shù),屬于操作系統(tǒng)級(jí)虛擬化.圖1顯示Docker容器技術(shù)與虛擬機(jī)的原理對(duì)比.
圖1 Docker容器與虛擬機(jī)的原理對(duì)比
Docker是秒級(jí)啟動(dòng),而虛擬機(jī)的啟動(dòng)速度是分鐘級(jí);Docker容器作為一種輕量級(jí)的虛擬技術(shù),其單機(jī)支持上千容器,而虛擬機(jī)由于需要虛擬出完整的操作系統(tǒng),單機(jī)一般只支持幾十個(gè);Docker資源利用率比虛擬機(jī)高,資源占用少[4].
Kubernetes(K8s)[5]是Goolge開源的軟件,提供了一個(gè)完備的分布式系統(tǒng)支撐平臺(tái),是Docker生態(tài)圈中的重要一員.它提供了強(qiáng)大的故障發(fā)現(xiàn)、負(fù)載均衡、自我修復(fù)、滾動(dòng)升級(jí)、資源調(diào)度管理、自動(dòng)擴(kuò)縮容等多個(gè)功能,具備的完善的集群管理的能力.并且其對(duì)現(xiàn)有的平臺(tái)侵入性較小,現(xiàn)有平臺(tái)容易升級(jí)改造遷移到Kubernetes上.
Kubernetes集群由 Master節(jié)點(diǎn)和Node節(jié)點(diǎn)組成,其中Master節(jié)點(diǎn)運(yùn)行集群管理方面的進(jìn)程(kubeapiserver、kuber-controller-manager和 kube-scheduler),負(fù)責(zé)實(shí)現(xiàn)整個(gè)集群的Pod調(diào)度、彈性伸縮、安全控制、資源管理等.Node節(jié)點(diǎn)是集群的工作節(jié)點(diǎn),主要負(fù)責(zé)運(yùn)行真正的應(yīng)用程序,通過(guò)運(yùn)行kublete、kubeproxy服務(wù)進(jìn)程,來(lái)負(fù)責(zé)Pod的創(chuàng)建、啟動(dòng)、監(jiān)控等,kube-proxy還提供了負(fù)載均衡.與傳統(tǒng)的容器相比,Pod是管理的最小運(yùn)行單元,而并非容器.圖2顯示Kubernetes的系統(tǒng)架構(gòu)圖.
目前,針對(duì)Kubernetes的日志收集提出了多種方案.Kubernetes官方推薦采用的方案是Flunetd +Elasticsearch + Kibana,通過(guò)使用DaemonSet的方式在每一個(gè)Node節(jié)點(diǎn)上啟動(dòng)一個(gè)Flunetd來(lái)收集日志文件(包括/var/log、/var/lib/docker/containers),常見的收集器還有Filebeat、Logstash;陳堅(jiān)娟等人[6]提出Logstash agent + Kafka + Logstash + Elasticsearch +Kibana結(jié)構(gòu),并將容器產(chǎn)生的日志掛載到宿主機(jī)的指定目錄上,通過(guò)Node上啟動(dòng)的Logstash agent 來(lái)收集指定目錄及/var/lib/docker目錄下的日志;羅東鋒等人[7]提出了基于Docker的大規(guī)模日志采集與分析系統(tǒng),主要使用Flunetd + Kafka + Flunetd + Elasticsearch +Kibana實(shí)現(xiàn)大規(guī)模日志采集;周德永等人[8]提出了在Node節(jié)點(diǎn)上部署Logspout收集日志,并Logstash Shipper轉(zhuǎn)發(fā)送容器日志,后轉(zhuǎn)發(fā)給Redis做緩沖,再有Logstash轉(zhuǎn)發(fā)至Elasticsearch進(jìn)行存儲(chǔ),Kibana進(jìn)行可視化.
Filebeat具有占用內(nèi)存較低,性價(jià)比較高的特點(diǎn),本文采用Filebeat作為日志文件的采集器,并針對(duì)兩種輸出方式的日志文件采用不同的收集方式,輸出到控制臺(tái)的日志文件,這類文件主要保存在/var/lib/docker/containers/目錄下,/var/log/container軟鏈接到該目錄下,該日志文件主要通過(guò)在Node節(jié)點(diǎn)上部署Filebeat進(jìn)行收集;未輸出到控制臺(tái)的日志文件,這類文件主要根據(jù)業(yè)務(wù)需求保存在不同的目錄下,并且日志文件的格式也不盡相同,此類日志文件通過(guò)在每一個(gè)Pod節(jié)點(diǎn)部署Filebeat來(lái)進(jìn)行日志收集,此方法可解決傳統(tǒng)日志文件通過(guò)掛載到宿主機(jī)上進(jìn)行收集時(shí)需要統(tǒng)一日志文件收集的規(guī)則、目錄和輸出方式的缺點(diǎn).
圖2 Kubernetes系統(tǒng)架構(gòu)
該系統(tǒng)的整個(gè)架構(gòu)(如圖3)從左到右共分為5層,第1層數(shù)據(jù)采集層,主要負(fù)責(zé)采集業(yè)務(wù)集群中的日志,并將日志發(fā)送給Redis服務(wù)中,采用的日志收集器為Filebeat;第2層為數(shù)據(jù)緩存層,該層使用Redis作為緩存;第3層為數(shù)據(jù)轉(zhuǎn)發(fā)層,該層主要負(fù)責(zé)去Redis集群拉數(shù)據(jù),轉(zhuǎn)發(fā)到Elasticsearch;第4層為數(shù)據(jù)存儲(chǔ)層,該層使用Elasticsearch把收到的數(shù)據(jù)進(jìn)行存儲(chǔ),寫入磁盤;第5層主要使用Kibana處理數(shù)據(jù)檢索請(qǐng)求,并進(jìn)行數(shù)據(jù)展示[7].
圖3 日志分析系統(tǒng)架構(gòu)圖
數(shù)據(jù)采集層主要負(fù)責(zé)采集各個(gè)服務(wù)器上不同的文件,進(jìn)行預(yù)處理后將數(shù)據(jù)傳送到數(shù)據(jù)緩存層.目前主流的采集器主要有Logstash、Fluentd、Filebeat,本文采用Filebeat作為主要的采集器,Filebeat相比與Logstash、Fluentd的內(nèi)存使用較低,性價(jià)比較高.
表1 Logstash、Fluentd、Filebeat對(duì)比
本文采用Kubernetes來(lái)實(shí)現(xiàn)容器管理、服務(wù)發(fā)現(xiàn)及調(diào)度,使用Filebeat作為采集器來(lái)采集日志文件.日志文件按照輸出的不同可以分為兩種:1)輸出到控制臺(tái)的日志文件.這類文件主要保存在/var/log/containers/目錄下;2)應(yīng)用日志(未輸出到控制臺(tái)的日志)輸出到指定文件下的文件.本文針對(duì)兩種不同的日志文件,使用不同的方式.如圖4為日志采集層.
圖4 日志采集層
輸出到控制臺(tái)的日志文件,這類文件都會(huì)保存在/var/lib/docker/containers/目錄下,以*-json.log的命名,/var/log/containers軟鏈接到該目錄下.該類日志文件主要使用每個(gè)Node節(jié)點(diǎn)上個(gè)運(yùn)行的一個(gè)Filebeat容器進(jìn)行日志采集,然后匯總到Redis緩存中.本文采用以DaemonSet的方式將Filebeat作為Kubernetes的一種資源對(duì)象運(yùn)行在Node節(jié)點(diǎn)上.
針對(duì)未輸出到控制臺(tái)的日志文件,這些文件主要存儲(chǔ)在容器中的指定目錄下,由于不同應(yīng)用產(chǎn)生的日志文件格式不同,位置不同,如果采用將Pod的日志掛載到宿主機(jī)上,進(jìn)行日志收集,需要統(tǒng)一日志收集規(guī)則、目錄和輸出方式,而各個(gè)文件各有不同,同時(shí)為了高擴(kuò)展性、方便維護(hù)和升級(jí),本文針對(duì)這類文件采用以每個(gè)Pod為單位進(jìn)行日志收集.用戶也可根據(jù)實(shí)際需求,來(lái)決定是否需要在Pod中使用Filebeat.
為了防止發(fā)送和接收速率不同而造成數(shù)據(jù)丟失問(wèn)題,在數(shù)據(jù)采集層和數(shù)據(jù)轉(zhuǎn)發(fā)層之間搭建了消息隊(duì)列,起到緩存作用.Redis[9]是一個(gè)開源、高性能、基于內(nèi)存的鍵值對(duì)數(shù)據(jù)庫(kù),支持?jǐn)?shù)據(jù)持久化和訂閱發(fā)布機(jī)制等高級(jí)特性,能夠滿足本系統(tǒng)的要求.為提高系統(tǒng)的性能和可靠性,該層使用Redis消息隊(duì)列作為緩存.
數(shù)據(jù)轉(zhuǎn)發(fā)層作為Redis隊(duì)列的消費(fèi)者,從Redis隊(duì)列中拉取消息并轉(zhuǎn)發(fā)到Elasticsearch數(shù)據(jù)存儲(chǔ)層進(jìn)行處理.本文采用Logstash實(shí)現(xiàn)日志的拉取、處理、轉(zhuǎn)發(fā).由于日志中存在字段不完整、格式不一致或者噪聲數(shù)據(jù),為了降低這些對(duì)數(shù)據(jù)存儲(chǔ)帶來(lái)的沖擊,同時(shí)提高數(shù)據(jù)的質(zhì)量,在數(shù)據(jù)轉(zhuǎn)發(fā)層需要對(duì)數(shù)據(jù)進(jìn)行預(yù)處理,使數(shù)據(jù)統(tǒng)一格式,過(guò)濾掉噪聲數(shù)據(jù)等.
輸出到控制臺(tái)的的日志文件,/var/log/containers/*-*-*_*_*.log代表的命名規(guī)則為:podName_namespace_deploymentName-containerID.log,針對(duì)日志文件名稱解析出deploymentName、podName、containerID、namespace字段,以下是Logstash部分配置信息:
數(shù)據(jù)存儲(chǔ)層使用Elasticsearch集群,數(shù)據(jù)轉(zhuǎn)發(fā)層將日志逐條插入到數(shù)據(jù)存儲(chǔ)層的Elasticsearch集群中.Elasticsearch[10]是一個(gè)實(shí)時(shí)分布式搜索和分析引擎,基于Apache Lucene(TM)的開源搜索引擎,使用Lucene作為實(shí)現(xiàn)所有索引和搜索的功能,它通過(guò)簡(jiǎn)單的RESTful API來(lái)隱藏Lucene的復(fù)雜性,使全文搜索變得簡(jiǎn)單.
Kibana是開源的數(shù)據(jù)分析和圖像化展示的平臺(tái).Kibana基于Apache License2.0 開源協(xié)議,可以對(duì)Elasticsearch索引中存儲(chǔ)的數(shù)據(jù)進(jìn)行搜索、分析、查看,可以進(jìn)行數(shù)據(jù)分析和統(tǒng)計(jì),并且可以繪制各種圖表展示結(jié)果.Kibana支持布爾運(yùn)算符、通配符和字段篩選進(jìn)行模糊匹配,并且其提供了Web界面,方便用戶查看結(jié)果.
本文重點(diǎn)驗(yàn)證系統(tǒng)整體的有效性.通過(guò)部署在同一局域網(wǎng)的5臺(tái)PC機(jī)搭建集群進(jìn)行測(cè)試.每臺(tái)PC機(jī)的硬件換件為主頻3.1 GHz的四核CPU、內(nèi)存4 GB、磁盤200 GB,軟件環(huán)境為CentOS 7.2(64 bit)、Elasticsearch 6.0.0、Kibana 6.0.0、Filebeat 6.0.0、Redis、Kubernetes 1.6.其中1臺(tái)作為Kubernetes的Master節(jié)點(diǎn),3臺(tái)作為Kubernetes的Node節(jié)點(diǎn),Kubernetes的集群部署信息如表2.圖5、圖6為實(shí)驗(yàn)結(jié)果.
表2 Kubernetes集群部署信息
圖5 未輸出到控制臺(tái)日志
本文將零散的日志統(tǒng)一收集存儲(chǔ),并采用Kubernetes實(shí)現(xiàn)容器管理、服務(wù)發(fā)現(xiàn)及調(diào)度,使用主流的開源日志收集系統(tǒng)ELK實(shí)現(xiàn)日志的存儲(chǔ)、查看,并通過(guò)緩存技術(shù)Redis消息隊(duì)列提供可靠的數(shù)據(jù)傳輸,提高運(yùn)維人員的工作效率.本系統(tǒng)可實(shí)現(xiàn)實(shí)時(shí)高效收集日志、處理分析,并進(jìn)行可視化展示.由于使用Kubernetes作為容器的管理工具,可實(shí)現(xiàn)快速部署、自動(dòng)擴(kuò)縮容、資源管理等.本系統(tǒng)不僅解決了日志的統(tǒng)一收集,針對(duì)不同的日志文件采用不同的收集策略,用戶靈活配置,同時(shí)也解決了容器的即用即銷造成的漂移問(wèn)題.下一步 工作將對(duì)采集到的日志進(jìn)行挖掘,發(fā)現(xiàn)有價(jià)值的信息.
圖6 輸出到控制臺(tái)日志