從 Docker 到 Kubernetes 日誌管理機制詳解
轉載於:https://blog.csdn.net/qianghaohao/article/details/100072538
在容器化時代,容器應用的日誌管理和傳統應用存在很大的區別,為了順應容器化應用,Docker 和 Kubernetes 提供了一套完美的日誌解決方案。本文從 Docker 到 Kubernetes 逐步介紹在容器化時代日誌的管理機制,以及在 Kubernetes 平臺下有哪些最佳的日誌收集方案。涉及到的話題有 Docker 日誌管理機制、Kubernetes 日誌管理機制、Kubernetes 叢集日誌收集方案。本文結構如下:
-
Docker 日誌管理機制
- Docker 的日誌種類
- 基於日誌驅動(loging driver)的日誌管理機制
- Docker 日誌驅動(loging driver)配置
- Docker 預設的日誌驅動
json-file
-
Kubernetes 日誌管理機制
- 應用 Pod 日誌
- Kuberntes 叢集元件日誌
-
Kubernetes 叢集日誌收集方案
- 節點級日誌代理方案
- sidecar 容器方案
- 應用程式直接將日誌傳輸到日誌平臺
一、Docker 日誌管理機制
1、Docker 的日誌種類
在 Docker 中日誌分為兩大類:
- Docker 引擎日誌;
- 容器日誌;
Docker 引擎日誌
Docker 引擎日誌就是 docker 服務的日誌,即dockerd
journal -u docker
檢視日誌。容器日誌
容器日誌指的是每個容器打到 stdout 和 stderr 的日誌,而不是容器內部的日誌檔案。docker 管理所有容器打到 stdout 和 stderr 的日誌,其他來源的日誌不歸 docker 管理。我們通過docker logs
命令檢視容器日誌都是讀取容器打到 stdout 和 stderr 的日誌。
基於日誌驅動(loging driver)的日誌管理機制
Docker 提供了一套通用、靈活的日誌管理機制,Docker 將所有容器打到 stdout 和 stderr 的日誌都統一通過日誌驅動重定向到某個地方。
Docker 支援的日誌驅動有很多,比如 local、json-file、syslog、journald 等等,類似外掛一樣,不同的日誌驅動可以將日誌重定向到不同的地方,這體現了 Docker 日誌管理的靈活性,以熱插拔的方式實現日誌不同目的地的輸出。
Dokcer 預設的日誌日誌驅動是json-file
,該驅動將將來自容器的 stdout 和 stderr 日誌都統一以json
的形式儲存到本地磁碟。日誌儲存路徑格式為:/var/lib/docker/containers/<容器 id>/<容器 id>-json.log
。所以可以看出在json-file
日誌驅動下,Docker 將所有容器日誌都統一重定向到了/var/lib/docker/containers/
目錄下,這為日誌收集提供了很大的便利。
注意:只有日誌驅動為:local、json-file 或者 journald 時,
docker logs
命令才能檢視到容器打到 stdout/stderr 的日誌。
下面為官方支援的日誌驅動列表:
驅動 | 描述 |
---|---|
none | 執行的容器沒有日誌,docker logs 也不返回任何輸出。 |
local | 日誌以自定義格式儲存,旨在實現最小開銷。 |
json-file | 日誌格式為JSON。Docker的預設日誌記錄驅動程式。 |
syslog | 將日誌訊息寫入syslog。該 syslog 守護程式必須在主機上執行。 |
journald | 將日誌訊息寫入journald。該journald守護程式必須在主機上執行。 |
gelf | 將日誌訊息寫入Graylog擴充套件日誌格式(GELF)端點,例如Graylog或Logstash。 |
fluentd | 將日誌訊息寫入fluentd(轉發輸入)。該fluentd守護程式必須在主機上執行。 |
awslogs | 將日誌訊息寫入Amazon CloudWatch Logs。 |
splunk | 使 用HTTP 事件收集器將日誌訊息寫入 splunk。 |
etwlogs | 將日誌訊息寫為 Windows 事件跟蹤(ETW)事件。僅適用於Windows平臺。 |
gcplogs | 將日誌訊息寫入 Google Cloud Platform(GCP)Logging。 |
logentries | 將日誌訊息寫入 Rapid7 Logentries。 |
Docker 日誌驅動(loging driver)配置
上面我們已經知道 Docker 支援多種日誌驅動型別,我們可以修改預設的日誌驅動配置。日誌驅動可以全域性配置,也可以給特定容器配置。
- 檢視 Docker 當前的日誌驅動配置
docker info |grep "Logging Driver"
- 檢視單個容器的設定的日誌驅動
docker inspect -f '{{.HostConfig.LogConfig.Type}}' 容器id
- Docker 日誌驅動全域性配置
全域性配置意味所有容器都生效,編輯 /etc/docker/daemon.json 檔案(如果檔案不存在新建一個),新增日誌驅動配置。
示例:配置 Docker 引擎日誌驅動為syslog
{ "log-driver": "syslog" }
- 給特定容器配置日誌驅動
在啟動容器時指定日誌驅動--log-driver
引數。
示例:啟動 nginx 容器,日誌驅動指定為 journald
docker run --name nginx -d --log-driver journald nginx
Docker 預設的日誌驅動json-file
json-file 日誌驅動記錄所有容器的 STOUT/STDERR 的輸出 ,用 JSON 的格式寫到檔案中,每一條 json 日誌中預設包含log
,stream
,time
三個欄位,示例日誌如下:
檔案路徑為:
/var/lib/docker/containers/40f1851f5eb9e684f0b0db216ea19542529e0a2a2e7d4d8e1d69f3591a573c39/40f1851f5eb9e684f0b0db216ea19542529e0a2a2e7d4d8e1d69f3591a573c39-json.log
{"log":"14:C 25 Jul 2019 12:27:04.072 * DB saved on disk\n","stream":"stdout","time":"2019-07-25T12:27:04.072712524Z"}
那麼打到磁碟的 json 檔案該如何配置輪轉,防止撐滿磁碟呢?每種 Docker 日誌驅動都有相應的配置項日誌輪轉,比如根據單個檔案大小和日誌檔案數量配置輪轉。json-file
日誌驅動支援的配置選項如下:
選項 | 描述 | 示例值 |
---|---|---|
max-size | 切割之前日誌的最大大小。可取值單位為(k,m,g), 預設為-1(表示無限制)。 | --log-opt max-size=10m |
max-file | 可以存在的最大日誌檔案數。如果切割日誌會建立超過閾值的檔案數,則會刪除最舊的檔案。僅在max-size設定時有效。正整數。預設為1。 | --log-opt max-file=3 |
labels | 適用於啟動Docker守護程式時。此守護程式接受的以逗號分隔的與日誌記錄相關的標籤列表。 | --log-opt labels=production_status,geo |
env | 適用於啟動Docker守護程式時。此守護程式接受的以逗號分隔的與日誌記錄相關的環境變數列表。 | --log-opt env=os,customer |
compress | 切割的日誌是否進行壓縮。預設是disabled。 | --log-opt compress=true |
二、Kubernetes 日誌管理機制
在 Kubernetes 中日誌也主要有兩大類:
- 應用 Pod 日誌;
- Kuberntes 叢集元件日誌;
1、應用 Pod 日誌
Kubernetes Pod 的日誌管理是基於 Docker 引擎的,Kubernetes 並不管理日誌的輪轉策略,日誌的儲存都是基於 Docker 的日誌管理策略。k8s 叢集排程的基本單位就是 Pod,而 Pod 是一組容器,所以 k8s 日誌管理基於 Docker 引擎這一說法也就不難理解了,最終日誌還是要落到一個個容器上面。
假設 Docker 日誌驅動為json-file
,那麼在 k8s 每個節點上,kubelet 會為每個容器的日誌建立一個軟連結,軟連線儲存路徑為:/var/log/containers/
,軟連線會連結到/var/log/pods/
目錄下相應 pod 目錄的容器日誌,被連結的日誌檔案也是軟連結,最終連結到 Docker 容器引擎的日誌儲存目錄:/var/lib/docker/container
下相應容器的日誌。另外這些軟連結檔名稱含有 k8s 相關資訊,比如:Pod id,名字空間,容器 ID 等資訊,這就為日誌收集提供了很大的便利。
舉例:我們跟蹤一個容器日誌檔案,證明上述的說明,跟蹤一個 kong Pod 日誌,Pod 副本數為 1
/var/log/containers/kong-kong-d889cf995-2ntwz_kong_kong-432e47df36d0992a3a8d20ef6912112615ffeb30e6a95c484d15614302f8db03.log -------> /var/log/pods/kong_kong-kong-d889cf995-2ntwz_a6377053-9ca3-48f9-9f73-49856908b94a/kong/0.log -------> /var/lib/docker/containers/432e47df36d0992a3a8d20ef6912112615ffeb30e6a95c484d15614302f8db03/432e47df36d0992a3a8d20ef6912112615ffeb30e6a95c484d15614302f8db03-json.log
Kuberntes 叢集元件日誌
Kuberntes 叢集元件日誌分為兩類:
- 執行在容器中的 Kubernetes scheduler 和 kube-proxy。
- 未執行在容器中的 kubelet 和容器 runtime,比如 Docker。
在使用 systemd 機制的伺服器上,kubelet 和容器 runtime 寫入日誌到 journald。如果沒有 systemd,他們寫入日誌到 /var/log 目錄的 .log 檔案。容器中的系統元件通常將日誌寫到 /var/log 目錄,在 kubeadm 安裝的叢集中它們以靜態 Pod 的形式執行在叢集中,因此日誌一般在/var/log/pods
目錄下。
2、Kubernetes 叢集日誌收集方案
Kubernetes 本身並未提供叢集日誌收集方案,k8s 官方文件給了三種日誌收集的建議方案:
- 使用執行在每個節點上的節點級的日誌代理
- 在應用程式的 pod 中包含專門記錄日誌 sidecar 容器
- 應用程式直接將日誌傳輸到日誌平臺
節點級日誌代理方案
從前面的介紹我們已經瞭解到,k8s 每個節點都將容器日誌統一儲存到了/var/log/containers/
目錄下,因此可以在每個節點安裝一個日誌代理,將該目錄下的日誌實時傳輸到日誌儲存平臺。
由於需要每個節點執行一個日誌代理,因此日誌代理推薦以 DaemonSet 的方式執行在每個節點。官方推薦的日誌代理是 fluentd,當然也可以使用其他日誌代理,比如 filebeat,logstash 等。
sidecar 容器方案
有兩種使用 sidecar 容器的方式:
- sidecar 容器重定向日誌流
- sidecar 容器作為日誌代理
sidecar 容器重定向日誌流
這種方式基於節點級日誌代理方案,sidecar 容器和應用容器在同一個 Pod 執行,這個容器的作用就是讀取應用容器的日誌檔案,然後將讀取的日誌內容重定向到 stdout 和 stderr,然後通過節點級日誌代理統一收集。這種方式不推薦使用,缺點就是日誌重複儲存了,導致磁碟使用會成倍增加。比如應用容器的日誌本身打到檔案儲存了一份,sidecar 容器重定向又儲存了一份(儲存到了 /var/lib/docker/containers/ 目錄下)。這種方式的應用場景是應用本身不支援將日誌打到 stdout 和 stderr,所以才需要 sidecar 容器重定向下。
sidecar 容器作為日誌代理
這種方式不需要節點級日誌代理,和應用容器在一起的 sidecar 容器直接作為日誌代理方式執行在 Pod 中,sidecar 容器讀取應用容器的日誌,然後直接實時傳輸到日誌儲存平臺。很顯然這種方式也存在一個缺點,就是每個應用 Pod 都需要有個 sidecar 容器作為日誌代理,而日誌代理對系統 CPU、和記憶體都有一定的消耗,在節點 Pod 數很多的時候這個資源消耗其實是不小的。另外還有個問題就是在這種方式下由於應用容器日誌不直接打到 stdout 和 stderr,所以是無法使用kubectl logs
命令檢視 Pod 中容器日誌。
應用程式直接將日誌傳輸到日誌平臺
這種方式就是應用程式本身直接將日誌打到統一的日誌收集平臺,比如 Java 應用可以配置日誌的 appender,打到不同的地方,很顯然這種方式對應用程式有一定的侵入性,而且還要保證日誌系統的健壯性,從這個角度看應用和日誌系統還有一定的耦合性,所以個人不是很推薦這種方式。
總結:綜合對比上述三種日誌收集方案優缺點,更推薦使用節點級日誌代理方案,這種方式對應用沒有侵入性,而且對系統資源沒有額外的消耗,也不影響 kubelet 工具檢視 Pod 容器日誌。
相關文件
https://juejin.im/entry/5c03f8bb5188251ba905741d| Docker 日誌驅動配置
https://www.cnblogs.com/operationhome/p/10907591.html| Docker容器日誌管理最佳實踐
https://www.cnblogs.com/cocowool/p/Docker_Kubernetes_Log_Location.html| 談一下Docker與Kubernetes叢集的日誌和日誌管理
https://kubernetes.io/docs/concepts/cluster-administration/logging/| Kubernetes 日誌架