Docker日誌收集最佳實踐

傳統日誌處理linux

說到日誌,咱們之前處理日誌的方式以下:json

· 日誌寫到本機磁盤上後端

· 一般僅用於排查線上問題,不多用於數據分析tomcat

·須要時登陸到機器上,用grep、awk等工具分析app

 

那麼,這種方式有什麼缺點呢?框架

 

第一,   它的效率很是低,由於每一次要排查問題的時候都要登到機器上去,當有幾十臺或者是上百臺機器的時候,每一臺機器去登錄這是一個沒辦法接受的事情,可能一臺機器浪費兩分鐘,整個幾小時就過去了。elasticsearch

 

第二,   若是要進行一些比較複雜的分析,像grep、awk兩個簡單的命令不可以知足需求時,就須要運行一些比較複雜的程序進行分析。分佈式

 

第三,   日誌自己它的價值不光在於排查一些系統問題上面,可能在一些數據的分析上,可能利用日誌來作一些用戶的決策,這也是它的價值,若是不能把它利用起來,價值就不能充分的發揮出來。工具

 

因此,如今不少公司會採用集中式日誌收集的日誌處理方式,咱們會把日誌分佈式收集,集中來存儲,咱們會在全部機器上面把日誌都收集起到一箇中心,在中內心面作一個日誌全文索引搜索,能夠經過一個界面去查詢,同時這個日誌系統後端能夠對接一些更復雜的數據處理系統,能夠對接監控、報警系統,對接數據挖掘數據分析系統,充分發揮日誌的價值。性能

 

Docker的日誌處理

 

使用過Docker的人尤爲是使用過容器編排系統,好比說咱們的容器服務,可能已經注意到這樣的一些特色:

 

容器編排跟傳統的佈置方式是不同的,在容器編排裏面,資源分配應用跑到哪臺機器上面的決策是由容器層來作的,因此你事先不知道你的容器應用會跑到哪臺機器上面;還有自動伸縮,根據負載自動增長或者減小容器數量;另外,在整個運行過程當中,系統發生一些狀況時,好比說你的容器宕掉了,容器服務會自動把容器應用遷到其餘的機器上去,整個過程很是動態,若是像傳統方式去配製日誌的收集工具,從一臺機器上面收集某一個應用,在這個動態下面,很難用原來的方式去配置。

 

基於這些特色,在Docker的日誌裏面, 咱們只可以採用中心化的日誌收集方案,你已經沒辦法再像原來登到一臺機器上面去看它的日誌是什麼,由於你不知道它其實在哪一個機器上面。

 

stdout和文件日誌

 

Docker的日誌咱們能夠把它分紅兩類,一類是stdout標準輸出,另一類是文件日誌。stdout是寫在標準輸出裏面的日誌,好比你在程序裏面,經過print或者echo來輸出的時候,這種輸出標準在linux上面實際上是往一個ID爲零的文件表述書裏面去寫;另外的就是文件日誌,文件日誌就是寫在磁盤上的日誌,通常來講咱們會在傳統的應用裏面會用得多一些。

 

stdout

 

在Docker的場景裏面,目前比較推崇這種標準輸出的日誌,標準輸出日誌具體過程如圖。標準輸出日誌的原理在於,當在啓動進程的時候,進程之間有一個父子關係,父進程能夠拿到子進程的標準輸出。拿到子進程標準輸出的後,父進程能夠對標準輸出作全部但願的處理。

例如,咱們經過exec.Command啓動了一個命令,帶一些參數,而後就能夠經過標準的pipeline拿到標準輸出,後面就能夠拿到程序運行過程當中產生標準輸出。 Docker也是用這個原理來拿的,全部的容器經過Docker Daemon啓動,實際上屬於Docker的一個子進程, 它能夠拿到你的容器裏面進程的標準輸出,而後拿到標準輸出以後,會經過它自身的一個叫作LogDriver的模塊來處理,LogDriver就是Docker用來處理容器標準輸出的一個模塊。 Docker支持不少種不一樣的處理方式,好比你的標準輸出以後,在某一種狀況下會把它寫到一個日誌裏面,Docker默認的JSON File日誌,除此以外,Docker還能夠把它發送到syslog裏面,或者是發送到journald裏面去,或者是gelf的一個系統。

 

