溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

解決 K8s 中日志輸出問題的技巧有哪些

發(fā)布時間:2021-11-22 16:17:14 來源:億速云 閱讀:92 作者:柒染 欄目:云計算

解決 K8s 中日志輸出問題的技巧有哪些,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。


前言

我們將從實踐角度出發(fā)來一步步構建 K8s 中的日志監(jiān)控體系。

構建日志系統(tǒng)的第一步是如何去產生這些日志,而這也往往是最繁雜最困難的一步。

Kubernetes 中日志重要性

通常日志最基礎的作用是記錄程序的運行軌跡,在此之上會衍生出非常多的功能,例如線上監(jiān)控、告警、運營分析、安全分析等等,這些功能反過來也對日志具備一定的要求,我們需要盡可能的將日志規(guī)范化,以減少收集、解析、分析的代價。

在 Kubernetes 中,環(huán)境的動態(tài)性很強,日志基本上都是易失的,因此需要實時將日志采集到中心的存儲中,為了配合日志采集,對于日志的輸出、采集的話會有更多的要求。

下述我們列舉了 Kubernetes 中,日志輸出的常見注意事項(其中標記 (*)的是 Kubernetes 中特有的項目):

如何選擇日志等級

日志等級是用來區(qū)分日志對應事件嚴重程度的說明,這是所有日志中必須具備的一個選項。通常日志會分為 6 個不同的等級:

  • FATAL(致命):用來輸出非常嚴重或預期中不會發(fā)生的錯誤,遇到此種錯誤應當立即報警并人工介入處理;

  • ERROR (錯誤):非預期中的錯誤,此種錯誤可能導致部分系統(tǒng)異常但不會影響核心業(yè)務和系統(tǒng)正常運行;

  • WARN(警告):潛在的危險或值得關注的信息(比較核心的路徑);

  • INFO(信息):應用執(zhí)行過程中的詳細信息,一般通過該信息可以看到每個請求的主要執(zhí)行過程;

  • DEBUG(調試):用于線下調試的日志信息,用于分析應用執(zhí)行邏輯,線上應用切勿開啟;

  • TRACE(跟蹤):輸出最細致的運行軌跡,可能包含涉及的數據內容。

作為程序員,一定要合理設置日志等級,個人在開發(fā)過程中總結了以下幾點經驗:

  1. FATAL 類型日志一定是非常嚴重的錯誤、需要人工處理的場景打印的;

  2. ERROR 和 WARNING 的區(qū)別很多程序員難以選擇,可以從告警角度考慮:ERROR 為一般需要告警,WARNING 為不需要;

  3. 日志等級一方面是為了能夠表示日志的嚴重程度,另一方面也是為了控制應用程序的日志輸出量,通常線上只能打開 INFO 或 WARN 的日志;

  4. DEBUG 日志可以多打,方便分析問題;

  5. 所有用戶請求日志,必須記錄;

  6. 對于不確定的外部系統(tǒng)調用,日志需盡可能覆蓋周全;

  7. 程序中的日志庫需要具備運行期間變更日志等級的能力,方便在遇到問題需要分析時臨時更改日志等級;

  8. 通常在新功能上線,涉及的日志可適當提升一個等級,方便實時觀察和監(jiān)控,待穩(wěn)定后再調整到正常(記得加上注釋,方便改回來)。

日志內容規(guī)范

通常在沒有約束的情況下,程序員的發(fā)揮天馬行空,各種日志內容都會出現,這些只有開發(fā)自己才能看懂的日志很難進行分析和告警。因此我們需要一個日志頂向下的規(guī)范來約束項目中的開發(fā)人員,讓所有的日志看起來是一個人打印的而且是易于分析的。

日志的字段

日志中通常必備的字段有:Time、Level、Location。對于特定模塊/流程/業(yè)務,還需要有一些 Common 的字段,例如:

  1. 如果使用 Trace 系統(tǒng),可以把 TraceID 附加到日志中;

  2. 固定的流程需要附加對應的字段,例如訂單的生命周期中,一定要有訂單號、用戶 ID 等信息,這些信息可以通過 Context 附加到對應流程的日志實例上;

  3. HTTP 請求需要記錄:URL、Method、Status、Latency、Inflow、OutFlow、ClientIP、UserAgent 等,詳情可以參考 Nginx日志格式;

  4. 如果多個模塊的日志都打印到同一個流/文件中,必須有字段標識模塊名。

日志的字段規(guī)約最好由運維平臺/中間件平臺自頂向下推動,約束每個模塊/流程的程序員按照規(guī)定打印日志。

日志表現形式

通常我們建議使用 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 等)。

單條日志換行問題

非必要情況下,盡量不要一條日志輸出成多行,這種對于采集、解析和索引的代價都比較高。

合理控制日志輸出量

日志的輸出量直接影響到磁盤使用以及對于應用的性能消耗,日志太多不利于查看、采集、分析;日志太少不利于監(jiān)控,同時在出現問題的時候沒辦法調查。

