Kubernetes 穩定性保障手冊 -- 日誌專題

頭圖.png

做者 | 悟鵬、沉醉
來源 | 阿里巴巴雲原生公衆號git

《Kubernetes 穩定性保障手冊》系列文章:github

不論對於軟件的用戶仍是開發者,日誌都是很重要的信息源。日誌能夠用來表徵軟件的運行狀態,在軟件運行不符合預期時提供豐富的信息,也能夠用在開發階段調試軟件,方便定位問題。web

軟件的生命週期涉及到 開發運行 兩個階段,日誌的生成是在軟件的開發階段,日誌的使用集中在軟件的運行階段。
在開發階段規範化日誌,有助於運行階段經過標準化方法分析日誌、配置日誌監控和告警。
在運行階段經過標準化方法使用日誌,有助於低成本把握程序的運行態行爲,及時感知異常,促進開發階段的迭代效率。安全

在軟件的生命週期中,運行階段時長佔比會遠大於開發階段,即對日誌的使用時長會遠大於開發階段寫日誌邏輯的時長。在開發階段應用良好的日誌規範,會對軟件生命週期的正常運行和快速迭代帶來很大幫助:架構

1.png

複雜度分析

程序中的元素能夠抽象爲兩部分:自身邏輯,依賴。兩類元素之間的交互爲:自身邏輯閉環,自身邏輯與依賴交互。ide

2.png

從長期角度來看,交互環節出問題的機率會比自身邏輯出問題的機率高,所以要重點關注交互環節的日誌邏輯。工具

同時,對日誌的管理須要意識到 _誰會使用這些日誌,_一般有 4 類角色:阿里雲

  • 用戶
  • 維護者
  • 安全人員
  • 審計人員

用戶從黑盒角度使用軟件,經過日誌瞭解軟件當前的運行狀態,關注重點是軟件正常的狀態。url

維護者從白盒角度使用軟件,開發角色經過日誌調試軟件,SRE 角色經過日誌及時感知軟件的異常狀態,並經過日誌上下文分析異常緣由。

安全人員經過分析日誌,瞭解惡意登陸、異常刪除等風險。

審計人員經過審計日誌、應用日誌,確認業務、架構的合規性。

根據上述不一樣的使用場景,咱們能夠梳理出幾類日誌類別,進一步加強開發和運行階段對日誌的理解:

3.jpg

開發階段

最佳實踐