怎麼配置log driver呢?

 

用Docker來啓動容器的話,你有兩種方式來配置LogDriver:

 

第一種方式是在Daemon上配置,對全部的容器生效。你配置以後,全部的容器啓動,若是沒有額外的其餘配製,默認狀況下就會把全部容器標準輸出所有都發送給Syslog服務,這樣就能夠在這個Syslog服務上面收集這臺機器上的全部容器的標準輸出;

第二種方式是在容器上配置,只對當前容器生效。若是你但願這個配置只對一個容器生效,不但願全部容器都受到影響,你能夠在容器上面配置。啓動一個容器,單獨配置它自身使用的logdriver。

其實Docker以前已經支持了不少的logdriver,圖中列表是直接從Docker的官方文檔上面拿到的。

 

文件日誌

 

對於stdout的這種日誌,在Docker裏面如今處理起來仍是比較方便的,若是沒有現成Logdriver的也能夠本身實現一個,可是對於文件日誌處理起來就沒有這麼簡單了。若是在一個容器裏面寫了日誌,文件位於容器內部,從宿主機上沒法訪問,的確你是能夠根據Docker用的devicemapper、overlayfs訪問到它裏面的一個文件,可是這種方式跟Docker的實現機制是有關係的,未來它若是改變,你的方案就失效了;另外,容器運行很是動態,日誌收集程序難以配置,若是有一個日誌收集的程序,在機器上面配置要收集哪一個文件,它的格式是什麼樣子的、發送到哪兒?由於一臺機器上面容器是一直在動態變的,它隨時可能在增長一個或者刪除一個,事先你並不知道這臺機器上會跑了多少個容器,他們的配置是怎麼樣子的,他們的日誌是寫在哪兒的,因此沒辦法預先在一臺機器上面把這個採集程序配好,這就是文件收集比較難的兩個地方。

 

最簡單的一個方案,給每一個容器弄一個日誌採集進程,這個進程跑到容器裏面,就能夠解決以上的兩個問題,第一由於它跑到容器裏面,就能夠訪問到容器裏面全部的文件,包括日誌文件;第二它跟容器在一塊兒,當容器啓動的時候,收集日誌的進程也啓動了,當容器銷燬的時候,進程也就被銷燬掉了。

 

這個方案很是簡單,可是其實會有不少的缺點:

 

第一,   由於每一個容器都有一個日誌的進程,意味着你的機器上面有100個容器,就須要啓動一百個日誌設備的程序,資源的浪費很是厲害。

 

第二,   在作鏡像的時候,須要把容器裏面日誌採集程序作到鏡像裏面去,對你的鏡像實際上是有入侵的,爲了日誌採集,不得不把本身的日誌程序再作個新鏡像,而後把東西放進去,因此對你的鏡像過程是有入侵性的。

 

第三,   當一個容器裏面好多個進程的時候,對於容器的資源管理,會干擾你對容器的資源使用的判斷,包括對於在作資源分配和監控的時候,都會有一些這樣的干擾。

 

fluentd-pilot

 

在容器服務上面,咱們新開發了一個工具,稱之爲fluentd-pilot。

 

fluentd-pilot是一個開源的日誌採集工具,適合直接在一臺機器上面跑單個進程模式。fluentd-pilot有這樣的一些特色:

 

· 一個單獨fluentd進程,收集機器上全部容器的日誌。不須要爲每一個容器啓動一個fluentd進程;

 

· 聲明式配置。使用label聲明要收集的日誌文件的路徑;

 

· 支持文件和stdout;

 

· 支持多種後端存儲:elasticsearch, 阿里雲日誌服務, graylog2…

 

