本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kubernetes 1.29 中的上下文日誌記錄:更好的故障排除和增強的日誌記錄
我們代表結構化日誌工作組和 SIG Instrumentation,欣然宣佈在 Kubernetes v1.24 中引入的上下文日誌記錄功能現已成功遷移到兩個元件(kube-scheduler 和 kube-controller-manager)以及一些目錄中。此功能旨在提供更有用的日誌,以更好地排查 Kubernetes 問題,並賦能開發者增強 Kubernetes。
什麼是上下文日誌記錄?
上下文日誌記錄基於 go-logr API。其核心思想是,庫從其呼叫者處接收一個 Logger 例項,並使用該例項進行日誌記錄,而不是訪問全域性 Logger。二進位制檔案決定日誌記錄的實現,而不是庫。go-logr API 圍繞結構化日誌記錄設計,並支援向 Logger 附加額外資訊。
這使得額外的用例成為可能
呼叫者可以向 Logger 附加額外資訊
- WithName 新增一個 "logger" 鍵,其值為用點連線的名稱
- WithValues 新增鍵/值對
當將此擴充套件的 Logger 傳入一個函式,並且該函式使用它而不是全域性 Logger 時,附加資訊就會包含在所有日誌條目中,而無需修改生成日誌條目的程式碼。這在高度並行的應用程式中非常有用,因為不同操作的輸出會交錯在一起,從而難以識別某個特定操作的所有日誌條目。
在執行單元測試時,日誌輸出可以與當前測試關聯。然後,當測試失敗時,go test 只會顯示失敗測試的日誌輸出。該輸出預設也可以更詳細,因為它不會在測試成功時顯示。測試可以並行執行而不會使其輸出交錯。
上下文日誌記錄的一個設計決策是允許將 Logger 作為值附加到 `context.Context`。由於 Logger 封裝了呼叫的預期日誌記錄的所有方面,它是上下文的**一部分**,而不僅僅是**使用**它。一個實際的優勢是許多 API 已經有了一個 `ctx` 引數或者可以新增一個。這提供了額外的優勢,比如能夠擺脫函式內部的 `context.TODO()` 呼叫。
如何使用它
上下文日誌記錄功能從 Kubernetes v1.24 開始為 Alpha 階段,因此需要啟用 `ContextualLogging` 特性門控。如果你想在 Alpha 階段測試此功能,你需要在 `kube-controller-manager` 和 `kube-scheduler` 上啟用此特性門控。
對於 `kube-scheduler`,有一點需要注意,除了啟用 `ContextualLogging` 特性門控外,instrumentation 還依賴於日誌詳細級別。為了避免因 1.29 版本為上下文日誌記錄新增的日誌 instrumentation 而減慢排程器,謹慎選擇何時新增額外資訊非常重要。
- 在 `-v3` 或更低級別,每個排程週期只使用一次 `WithValues("pod")`。這達到了預期的效果,即該週期的所有日誌訊息都包含 Pod 資訊。一旦上下文日誌記錄達到 GA 階段,“pod” 鍵/值對就可以從所有日誌呼叫中移除。
- 在 `-v4` 或更高級別,會生成更豐富的日誌條目,其中 `WithValues` 也用於節點(如果適用),`WithName` 用於當前操作和外掛。
下面是一個演示效果的例子
I1113 08:43:37.029524 87144 default_binder.go:53] "Attempting to bind pod to node" logger="Bind.DefaultBinder" pod="kube-system/coredns-69cbfb9798-ms4pq" node="127.0.0.1"
直接的好處是操作和外掛名稱在 `logger` 中可見。`pod` 和 `node` 在 `kube-scheduler` 程式碼中的各個日誌呼叫中已經作為引數被記錄。一旦 `kube-scheduler` 之外的更多包支援上下文日誌記錄,它們也將在那裡可見(例如,client-go)。一旦達到 GA 階段,日誌呼叫可以被簡化以避免重複這些值。
在 `kube-controller-manager` 中,`WithName` 用於將使用者可見的控制器名稱新增到日誌輸出中,例如:
I1113 08:43:29.284360 87141 graph_builder.go:285] "garbage controller monitor not synced: no monitors" logger="garbage-collector-controller"
`logger=”garbage-collector-controller”` 是由 `kube-controller-manager` 核心在例項化該控制器時新增的,並出現在其所有日誌條目中——至少只要它呼叫的程式碼支援上下文日誌記錄。需要進一步的工作來轉換像 client-go 這樣的共享包。
效能影響
在一個包中支援上下文日誌記錄,即接受來自呼叫者的 Logger,代價很低。對於 `kube-scheduler` 沒有觀察到效能影響。如上所述,新增 `WithName` 和 `WithValues` 需要更謹慎地進行。
在 Kubernetes 1.29 中,以生產環境的詳細級別(`-v3` 或更低)啟用上下文日誌記錄,並未對 `kube-scheduler` 造成可測量的減速,預計對 `kube-controller-manager` 也不會。在除錯級別,某些測試用例的 28% 減速仍然是合理的,因為由此產生的日誌使除錯更容易。詳情請參閱關於將該功能提升到 Beta 階段的討論。
對下游使用者的影響
日誌輸出不屬於 Kubernetes API 的一部分,並且在每個版本中都會定期更改,無論是因為開發人員在處理程式碼,還是因為正在進行的向結構化和上下文日誌記錄的轉換。
如果下游使用者依賴於特定的日誌,他們需要意識到這一變化對他們的影響。
進一步閱讀
參與其中
如果你有興趣參與進來,我們隨時歡迎新的貢獻者加入我們。上下文日誌記錄為你提供了一個為 Kubernetes 開發做出貢獻併產生有意義影響的絕佳機會。透過加入結構化日誌工作組,你可以積極參與 Kubernetes 的開發並做出你的第一個貢獻。這是學習和與社群互動、同時獲得寶貴經驗的好方法。
我們鼓勵你探索程式碼倉庫,並熟悉正在進行的討論和專案。這是一個協作的環境,你可以與其他貢獻者交流思想、提出問題並共同工作。
如果你有任何問題或需要指導,請隨時與我們聯絡,你可以在我們的公共 Slack 頻道上這樣做。如果你還不是該 Slack 工作區的成員,可以訪問 https://slack.k8s.io/ 獲取邀請。
我們想對所有提供了出色審查、分享了寶貴見解並協助實現此功能的貢獻者表示感謝(按字母順序排列):
- Aldo Culquicondor (alculquicondor)
- Andy Goldstein (ncdc)
- Feruzjon Muyassarov (fmuyassarov)
- Freddie (freddie400)
- JUN YANG (yangjunmyfm192085)
- Kante Yin (kerthcet)
- Kiki (carlory)
- Lucas Severo Alve (knelasevero)
- Maciej Szulik (soltysh)
- Mengjiao Liu (mengjiao-liu)
- Naman Lakhwani (Namanl2001)
- Oksana Baranova (oxxenix)
- Patrick Ohly (pohly)
- songxiao-wang87 (songxiao-wang87)
- Tim Allclai (tallclair)
- ZhangYu (Octopusjust)
- Ziqi Zhao (fatsheep9146)
- Zac (249043822)