做者 | 元乙 阿里雲存儲服務技術專家html
導讀:近年來,愈來愈多的同窗諮詢如何爲 Kubernetes 構建一個日誌系統,或者是來求助在此過程當中遇到一系列問題如何解決,授人以魚不如授人以漁,因而做者想把這些年積累的經驗以文章的形式發出來,讓看到文章的同窗少走彎路。K8s 日誌系列文章內容偏向落地實操以及經驗分享,且內容會隨着技術的迭代而不按期更新,本文爲該系列文章的第 3 篇。python
第一篇:《6 個 K8s 日誌系統建設中的典型問題,你遇到過幾個?》nginx
第二篇:《一文看懂 K8s 日誌系統設計和實踐》git
在上一篇文章《一文看懂 K8s 日誌系統設計和實踐》中,主要和你們介紹從全局維度考慮如何去構建 K8s 中的日誌系統,本文咱們將從實踐角度出發來一步步構建 K8s 中的日誌監控體系。程序員
構建日誌系統的第一步是如何去產生這些日誌,而這也每每是最繁雜最困難的一步。github
2009 年阿里雲春節上班第一天,在北京一間連暖氣都沒有的辦公室裏,一幫工程師一邊口呼白氣,一邊敲出了「飛天」的第一行代碼。「飛天」做爲阿里雲的核心技術平臺,其英文名 Apsara——來自吳哥王朝的阿僕薩羅飛天仙女的名字。docker
阿里雲飛天系統的第一行代碼就是爲了編寫一個日誌系統,而如今 apsara logging 的日誌庫應用在飛天全部的系統中,包括盤古、女媧、伏羲、洛神...後端
一般日誌最基礎的做用是記錄程序的運行軌跡,在此之上會衍生出很是多的功能,例如線上監控、告警、運營分析、安全分析等等(詳情能夠參見第一篇文章《6 個 K8s 日誌系統建設中的典型問題,你遇到過幾個?》,這些功能反過來也對日誌具有必定的要求,咱們須要儘量的將日誌規範化,以減小收集、解析、分析的代價。緩存
在 Kubernetes 中,環境的動態性很強,日誌基本上都是易失的,所以須要實時將日誌採集到中心的存儲中,爲了配合日誌採集,對於日誌的輸出、採集會有更多的要求。安全
下述咱們列舉了 Kubernetes 中,日誌輸出的常見注意事項(其中標記 (*)的是 Kubernetes 中特有的項目):
日誌等級是用來區分日誌對應事件嚴重程度的說明,這是全部日誌中必須具有的一個選項。一般日誌會分爲 6 個不一樣的等級:
做爲程序員,必定要合理設置日誌等級,我的在開發過程當中總結了如下幾點經驗:
一般在沒有約束的狀況下,程序員的發揮天馬行空,各類日誌內容都會出現,這些只有開發本身才能看懂的日誌很難進行分析和告警。所以咱們須要一個日誌頂向下的規範來約束項目中的開發人員,讓全部的日誌看起來是一我的打印的並且是易於分析的。
日誌中一般必備的字段有:Time、Level、Location。對於特定模塊/流程/業務,還須要有一些 Common 的字段,例如:
日誌的字段規約最好由運維平臺/中間件平臺自頂向下推進,約束每一個模塊/流程的程序員按照規定打印日誌。
一般咱們建議使用 KeyValue 對形式的日誌格式,好比咱們阿里的飛天日誌庫採用的就是這種形式:
[2019-12-30 21:45:30.611992] [WARNING] [958] [block_writer.cpp:671] path:pangu://localcluster/index/3/prom/7/1577711464522767696_0_1577711517 min_time:1577712000000000 max_time:1577715600000000 normal_count:27595 config:prom start_line:57315569 end_line:57343195 latency(ms):42 type:AddBlock
KeyValue 對的日誌能夠徹底自解析且易於理解,同時便於日誌採集時自動解析。
另外推薦的是 JSON 日誌格式,支持以 JSON 格式輸出的日誌庫不少,並且大部分的日誌採集 Agent 都支持 JSON 格式的日誌收集。
{"addr":"tcp://0.0.0.0:10010","caller":"main.go:98","err":"listen tcp: address tcp://0.0.0.0:10010: too many colons in address","level":"error","msg":"Failed to listen","ts":"2019-03-08T10:02:47.469421Z"}
注意:絕大部分場景不建議使用非可讀的日誌格式(例如 ProtoBuf、Binlog 等)。
非必要狀況下,儘可能不要一條日誌輸出成多行,這種對於採集、解析和索引的代價都比較高。
日誌的輸出量直接影響到磁盤使用以及對於應用的性能消耗,日誌太多不利於查看、採集、分析;日誌太少不利於監控,同時在出現問題的時候沒辦法調查。
通常線上應用需合理控制日誌的數據量:
建議一個應用不一樣類型的日誌輸出到不一樣的目標(文件),這樣便於分類採集、查看和監控。例如:
日誌做爲業務系統的輔助模塊,必定不能影響到業務正常的工做,所以日誌模塊的性能消耗須要單獨額外注意,通常在選擇/開發日誌庫時,須要對日誌庫進行性能測試,確保正常狀況下日誌的性能消耗不超過總體 CPU 佔用的 5%。
注意:必定要確保日誌打印是異步的,不能阻塞業務系統運行。
開源的日誌庫很是多,基本每一個語言都有數十種,選擇一個符合公司/業務需求的日誌庫須要精挑細選,有一個簡單的指導原則是儘量使用比較流行的日誌庫的穩定版本,入坑的概率要小一點。例如:
在虛擬機/物理機的場景中,絕大部分應用都以文件的形式輸出日誌(只有一些系統應用輸出到 syslog/journal);而在容器場景中,多了一個標準輸出的方式,應用把日誌打到 stdout 或 stderr 上,日誌會自動進入到 docker 的日誌模塊,能夠經過 docker logs 或 kubectl logs 直接查看。
容器的標準輸出只適應於比較單一的應用,例如 K8s 中的一些系統組件,線上的服務類應用一般都會涉及到多個層級(中間件)、和各類服務交互,通常日誌都會分爲好幾類,若是所有打印到容器的標準輸出,很難區分處理。<br />同時容器標準輸出對於 DockerEngine 的性能消耗特別大,實測 10W/s 的日誌量會額外佔用 DockerEngine 1 個核心的 CPU(單核 100%)。
在 Kubernetes 中,還能夠將日誌庫直接對接日誌系統,日誌打印的時候不落盤而直接傳輸到日誌系統後端。這種使用方式免去了日誌落盤、Agent 採集的過程,總體性能會高不少。
這種方式咱們通常只建議日誌量極大的場景使用,普通狀況下仍是直接落盤,相比直接發送到後端的方式,落盤增長了一層文件緩存,在網絡失敗的狀況下還能緩存必定的數據,在日誌系統不可用的狀況下咱們的研發運維同窗能夠直接查看文件的日誌,提升總體的可靠性。
Kubernetes 提供了多種存儲方式,通常在雲上,都會提供本地存儲、遠程文件存儲、對象存儲等方式。因爲日誌寫入的 QPS 很高,和應用也直接相關,若是使用遠程類型的存儲,會額外多 2-3 次網絡通訊開銷。咱們通常建議使用本地存儲的方式,可使用 HostVolume 或者 EmptyDir 的方式,這樣對於寫入和採集的性能影響會盡量的小。
相比傳統虛擬機/物理機的場景,Kubernetes 對於節點、應用層提供了強大的調度、容錯、縮/擴容能力,咱們經過 Kubernetes 很容易就能讓應用得到高可靠運行、極致彈性。這些優點帶來的一個現象是:節點動態建立/刪除、容器動態建立/刪除,這樣日誌也會隨時銷燬,沒辦法保證日誌的存儲週期可以知足 DevOps、審計等相關的需求。
在動態的環境下實現日誌的長期存儲只能經過中心化的日誌存儲來實現,經過實時的日誌採集方式,將各個節點、各個容器的日誌在秒級內採集到日誌中心繫統上,即便節點/容器掛掉也可以經過日誌還原當時的現場。
日誌輸出是日誌系統建設中很是重要的環節,公司/產品線必定要遵循一個統一的日誌規範,這樣才能保證後續日誌採集、分析、監控、可視化可以順利進行。
後面的章節會介紹如何爲 Kubernetes 規劃日誌採集和存儲的最佳實踐,敬請期待。
「阿里巴巴雲原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的技術圈。」