DevOps雲翼日誌服務實踐

京東科技開發者發表於2019-11-22

DevOps雲翼日誌服務實踐

10月30日,全球權威資料調研機構IDC正式釋出《IDCMarketScape: 中國DevOps雲市場2019,廠商評估》報告。京東雲憑藉豐富的場景和實踐能力,以及高質量的服務交付和平臺穩定性,取得優異的成績, 躋身“Major Players”(核心廠商)位置
京東雲DevOps能力起源於自身的業務實踐,針對京東集團的複雜業務場景打造並經受住多次618、11.11電商大促的嚴峻考驗,保證了高效高質的交付和對變化的靈活應對。能夠支援複雜場景的自動化運維需求、實現工具鏈產品與平臺化產品結合,幫助客戶根據不同的需求靈活定製方案。

前兩次的專題內容中,我們分別與大家分享了 大型企業級監控系統的設計以及 監控系統的可觀測性與資料儲存。今天,我們將透過介紹京東雲DevOps落地實踐,和大家繼續分享DevOps中另一個重要內容:日誌查詢服務。

日誌查詢服務,是構建軟體專案的基石之一,是系統穩定執行必不可少的一部分,已然成為DevOps中的標配選項。這裡,我們來聊一聊京東雲翼DevOps平臺的日誌查詢服務實踐。

本著客戶為先,全心全意為使用者服務的原則,雲翼日誌查詢服務的發展分以下幾個階段解決使用者的日誌需求:

場景一:使用者需要檢視自己的應用日誌,以此來判斷自己的應用程式當前執行是否正常,或者在遇到問題時,需要透過檢視應用輸出的日誌資訊來定位問題。

針對使用者的這個需求,我們開發並提供了 現場日誌查詢功能

何為現場日誌?就是案發現場的日誌。案發現場一般在哪裡呢?當然是使用者應用部署所在的主機了。

我們提供現場日誌查詢的功能,用於查詢使用者主機上的應用日誌。該功能預設支援規範目錄下的日誌查詢,且支援擴充套件的自定義路徑。

  • 規範目錄 /export/Logs/$appName/$instanceName/ ,在使用者主機這個目錄下的日誌檔案,會自動列到頁面,使用者選擇要查詢的檔案進行查詢即可。 $appName  代表使用者的應用名稱; $instanceName  代表應用部署的例項名稱。

  • 使用者自定義路徑舉例 /export/test.log ,由於這個路徑對我們系統來講是“不規範”的,使用者如果需要查這個日誌資訊,就需要自己手動輸入該日誌路徑,然後再執行查詢操作。

DevOps雲翼日誌服務實踐

現場日誌查詢檔案選擇示例圖

如何實現現場日誌查詢功能

想想一般我們自己要檢視主機上的日誌是怎麼做的呢?第一步往往是ssh登入到主機,然後透過 grep 命令查詢指定內容。是的,我們的現場日誌就是將這一過程進行了平臺化,使用者在現場日誌頁面上選擇要查詢的日誌檔案,輸入要查詢的關鍵字,點查詢按鈕即可。出於安全性考慮,ssh認證我們採用金鑰認證而非密碼認證。當然了,既然透過ssh連線,那就要求使用者主機必須開放22埠。

現場日誌透過ssh查詢遇到的問題

比如有的使用者的主機是在VPC裡的,ssh直接訪問不到,怎麼辦呢?想想辦法這個問題是可以解決的,那就是配置代理,這樣就導致漸漸地要維護一堆的代理配置。

改進措施

隨著雲翼內部新的控制系統zero的出現(zero是一套控制系統,透過給使用者主機上的zero-agent下發任務實現對使用者主機的一些操作),現場日誌查詢有了新的實現方式,可以透過呼叫控制系統API,用控制系統下發任務的方式來實現日誌查詢,這樣採用http的連線方式替代之前的ssh,不再依賴金鑰,也不再需要再維護一堆的ssh代理配置了。嗯,感覺一下清爽了好多。

新的困境

改變實現方式後,發現一個新的問題,就是使用者單條日誌太大的情況下,查詢資料量如果超過zero-agent一次傳輸資料量的限制會導致查詢失敗,這裡就需要做個權衡了,要麼使用者調整日誌長度,要麼減小一頁的資料展示條數,再要麼可以考慮換一種查詢方式,比如用下面將要介紹的歷史日誌查詢,當然了,這只是權宜之計,歷史日誌功能並不是為了解決這個問題才產生的。


場景二:使用者的應用部署在多臺機器上,使用者需要對多臺機器上的日誌進行集中檢索,且做日誌檢索時不希望消耗自己機器上的資源(比如頻寬、記憶體、CPU)。