一般線上應用需合理控制日志的數據量:

  1. 服務入口的請求和響應日志沒有特殊原因都要輸出并采集,采集的字段可以根據需求調整;

  2. 錯誤日志一般都要打印,如果太多,可以使用采樣方式打??;

  3. 減少無效日志輸出,尤其是循環(huán)中打印日志的情況需盡量減少;

  4. 請求型的日志(比如 Ingress、Nginx 訪問日志)一般不超過 5MB/s(500 字節(jié)每條,不超過 1W/s),應用程序日志不超過 200KB/s(2KB 每條,不超過 100 條/s)。

選擇多種日志輸出目標

建議一個應用不同類型的日志輸出到不同的目標(文件),這樣便于分類采集、查看和監(jiān)控。例如:

  1. 訪問日志單獨放到一個文件,如果域名不多,可以按照一個域名一個文件的形式;

  2. 錯誤類的日志單獨放一個文件,單獨配置監(jiān)控告警;

  3. 調用外部系統(tǒng)的日志單獨放一個文件,便于后續(xù)對賬、審計;

  4. 中間件通常都由統(tǒng)一的平臺提供,日志一般單獨打印一個文件。

控制日志性能消耗

日志作為業(yè)務系統(tǒng)的輔助模塊,一定不能影響到業(yè)務正常的工作,因此日志模塊的性能消耗需要單獨額外注意,一般在選擇/開發(fā)日志庫時,需要對日志庫進行性能測試,確保正常情況下日志的性能消耗不超過整體 CPU 占用的 5%。

注意:一定要確保日志打印是異步的,不能阻塞業(yè)務系統(tǒng)運行。

如何選擇日志庫

開源的日志庫非常多,基本每個語言都有數十種,選擇一個符合公司/業(yè)務需求的日志庫需要精挑細選,有一個簡單的指導原則是盡可能使用比較流行的日志庫的穩(wěn)定版本,入坑的幾率要小一點。例如:

  1. Java 使用 Log4J、LogBack;

  2. Golang 使用 go-kit;

  3. Python 默認集成的日志庫大部分場景都夠用,建議閱讀一下 CookBook;

  4. C++ 推薦使用 spdlog,高性能、跨平臺。

日志形態(tài)選擇

在虛擬機/物理機的場景中,絕大部分應用都以文件的形式輸出日志(只有一些系統(tǒng)應用輸出到 syslog/journal);而在容器場景中,多了一個標準輸出的方式,應用把日志打到 stdout 或 stderr 上,日志會自動進入到 docker 的日志模塊,可以通過 docker logs 或 kubectl logs 直接查看。

容器的標準輸出只適應于比較單一的應用,例如 K8s 中的一些系統(tǒng)組件,線上的服務類應用通常都會涉及到多個層級(中間件)、和各種服務交互,一般日志都會分為好幾類,如果全部打印到容器的標準輸出,很難區(qū)分處理。
同時容器標準輸出對于 DockerEngine 的性能消耗特別大,實測 10W/s 的日志量會額外占用 DockerEngine 1 個核心的 CPU(單核 100%)。

日志是否落盤以及落盤介質

在 Kubernetes 中,還可以將日志庫直接對接日志系統(tǒng),日志打印的時候不落盤而直接傳輸到日志系統(tǒng)后端。這種使用方式免去了日志落盤、Agent 采集的過程,整體性能會高很多。

這種方式我們一般只建議日志量極大的場景使用,普通情況下還是直接落盤,相比直接發(fā)送到后端的方式,落盤增加了一層文件緩存,在網絡失敗的情況下還能緩存一定的數據,在日志系統(tǒng)不可用的情況下我們的研發(fā)運維同學可以直接查看文件的日志,提高整體的可靠性。

Kubernetes 提供了多種存儲方式,一般在云上,都會提供本地存儲、遠程文件存儲、對象存儲等方式。由于日志寫入的 QPS 很高,和應用也直接相關,如果使用遠程類型的存儲,會額外多 2-3 次網絡通信開銷。我們一般建議使用本地存儲的方式,可以使用 HostVolume 或者 EmptyDir 的方式,這樣對于寫入和采集的性能影響會盡可能的小。

如何保證日志存儲周期

相比傳統(tǒng)虛擬機/物理機的場景,Kubernetes 對于節(jié)點、應用層提供了強大的調度、容錯、縮/擴容能力,我們通過 Kubernetes 很容易就能讓應用獲得高可靠運行、極致彈性。這些優(yōu)勢帶來的一個現象是:節(jié)點動態(tài)創(chuàng)建/刪除、容器動態(tài)創(chuàng)建/刪除,這樣日志也會隨時銷毀,沒辦法保證日志的存儲周期能夠滿足 DevOps、審計等相關的需求。

在動態(tài)的環(huán)境下實現日志的長期存儲只能通過中心化的日志存儲來實現,通過實時的日志采集方式,將各個節(jié)點、各個容器的日志在秒級內采集到日志中心系統(tǒng)上,即使節(jié)點/容器掛掉也能夠通過日志還原當時的現場。

日志輸出是日志系統(tǒng)建設中非常重要的環(huán)節(jié),公司/產品線一定要遵循一個統(tǒng)一的日志規(guī)范,這樣才能保證后續(xù)日志采集、分析、監(jiān)控、可視化能夠順利進行。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

k8s
AI