系統日誌
系統元件日誌記錄叢集中發生的事件,這對除錯非常有用。你可以配置日誌詳細程度以檢視更多或更少細節。日誌的粒度可以粗到顯示元件中的錯誤,也可以細到顯示事件的逐步跟蹤(例如 HTTP 訪問日誌、Pod 狀態變更、控制器操作或排程器決策)。
警告
與此處描述的命令列引數不同,日誌輸出本身不受 Kubernetes API 穩定性保證的約束:單個日誌條目及其格式可能會在不同版本之間發生變化!Klog
klog 是 Kubernetes 的日誌庫。klog 為 Kubernetes 系統元件生成日誌訊息。
Kubernetes 正在簡化其元件中的日誌記錄。以下 klog 命令列引數在 Kubernetes v1.23 中已棄用,並將在 Kubernetes v1.26 中移除:
--add-dir-header
--alsologtostderr
--log-backtrace-at
--log-dir
--log-file
--log-file-max-size
--logtostderr
--one-output
--skip-headers
--skip-log-headers
--stderrthreshold
無論輸出格式如何,輸出始終寫入到 stderr。輸出重定向預計由呼叫 Kubernetes 元件的元件處理。這可以是 POSIX shell 或 systemd 等工具。
在某些情況下,例如無發行版容器或 Windows 系統服務,這些選項不可用。此時,可以將 kube-log-runner
二進位制檔案用作 Kubernetes 元件的包裝器,以重定向輸出。預構建的二進位制檔案包含在幾個 Kubernetes 基礎映象中,其傳統名稱為 /go-runner
,在伺服器和節點發布歸檔中則為 kube-log-runner
。
此表顯示了 kube-log-runner
呼叫如何與 shell 重定向相對應。
用途 | POSIX shell (例如 bash) | kube-log-runner <options> <cmd> |
---|---|---|
合併 stderr 和 stdout,寫入 stdout | 2>&1 | kube-log-runner (預設行為) |
重定向兩者到日誌檔案 | 1>>/tmp/log 2>&1 | kube-log-runner -log-file=/tmp/log |
複製到日誌檔案並輸出到 stdout | 2>&1 | tee -a /tmp/log | kube-log-runner -log-file=/tmp/log -also-stdout |
僅將 stdout 重定向到日誌檔案 | >/tmp/log | kube-log-runner -log-file=/tmp/log -redirect-stderr=false |
Klog 輸出
傳統 klog 原生格式的示例
I1025 00:15:15.525108 1 httplog.go:79] GET /api/v1/namespaces/kube-system/pods/metrics-server-v0.3.1-57c75779f-9p8wg: (1.512ms) 200 [pod_nanny/v0.0.0 (linux/amd64) kubernetes/$Format 10.56.1.19:51756]
訊息字串可能包含換行符
I1025 00:15:15.525108 1 example.go:79] This is a message
which has a line break.
結構化日誌
Kubernetes v1.23 [beta]
警告
向結構化日誌訊息的遷移是一個持續的過程。並非所有日誌訊息在此版本中都是結構化的。解析日誌檔案時,你也必須處理非結構化日誌訊息。
日誌格式和值序列化可能會發生變化。
結構化日誌在日誌訊息中引入了統一的結構,允許以程式設計方式提取資訊。你可以以更小的精力和成本儲存和處理結構化日誌。生成日誌訊息的程式碼決定是使用傳統的非結構化 klog 輸出還是結構化日誌。
結構化日誌訊息的預設格式是文字,其格式與傳統 klog 向後相容:
<klog header> "<message>" <key1>="<value1>" <key2>="<value2>" ...
示例
I1025 00:15:15.525108 1 controller_utils.go:116] "Pod status updated" pod="kube-system/kubedns" status="ready"
字串用引號括起來。其他值用 %+v
格式化,這可能會導致日誌訊息 根據資料 繼續到下一行。
I1025 00:15:15.525108 1 example.go:116] "Example" data="This is text with a line break\nand \"quotation marks\"." someInt=1 someFloat=0.1 someStruct={StringField: First line,
second line.}
上下文日誌
Kubernetes v1.30 [beta]
上下文日誌是基於結構化日誌構建的。它主要關注開發人員如何使用日誌呼叫:基於該概念的程式碼更加靈活,並支援 上下文日誌 KEP 中描述的其他用例。
如果開發人員在其元件中使用了 WithValues
或 WithName
等附加函式,則日誌條目將包含由其呼叫者傳遞到函式中的附加資訊。
對於 Kubernetes 1.34,此功能由 ContextualLogging
Feature Gate 控制,並預設啟用。其基礎設施在 1.24 中新增,但未修改元件。 component-base/logs/example
命令演示瞭如何使用新的日誌呼叫以及支援上下文日誌的元件的行為。
$ cd $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/component-base/logs/example/cmd/
$ go run . --help
...
--feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
ContextualLogging=true|false (BETA - default=true)
$ go run . --feature-gates ContextualLogging=true
...
I0222 15:13:31.645988 197901 example.go:54] "runtime" logger="example.myname" foo="bar" duration="1m0s"
I0222 15:13:31.646007 197901 example.go:55] "another runtime" logger="example" foo="bar" duration="1h0m0s" duration="1m0s"
logger
鍵和 foo="bar"
是由呼叫記錄 runtime
訊息和 duration="1m0s"
值的函式新增的,而無需修改該函式。
在停用上下文日誌時,WithValues
和 WithName
不起作用,並且日誌呼叫透過全域性 klog 日誌器。因此,此附加資訊不再出現在日誌輸出中。
$ go run . --feature-gates ContextualLogging=false
...
I0222 15:14:40.497333 198174 example.go:54] "runtime" duration="1m0s"
I0222 15:14:40.497346 198174 example.go:55] "another runtime" duration="1h0m0s" duration="1m0s"
JSON 日誌格式
Kubernetes v1.19 [alpha]
警告
JSON 輸出不支援許多標準 klog 標誌。有關不支援的 klog 標誌列表,請參閱命令列工具參考。
並非所有日誌都保證以 JSON 格式寫入(例如,在程序啟動期間)。如果你打算解析日誌,請確保你也能處理非 JSON 格式的日誌行。
欄位名稱和 JSON 序列化可能會發生變化。
--logging-format=json
標誌將日誌格式從 klog 本機格式更改為 JSON 格式。JSON 日誌格式示例(美化輸出):
{
"ts": 1580306777.04728,
"v": 4,
"msg": "Pod status updated",
"pod":{
"name": "nginx-1",
"namespace": "default"
},
"status": "ready"
}
具有特殊含義的鍵
ts
- Unix 時間戳(必需,浮點數)v
- 詳細級別(僅用於資訊而非錯誤訊息,整數)err
- 錯誤字串(可選,字串)msg
- 訊息(必需,字串)
目前支援 JSON 格式的元件列表
日誌詳細級別
-v
標誌控制日誌的詳細程度。增加該值會增加記錄事件的數量,而減少該值會減少記錄事件的數量。提高詳細程度設定會記錄嚴重程度越來越低的事件。詳細程度設定為 0 只會記錄關鍵事件。
日誌位置
系統元件有兩種型別:執行在容器中的和不執行在容器中的。例如:
- Kubernetes 排程器和 kube-proxy 執行在容器中。
- kubelet 和 容器執行時 不在容器中執行。
在裝有 systemd 的機器上,kubelet 和容器執行時會寫入 journald。否則,它們會寫入 /var/log
目錄中的 .log
檔案。容器內的系統元件總是寫入 /var/log
目錄中的 .log
檔案,繞過預設的日誌記錄機制。與容器日誌類似,你應該輪換 /var/log
目錄中的系統元件日誌。在由 kube-up.sh
指令碼建立的 Kubernetes 叢集中,日誌輪換由 logrotate
工具配置。logrotate
工具每天或在日誌大小大於 100MB 時輪換日誌。
日誌查詢
Kubernetes v1.30 [beta]
(預設啟用:false)為了幫助除錯節點上的問題,Kubernetes v1.27 引入了一個特性,允許檢視節點上執行的服務的日誌。要使用此特性,請確保該節點已啟用 NodeLogQuery
功能門控,並且 kubelet 配置選項 enableSystemLogHandler
和 enableSystemLogQuery
都設定為 true。在 Linux 上,假設服務日誌可透過 journald 獲取。在 Windows 上,假設服務日誌可透過應用程式日誌提供程式獲取。在這兩個作業系統上,日誌也可透過讀取 /var/log/
中的檔案獲取。
如果你有權與節點物件互動,可以在所有節點或僅部分節點上試用此功能。這是一個從節點檢索 kubelet 服務日誌的示例:
# Fetch kubelet logs from a node named node-1.example
kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet"
你還可以獲取檔案,前提是這些檔案位於 kubelet 允許獲取日誌的目錄中。例如,你可以在 Linux 節點上從 /var/log
獲取日誌:
kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=/<insert-log-file-name-here>"
kubelet 使用啟發式方法檢索日誌。如果不知道給定的系統服務是將日誌寫入作業系統自己的日誌記錄器(如 journald)還是寫入 /var/log/
中的日誌檔案,這將很有幫助。啟發式方法首先檢查本地日誌記錄器,如果不可用,則嘗試從 /var/log/<servicename>
、/var/log/<servicename>.log
或 /var/log/<servicename>/<servicename>.log
中檢索第一個日誌。
可使用的完整選項列表如下:
選項 | 描述 |
---|---|
boot | boot 顯示特定系統啟動的訊息 |
pattern | pattern 透過提供的與 PERL 相容的正則表示式過濾日誌條目 |
query | query 指定要返回日誌的服務或檔案(必需) |
sinceTime | 一個 RFC3339 時間戳,從此時間戳開始顯示日誌(包含) |
untilTime | 一個 RFC3339 時間戳,到此時間戳結束顯示日誌(包含) |
tailLines | 指定從日誌末尾檢索多少行;預設是獲取整個日誌 |
更復雜查詢的示例
# Fetch kubelet logs from a node named node-1.example that have the word "error"
kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet&pattern=error"