具體是怎麼作呢?如圖,這是一個簡單的結構,在Docker宿主機上面部署一個fluentd-pilot容器,而後在容器裏面啓動的時候,咱們要聲明容器的日誌信息,fluentd-pilot會自動感知全部容器的配置。每次啓動容器或者刪除容器的時候,它可以看獲得,當看到容器有新容器產生以後,它就會自動給新容器按照你的配置生成對應的配置文件,而後去採集,最後採集回來的日誌一樣也會根據配置發送到後端存儲裏面去,這裏面後端主要指的elasticsearch或者是SLS這樣的系統,接下來你能夠在這個系統上面用一些工具來查詢等等。整個這一塊在Docker宿主機上面,外面的就是外部系統,由這兩個部分來組成。

 

咱們既然要用fluentd-pilot,就得先把它啓動起來。還要有一個日誌系統,日誌要集中收集,必然要有一箇中間服務去收集和存儲,因此要先把這種東西準備好,而後咱們在每個收集日誌的機器上面部署一個fluentd-pilot,用這個命令來部署,其實如今它是一個標準的Docker鏡像,內部支持一些後端存儲,能夠經過環境變量來指定日誌放到哪兒去,這樣的配置方式會把全部的收集到的日誌所有都發送到elasticsearch裏面去,固然兩個管掛載是須要的,由於它鏈接Docker,要感知到Docker裏面全部容器的變化,它要經過這種方式來訪問宿主機的一些信息。

配置好以後啓動應用,咱們看應用上面要收集的日誌,我該在上面作什麼樣的聲明?關鍵的配置有兩個,一是label catalina,聲明的時候要收集容器的日誌,全部的名字均可以;二是聲明access,這也是個名字,均可以用你喜歡的名字。這樣一個路徑的地址,當你經過這樣的配置來去啓動fluentd-pilot容器以後,它就可以感受到這樣一個容器的啓動事件,它會去看容器的配置是什麼,要收集這個目錄下面的文件日誌,而後告訴fluentd-pilot去中心配置而且去採集,這裏有一個-V,實際上跟Logs是一致的,在容器外面實際上沒有一種通用的方式可以獲取到容器裏面的文件,全部咱們主動把目錄從宿主機上掛載進來,這樣就能夠在宿主機上看到目錄下面全部的東西。

 

除了最簡單的場景以外,你的日誌可能會有一些更復雜的特性,好比你的日誌格式是什麼樣子,你可能但願在收集以後加一些內容,便於搜索,當你在真用的時候,它不光是一個很是簡單的容器,它可能屬於某一個業務或者屬於某一個應用,那麼,你但願在收集的時候可以有一些關聯信息,因此你能夠指定日誌格式是什麼樣子,而後能夠在日誌裏添加tag,這些tag至關於一些關鍵信息,能夠附加任何須要的關聯信息,這樣未來在搜索的時候能夠更方便的把這些日誌聚在一塊;並且,它能夠指定不少的後端,fluetnd-pilot支持多種後端,使用環境變量FLUENTD_OUTPUT指定後端類型。

 

fluent-pilot已經開源,若是功能不知足需求,能夠本身定製,本身修改代碼實現須要的功能。它的結構比較簡單,有這樣幾個模塊:

 

最上層是容器事件管理,這一塊跟Docker進行交互,它會感知Docker的建立容器,而後作出相應的生成配置或者清理配置上的事情;解析容器label跟容器配置,當你建立一個新容器以後,就會用這個模塊拿到新容器的配置,而後生成對應的配置文件;FluentdController主要是用來維護對應進程,包括控制何時加載新配置,而後檢測一些健康狀態等等;再下面就是Fluentd的一些插件,若是你須要增長一些日誌的後端,就能夠本身實現一些插件,放在這個裏面,而後再生成跟對應的插件相關的一些配置。   

 

fleuntd-pilot+阿里雲容器服務

 