理解了日誌使用者關注的重點後,開發階段寫日誌時,推薦使用以下最佳實踐:

  • 使用 structured logs
    • 不使用 format strings
  • 使用 info 和 error 表徵日誌級別
    • info 又可細化爲多個級別,0~10,信息的重要性依次下降 (也能夠參考《Kubernetes: sig-instrumentation/logging.md》
      • 0:用戶想要看到的信息
      • 1:維護者關注的白盒行爲信息
      • 10: 維護者調試用的信息
  • 使用具備過濾器能力的 log lib,經過 logger 自動過濾敏感信息
  • 日誌經過 stdout/stderr 輸出,關閉沒必要要的文本日誌
    • 避免額外的磁盤佔用、IO 消耗、日誌清理任務的維護等

對於 golang,能夠考慮使用 klog 做爲 logger 實現。

FAQ

爲何使用 structured logs?

structured logs 是一種結構化的日誌格式,結構以下,其中 msg 表徵通用的事件,多對的 k=v 用來具化事件:

msg k=v k=v ... k=v

示例:

"Pod status updated" pod="kube-system/kubedns" status="ready"

對於開發階段,structured logs 經過固化的結構和字段語義,協助開發者思考程序邏輯狀態,有助於進一步控制程序複雜度和理解程序邏輯。

對於運行階段,structured logs 中的 k 自然具有索引的屬性,便於進行查詢和分析。也能夠考慮將 msg 規範化,增長 事件 語義,經過限制 msg 語義來加強 msg 的做用。

爲何不使用 debug/warning/critical/fatal?

經過減小日誌類型,下降使用和維護負擔。

debug 能夠融入到 info 級別。

warning/critical 對於用戶和維護者都是模糊的詞,對於要採起的行動一般不具有指導意義。warning/critical 和 error 相似,表徵程序運行過程當中出現了預期外的現象,此時程序要麼自動處理,要麼交由外部人工介入判斷。若由程序自動處理,那麼用戶和維護者感知到這類現象便可,info 能夠知足。若須要交由外部人工介入,那麼 error 就能夠知足。對於問題的嚴重性,可放在運行階段,經過異常具體的信息來表徵,如 ServiceUnavailable、Unauthorized 等。

fatal 是將 error 和 panic 兩類邏輯封裝了起來,在開發過程當中可能會帶來執行邏輯上的不清晰,如決定是否 panic 的邏輯須要放在最頂層邏輯中,若在頂層邏輯之下調用 fatal,可能會帶來資源泄露、程序運行復雜度增長等問題。

爲何不使用 format strings?

format strings 是形如以下的結構:

klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v", seconds, retries, url)

這種結構將 通用事件具體內容 耦合在一塊兒,不利於開發階段下降理解程序邏輯的成本,也不便於使用階段經過標準化的方式進行查詢、分析,增長日誌的使用成本。

一種改善方式:

klog.V(4).InfoS("got a retry-after response when requesting url", "attempt", retries, "after seconds", seconds, "url", url)

爲何要使用具備過濾器能力的 log lib?

開發過程當中,可能會因爲疏忽而將敏感信息輸出到日誌中,如密碼、token 等信息。爲了不敏感信息泄露,須要增強 code review,同時也能夠考慮在 logger 中配置過濾器,自動進行敏感信息的過濾,參見 《KEP: Kubernetes system components logs sanitization》

對於 golang,能夠考慮使用 klog 做爲 logger 實現,並配合 Kubernetes/component-base: sanitization 進行使用。

運行階段

最佳實踐

運行階段是對日誌的使用,包括以下 4 個階段:

  1. 採集
  2. 查詢
  3. 分析
  4. 告警

因爲日誌服務對程序的運行以及後續的運營極爲重要,建議採用託管型的日誌產品來知足運行階段對日誌的使用需求,如阿里雲的 SLS 產品

若在多個 region 部署集羣,且集羣的組件相同,在使用日誌產品時,須要確保每一個 region 中日誌項目名稱規則的一致性。以阿里雲 SLS 產品爲例,若須要分別收集多個 region 的日誌,則 project、logstore 的名稱須要在多個 region 中保持相同的規則,目的是便於經過統一的方法對不一樣集羣的日誌作查詢和分析。

一般狀況下,日誌產品會提供上述 4 個階段的服務,具體的使用方法能夠參見對應日誌產品的文檔,下述針對告警作重點分析。

告警

告警要知足以下目標:

  • 覆蓋面全
  • 關鍵告警及時感知

基於開發階段的日誌規範,可對 error 級別的告警作統一告警,將告警信息統一到低優先級的通知渠道,如表徵普通告警的釘釘羣。

若要及時感知到關鍵告警,須要從以下 2 個方面入手:

  • 定義「關鍵告警」特徵
  • 分級告警,與相應的通知渠道結合

定義「關鍵告警」的特徵是個 長期持續完善 的過程,有 通用關鍵告警 和 業務關鍵告警。

通用關鍵告警 與業務耦合度小,如機器級別的關鍵告警 (宕機、內存壓力大、load 太高等)、託管服務的關鍵告警 (master 組件 panic/OOM、master 組件內存壓力大等),這部分告警配置能夠做爲基礎服務,做爲集羣交付的一部分。

業務關鍵告警 與業務耦合度大,須要與業務長期維護,重點關注「業務交互環節」的告警。

通知渠道一般會有以下幾類:

  • IM 羣 (如釘釘羣等)
  • 短信
  • 電話
  • webhook

這些通知渠道對人觸達的及時性不一樣,電話觸達性最好,短信其次,而後是 IM 羣。webhook 本質上是條通道,能夠對接不一樣的 IM 羣或短信、電話渠道。

推薦以下三種告警級別:

4.jpg

配置告警是個長期、不斷迭代的過程,爲了有助於告警有效性的迭代,配置每條告警時,能夠考慮使用以下表格,規範化每條告警的配置,並深刻思考告警配置的有效性:

5.jpg

FAQ

如何預先配置未模擬出的異常?

業務依賴的 OpenAPI/SDK/Lib 等一般都會有錯誤碼列表,如 阿里雲:API 錯誤中心、Lib 中的 errors 文件等。能夠基於該已知信息,枚舉依賴的 OpenAPI/SDK 中對業務有明顯負面影響的狀態碼作分級告警,如 ServiceUnavailable/Forbbiden/Unauthorized 等。

歡迎你們留言交流使用 Kubernetes 過程當中的穩定性保障問題,以及對穩定性保障的期待工具或服務。你們也可經過郵箱聯繫做者,進一步深刻交流:flyer.zyf@alibaba-inc.com

相關文章
相關標籤/搜索