為此,雲翼的 歷史日誌查詢功能應運而生。我們期望歷史日誌支援最近7天的日誌檢索。

既然要集中檢索,那我們首先需要及時把日誌資料採集走,進行集中儲存。這裡需要使用者做一個日誌訂閱的操作,其實就是告訴日誌服務要採集哪個應用下的哪個日誌檔案的資料。

日誌資料流向圖:

DevOps雲翼日誌服務實踐

上圖反映了使用者訂閱後,使用者日誌資料的流向情況。可以看到資料儲存涉及兩種介質,一種是kafka,一種是ES,資料先快取到kafka,最終流向ES。ElasticSearch簡稱ES,是一個開源的分散式搜尋引擎,我們的歷史日誌查詢功能正是藉助於ES強大的搜尋能力實現的。

下面依次介紹一下上圖中的log-agent、fwd和indexer模組。

  • log-agent ,是雲翼的日誌採集客戶端,部署在使用者的應用主機上。它可以動態發現使用者的訂閱資訊,實時採集日誌資料並將資料上報給fwd模組。log-agent內部封裝了rsyslog,透過控制rsyslog的配置以及程式的啟停來實現對使用者日誌的採集。rsyslog是linux上一款比較成熟的系統日誌採集工具,我們拿來採集應用級別的日誌,當然也是可以的。

  • fwd ,這個模組負責接收log-agent上報的資料,並轉發至kafka。它的價值在於解耦了log-agent和kafka,避免了成千上萬的主機和kafka直連;當kafka有變動的時候,我們只給有限的幾臺fwd做修改和升級即可,不需要對所有的log-agent做統一的升級了。


  • indexer ,該模組可以被看作一個資料搬運工,負責把日誌資料從kafka搬到ES。indexer的本質是rsyslog,它的輸入是kafka,輸出是ES。是不是發現rsyslog很強大?這個模組雖然簡單,但很重要。曾經一度令人特別頭疼的是它經常罷工,要麼吃記憶體,要麼假死不幹活。它不幹活,ES就得眼巴巴等資料而不得,ES沒資料,歷史日誌就查不出內容,這個問題簡直太嚴重了。經過反覆排查分析,最終發現是由於action佇列裡的訊息出隊太慢導致的,在對rsyslog的佇列配置反覆做了幾次調整後,這傢伙終於肯乖乖幹活了,好開心。有時候並不是現成的工具不好用,而是我們不會用。

ES索引介紹

ES儲存離不開索引,最初我們的索引是按照天的粒度來建立的,一天一個索引,例如: index-log-2019-10-21 。但是隨著日誌量的增加,按天索引,每次查詢時,搜尋範圍太大,會導致一次查詢特別慢,使用者體驗非常不好。為了提升查詢效率,後來就把索引改成了小時粒度,例如: index-log-2019-10-21-13

索引時間如何確定

看完ES索引介紹,有人可能會有疑惑,既然是按時間索引,這個時間具體是怎麼取的呢?從使用者的日誌訊息中解析的嗎?不是的。使用者的日誌,時間格式各不相同,從使用者日誌中解析時間顯然是不現實的。

難道是按照當前的搬運時間來確定索引?這樣的話,在資料處理不及時,kafka訊息有積壓的情況下,使用者日誌中的時間和索引的時間就很可能不一致了呀,比如15點的資料,可能會放到16點的索引中,這樣在搜尋15點的資料的時候是搜不到期望的資料的。

這裡要說明一下,我們log-agent採集的每條資料,除了日誌內容外,都會帶有一些元資訊,比如部門名稱、應用名、日誌檔案路徑,time時間戳等,這裡的時間戳記錄的是日誌採集時的時間,由於是實時採集,這個時間和使用者應用日誌中的時間可以看作是幾乎相等的。在索引資料前,先解析出time時間戳,透過這個時間戳來確定具體的索引。這樣即使在kafka訊息有積壓的情況下,也能保證日誌資料可以正確存放到期望的索引中。

DevOps雲翼日誌服務實踐

歷史日誌查詢示例圖

歷史日誌面臨的問題

隨著日誌量的增多,有一個比較尷尬的問題,就是ES儲存資源會出現不足的情況。這是一個需要我們和使用者一起努力來解決的問題。


場景三:有的使用者覺得自己應用的日誌比較重要,希望能夠長久保留,比如三個月、半年……當突然需要某天的資料了,可以透過日誌服務將資料檔案下載下來進行檢視。

針對這個使用者需求,我們的做法是將使用者的日誌按照日期進行儲存,然後在前端頁面提供日誌下載功能,供使用者根據需要進行查詢和下載指定日期的的日誌檔案。這裡我們抽象出的功能叫 日誌下載