以上是fleuntd-pilot自己的一些能力,如今你能夠在任何地方使用它,可是在容器服務上面咱們針對它作了一些更加靈活方便、更酷的一些事情,容器服務爲fluentd-pilot進行優化:

第一,   自動識別aliyun.logs標籤,並建立Volume;

第二,   從新部署,新容器自動複用已有的Volume,避免日誌丟失。

 

原生支持SLS

 

容器服務有一個很棒的特色,它會跟其餘的雲產品作一些很是方便的集成,這對於用戶來講,在使用容器服務的時候,雲產品可以更加方便的使用。好比說在日誌方面,阿里雲容器服務專爲SLS作了優化,讓用戶更簡單的在容器服務上使用SLS。SLS是阿里雲提供的日誌服務,性能強悍,使用方便,還能夠對接ODPS等數據系統;支撐1W臺物理機,一天12TB日誌數據,IOPS>= 2W,採集平均<1 S;單機:在1個CPU core狀況下,能夠實時採集15-18MB/S  日誌量;若是配置中增長能夠用線程數目,可水平擴展;是阿里雲環境下的最佳日誌方案。

 

優化優勢具體體如今:自動建立sls的project, logstore;同時支持stdout和文件日誌,使用一樣的方式配置。

 

容器服務日誌方案

 

好比在容器服務上面佈一個tomcat,可能會寫如圖的一個標準Docker的模板。  

 

當你經過部署以後,就能夠在日誌服務上面看到會生成兩個東西,都是建立好的,加一些前綴來區分,不用管一些配置,你惟一要作的事是什麼呢?點日誌索引查詢,而後到日誌搜索界面,剛纔啓動的時候一些日誌,能夠看到從哪過來的,這條日誌的內容是什麼,這些信息都已經很快的出現了,包括須要檢索能夠選中一個時間段,輸入關健詞去作一些搜索,自動在日誌服務上建立並配置logstore。

 

咱們在容器服務上面作到了對於文件日誌的收集,而且方式也都很是簡單,都是你能夠設立一個label,經過label方式能夠收集到全部的日誌。

 

日誌存儲方案

 

最後簡單的介紹幾種日誌存儲方案的對比,圖爲如今比較流行的日誌方案Elasticsearch,它自己並不提供界面,ELK中的E,基於Lucene,主要用於日誌索引、存儲和分析;一般配合Kibana展現日誌,免費,支持集羣模式,能夠搭一個Docker用的生產環境可用的系統。

接下來是graylog2,目前不算很流行,可是也是功能很強大的系統,它不像Elasticsearch還須要配合其它去使用,它自身擁有日誌存儲、索引以及展現全部的功能,都在一個系統裏面實現,它能夠設置一些報警規則,當日志裏面出現一些關鍵字的時候自動報警,這個功能仍是很是有用的,免費、支持集羣模式,能夠在生產環境裏面搭一個Docker用的生產系統。

阿里雲的日誌服務SLS特色以下:

· 阿里雲託管,不須要本身維護

· 支持多用戶和權限管理

· 能夠對接ODPS等系統

· 支撐1W臺物理機,一天12TB日誌數據,IOPS>= 2W,採集平均<1 S;單機:在1個CPU core狀況下,能夠實時採集15-18MB/S  日誌量;若是配置中增長能夠用線程數目,可水平擴展

 

用正確的方式寫日誌

 

那麼,咱們怎麼樣去收集日誌、存儲日誌,用什麼樣的系統,日誌的源頭和寫日誌咱們又該怎麼來作,有這樣幾個建議:

 

1.  選擇合適的日誌框架,不要直接print;

2.  爲每一條日誌選擇正確的level,該debug的不要用info;

3.  附加更多的上下文信息;

4.  使用json、csv等日誌格式,方便工具解析;

5.  儘可能不要使用多行日誌(Java Exception Stack)。

 

       (--轉載 :雲棲社區--)

相關文章
相關標籤/搜索