1. 程式人生 > 其它 >簡述Kubernetes容器日誌收集原理!

簡述Kubernetes容器日誌收集原理!

概述

關於容器日誌

Docker的日誌分為兩類,一類是Docker引擎日誌;另一類是容器日誌。引擎日誌一般都交給了系統日誌,不同的作業系統會放在不同的位置。本文主要介紹容器日誌,容器日誌可以理解是執行在容器內部的應用輸出的日誌,預設情況下,docker logs顯示當前執行的容器的日誌資訊,內容包含 STOUT(標準輸出)和STDERR(標準錯誤輸出)。日誌都會以json-file的格式儲存於/var/lib/docker/containers/<容器id>/<容器id>-json.log,不過這種方式並不適合放到生產環境中。

  • 預設方式下容器日誌並不會限制日誌檔案的大小,容器會一直寫日誌,導致磁碟爆滿,影響系統應用。(docker log-driver支援log檔案的rotate)

  • Docker Daemon收集容器的標準輸出,當日志量過大時會導致Docker Daemon成為日誌收集的瓶頸,日誌的收集速度受限。

  • 日誌檔案量過大時,利用docker logs -f檢視時會直接將Docker Daemon阻塞住,造成docker ps等命令也不響應。

Docker提供了logging drivers配置,使用者可以根據自己的需求去配置不同的log-driver,可參考官網Configure logging drivers[1]。但是上述配置的日誌收集也是通過Docker Daemon收集,收集日誌的速度依然是瓶頸。

log-driver 日誌收集速度

syslog 14.9 MB/s


json-file 37.9 MB/s

能不能找到不通過Docker Daemon收集日誌直接將日誌內容重定向到檔案並自動rotate的工具呢?答案是肯定的採用S6[2]基底映象。

S6-log將CMD的標準輸出重定向到/.../default/current,而不是傳送到 Docker Daemon,這樣就避免了Docker Daemon收集日誌的效能瓶頸。本文就是採用S6基底映象構建應用映象形成統一日誌收集方案。

關於Kubernetes日誌

Kubernetes日誌收集方案分成三個級別:

應用(Pod)級別

Pod級別的日誌,預設是輸出到標準輸出和標誌輸入,實際上跟Docker容器的一致。使用kubectl logs pod-name -n namespace檢視,具體參考:

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#logs。

節點級別

Node級別的日誌 , 通過配置容器的log-driver來進行管理,這種需要配合logrotare來進行,日誌超過最大限制,自動進行rotate操作。

叢集級別

叢集級別的日誌收集,有三種。

節點代理方式,在Node級別進行日誌收集。一般使用DaemonSet部署在每個Node中。這種方式優點是耗費資源少,因為只需部署在節點,且對應用無侵入。缺點是隻適合容器內應用日誌必須都是標準輸出。

使用sidecar container作為容器日誌代理,也就是在Pod中跟隨應用容器起一個日誌處理容器,有兩種形式:

一種是直接將應用容器的日誌收集並輸出到標準輸出(叫做Streaming sidecar container),但需要注意的是,這時候,宿主機上實際上會存在兩份相同的日誌檔案:一份是應用自己寫入的;另一份則是sidecar的stdout和stderr對應的JSON檔案。這對磁碟是很大的浪費,所以說,除非萬不得已或者應用容器完全不可能被修改。

另一種是每一個Pod中都起一個日誌收集agent(比如Logstash或Fluebtd)也就是相當於把方案一里的logging agent放在了Pod裡。但是這種方案資源消耗(CPU,記憶體)較大,並且日誌不會輸出到標準輸出,kubectl logs會看不到日誌內容。

應用容器中直接將日誌推到儲存後端,這種方式就比較簡單了,直接在應用裡面將日誌內容傳送到日誌收集服務後端。

日誌架構

通過上文對Kubernetes日誌收集方案的介紹,要想設計一個統一的日誌收集系統,可以採用節點代理方式收集每個節點上容器的日誌,日誌的整體架構如圖所示:

解釋如下:

  1. 所有應用容器都是基於S6基底映象的,容器應用日誌都會重定向到宿主機的某個目錄檔案下比如/data/logs/namespace/appname/podname/log/xxxx.log

  2. log-agent內部包含Filebeat,Logrotate等工具,其中Filebeat是作為日誌檔案收集的agent

  3. 通過Filebeat將收集的日誌傳送到Kafka

  4. Kafka在講日誌傳送的ES日誌儲存/kibana檢索層

  5. Logstash作為中間工具主要用來在ES中建立index和消費Kafka的訊息

整個流程很好理解,但是需要解決的是:

  1. 使用者部署的新應用,如何動態更新Filebeat配置

  2. 如何保證每個日誌檔案都被正常的rotate

  3. 如果需要更多的功能則需要二次開發Filebeat,使Filebeat支援更多的自定義配置

付諸實踐

解決上述問題,就需要開發一個log-agent應用以DaemonSet形式執行在Kubernetes叢集的每個節點上,應用內部包含Filebeat,Logrotate和需要開發的功能元件。

第一個問題,如何動態更新Filebeat配置,可以利用http://github.com/fsnotify/fsnotify工具包監聽日誌目錄變化create、delete事件,利用模板渲染的方法更新Filebeat配置檔案。

第二個問題,利用http://github.com/robfig/cron工具包建立CronJob,定期rotate日誌檔案,注意應用日誌檔案所屬使用者,如果不是root使用者所屬,可以在配置中設定切換使用者。

/var/log/xxxx/xxxxx.log {
  su www-data www-data
  missingok
  notifempty
  size 1G
  copytruncate
} 

第三個問題,關於二次開發filebeat,可以參考博文:https://www.jianshu.com/p/fe3ac68f4a7a

總結

本文只是對Kubernetes日誌收集提供了一個簡單的思路,關於日誌收集可以根據公司的需求,因地制宜。

寫在最後

歡迎大家關注我的公眾號【風平浪靜如碼】,海量Java相關文章,學習資料都會在裡面更新,整理的資料也會放在裡面。

覺得寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!