日誌下載功能的實現思路

日誌下載的前提和核心是將零散的日誌資訊合併到檔案進行長久儲存。

之前我們將採集到的資料存放到了kafka,資料來源有了,接下來就是把資料拉下來進行合併儲存的問題了。對,期初我們選擇的儲存介質是HDFS(ES是檢索利器,且儲存成本太高,用做長久儲存顯然是不現實的)。

為此,我們寫了一個Spark job的程式,起了一個consumerGroup從kafka消費資料,由於對實時性要求不高,我們用Spark Streaming的方式,每隔兩分鐘,進行一次資料拉取,然後進行離線計算。由於一條訊息的後設資料中包含採集時間戳和日誌路徑,我們很容易確定一條日誌該追加到哪個HDFS檔案中。最終透過httpfs從hdfs下載日誌檔案。

DevOps雲翼日誌服務實踐

用HDFS作為儲存,隨著日誌量的增加,資源不足的問題便呈現出來了。最終,我們把儲存目標鎖定到了京東雲的物件儲存OSS。當然了,初期的將資料計算後儲存到HDFS的工作還是很有用的,接下來的工作就是把HDFS上的檔案下載匯入到OSS,然後生成OSS下載連結提供給使用者就好了。這樣HDFS相當於中轉的作用,檔案不需要保留太久,只要確定資料已經轉存到OSS,HDFS上的檔案就可以刪除了,這樣大大緩解了HDFS的儲存壓力。

日誌轉存(HDFS->OSS)遇到的問題及解決辦法

在做日誌轉存至OSS的時候,我們遇到一個問題,比如使用者的日誌檔案比較大,使用者可能在自己的主機上做了日誌切割,但是由於我們把資料採集後,變成了kafka中一條條的日誌訊息,我們相當於再把這一條條的日誌訊息重新合併到一個HDFS檔案中。把一天的日誌合到一個檔案進行儲存,有的應用日誌列印比較頻繁的話,最終合成的這個檔案就會比較大,有的甚至超過了100G,這樣不管是從HDFS進行下載和還是壓縮上傳至OSS操作都會比較耗時,而且磁碟空間佔用也比較多。對於使用者來說,下載一個大檔案進行處理也會是一件比較頭疼的事情。

為了解決這個問題,我們調整了spark job處理邏輯,實現了HDFS檔案切割,確保單個HDFS檔案大小不超過1G。這樣一個大檔案就被拆分成了多個小檔案。對多個小檔案進行併發轉存,這樣整體效率就大大提升了。壓縮後的檔案,一般不超過300MB,這樣使用者下載也會快很多。

DevOps雲翼日誌服務實踐

日誌下載功能示例圖

OSS做持久化儲存後,有一個缺點,就是由於需要轉存,無法實時下載當天的日誌,不過這並不是一個特別急迫的問題,因為當天的日誌完全可以透過前面介紹的現場日誌查詢或歷史日誌查詢功能來進行檢索檢視。


場景四:特定儲存需求 - 使用者說,我的日誌資料不想交給你做集中儲存,我想自己儲存,然後用來做分析,你幫我收集到指定地方就好了。

這確實是比較典型的使用者需求,為了滿足使用者的這個需求,我們開發了 自定義日誌目的地的功能。

自定義日誌目的地,顧名思義,就是讓使用者自己來指定將日誌存放到哪裡,然後使用者在做訂閱操作的時候,指定這個目的地名稱即可。

目前支援的日誌目的地有兩種型別:fwd和kafka。

  • fwd 型別,要求提供目的地服務的域名和埠號,且目的地服務支援RELP協議,RELP是一種比TCP更可靠的傳輸協議。

  • kafka型別,需要指定kafka的broker和topic。

從使用情況來看,目前kafka型別的日誌目的地佔絕大多數。


至此,雲翼日誌服務的幾個主要功能就介紹完了。從整個過程看,日誌服務是連線運維和開發之間很好的橋樑,日誌中幾乎包含了運維和開發所關心的一切,也完整呈現出了應用程式線上上真實的執行情況。雲翼的現場日誌查詢、歷史日誌查詢、日誌下載、自定義日誌目的地這四個功能互相補充,可以滿足使用者在不同場景下的使用訴求。

目前京東雲監控提供免費服務,點選【 閱讀 】,瞭解更多關於京東雲監控的內容。
歡迎點選“ 京東雲 ”瞭解更多精彩內容


DevOps雲翼日誌服務實踐

DevOps雲翼日誌服務實踐


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912185/viewspace-2665348/,如需轉載,請註明出處,否則將追究法律責任。

相關文章