自 2013 年 dotCloud 公司開源 Docker 以來,以 Docker 爲表明的容器產品憑藉着隔離性好、可移植性高、資源佔用少、啓動迅速等特性迅速風靡世界。下圖展現了 2013 年以來 Docker 和 OpenStack 的搜索趨勢。php
容器技術在部署、交付等環節給人們帶來了不少便捷,但在日誌處理領域卻帶來了許多新的挑戰,包括:css
本文以 Docker 爲例,依託阿里雲日誌服務團隊在日誌領域深耕多年積累下的豐富經驗,介紹容器日誌處理的通常方法和最佳實踐,包括:html
採集日誌首先要弄清日誌存在的位置,這裏以 Nginx、Tomcat 這兩個經常使用容器爲例進行分析。linux
Nginx 產生的日誌包括 access.log 和 error.log,根據 nginx Dockerfile 可知 access.log 和 error.log 被分別重定向到了 STDOUT 和 STDERR 上。nginx
Tomcat 產生的日誌比較多,包括 catalina.log、access.log、manager.log、host-manager.log 等,tomcat Dockerfile 並無將這些日誌重定向到標準輸出,它們存在於容器內部。git
容器產生的日誌大部分均可以歸結於上述情形。這裏,咱們不妨將容器日誌分紅如下兩類。github
容器日誌分類 | 定義 |
---|---|
標準輸出 | 經過 STDOUT、STDERR 輸出的信息,包括被重定向到標準輸出的文本文件。 |
文本日誌 | 存在於容器內部而且沒有被重定向到標準輸出的日誌。 |
容器的標準輸出會由 logging driver 統一處理。以下圖所示,不一樣的 logging driver 會將標準輸出寫往不一樣的目的地。docker
經過 logging driver 採集容器標準輸出的優點在於使用簡單,例如:json
# 該命令表示在 docker daemon 級別爲全部容器配置 syslog 日誌驅動
dockerd -–log-driver syslog –-log-opt syslog-address=udp://1.2.3.4:1111 # 該命令表示爲當前容器配置 syslog 日誌驅動 docker run -–log-driver syslog –-log-opt syslog-address=udp://1.2.3.4:1111 alpine echo hello world
除了 json-file 和 journald,使用其餘 logging driver 將使 docker logs API 不可用。tomcat
例如,當您使用 portainer 管理宿主機上的容器,而且使用了上述二者以外的 logging driver,您會發現沒法經過 UI 界面觀察到容器的標準輸出。
對於那些使用默認 logging driver 的容器,咱們能夠經過向 docker daemon 發送 docker logs 命令來獲取容器的標準輸出。使用此方式採集日誌的工具包括 logspout、sematext-agent-docker 等。下列樣例中的命令表示獲取容器自2018-01-01T15:00:00
以來最新的5條日誌。
docker logs --since "2018-01-01T15:00:00" --tail 5 <container-id>
當日志量較大時,這種方式會對 docker daemon 形成較大壓力,致使 docker daemon 沒法及時響應建立容器、銷燬容器等命令。
默認 logging driver 會將日誌以 json 的格式寫入宿主機文件裏,文件路徑爲/var/lib/docker/containers/<container-id>/<container-id>-json.log
。這樣能夠經過直接採集宿主機文件來達到採集容器標準輸出的目的。
該方案較爲推薦,由於它既不會使 docker logs API 變得不可用,又不會影響 docker daemon,而且如今許多工具原生支持採集宿主機文件,如 filebeat、logtail 等。
採集容器內文本日誌最簡單的方法是在啓動容器時經過 bind mounts 或 volumes 方式將宿主機目錄掛載到容器日誌所在目錄上,以下圖所示。
針對 tomcat 容器的 access log,使用命令docker run -it -v /tmp/app/vol1:/usr/local/tomcat/logs tomcat
將宿主機目錄/tmp/app/vol1
掛載到 access log 在容器中的目錄/usr/local/tomcat/logs
上,經過採集宿主機目錄/tmp/app/vol1
下日誌達到採集 tomcat access log 的目的。
使用掛載宿主機目錄的方式採集日誌對應用會有必定的侵入性,由於它要求容器啓動的時候包含掛載命令。若是採集過程能對用戶透明那就太棒了。事實上,能夠經過計算容器 rootfs 掛載點來達到這種目的。
和容器 rootfs 掛載點密不可分的一個概念是 storage driver。實際使用過程當中,用戶每每會根據 linux 版本、文件系統類型、容器讀寫狀況等因素選擇合適的 storage driver。不一樣 storage driver 下,容器的 rootfs 掛載點遵循必定規律,所以咱們能夠根據 storage driver 的類型推斷出容器的 rootfs 掛載點,進而採集容器內部日誌。下表展現了部分 storage dirver 的 rootfs 掛載點及其計算方法。
Storage driver | rootfs 掛載點 | 計算方法 |
---|---|---|
aufs | /var/lib/docker/aufs/mnt/<id> | id 能夠從以下文件讀到。/var/lib/docker/image/aufs/layerdb/mounts/\<container-id\>/mount-id |
overlay | /var/lib/docker/overlay/<id>/merged | 完整路徑能夠經過以下命令獲得。docker inspect -f '{{.GraphDriver.Data.MergedDir}}' <container-id> |
overlay2 | /var/lib/docker/overlay2/<id>/merged | 完整路徑能夠經過以下命令獲得。docker inspect -f '{{.GraphDriver.Data.MergedDir}}' <container-id> |
devicemapper | /var/lib/docker/devicemapper/mnt/<id>/rootfs | id 能夠經過以下命令獲得。docker inspect -f '{{.GraphDriver.Data.DeviceName}}' <container-id> |
在充分比較了容器日誌的各類採集方法,綜合整理了廣大用戶的反饋與訴求後,日誌服務團隊推出了容器日誌一站式解決方案。
logtail 方案包含以下功能:
和 K8s 生態深度集成,能很是方便地採集 K8s 容器日誌是日誌服務 logtail 方案的又一大特點。
採集配置管理:
採集模式:
關於 Logtail 方案的詳細說明可參考文章全面提高,阿里雲Docker/Kubernetes(K8S) 日誌解決方案與選型對比。
完成日誌採集工做後,下一步須要對這些日誌進行查詢分析和可視化。這裏以 Tomcat 訪問日誌爲例,介紹日誌服務提供的強大的查詢、分析、可視化功能。
容器日誌被採集時會帶上 container name、container IP、目標文件路徑等信息,所以在查詢的時候能夠經過這些信息快速定位目標容器和文件。查詢功能的詳細介紹可參考文檔查詢語法。
日誌服務實時分析功能兼容 SQL 語法且提供了 200 多種聚合函數。若是您有使用 SQL 的經驗,可以很容易寫出知足業務需求的分析語句。例如:
* | SELECT request_uri, COUNT(*) as c GROUP by request_uri ORDER by c DESC LIMIT 10
* | SELECT diff[1] AS c1, diff[2] AS c2, round(diff[1] * 100.0 / diff[2] - 100.0, 2) AS c3 FROM (select compare( flow, 3600) AS diff from (select sum(body_bytes_sent) as flow from log))
該語句使用同比環比函數計算不一樣時間段的網絡流量。
爲了讓數據更加生動,您可使用日誌服務內置的多種圖表對 SQL 計算結果進行可視化展現,並將圖表組合成一個儀表盤。
下圖展現了基於 Tomcat 訪問日誌的儀表盤,它展現了錯誤請求率、網絡流量、狀態碼隨時間的變化趨勢等信息。該儀表盤展示的是多個 Tomcat 容器數據聚合後的結果,您可使用儀表盤過濾器功能,經過指定容器名查看單個容器的數據。
查詢分析、儀表盤等功能能幫助咱們把握全局信息、瞭解系統總體運行狀況,但定位具體問題每每須要上下文信息的幫助。
上下文指的是圍繞某個問題展開的線索,如日誌中某個錯誤的先後信息。上下文包含兩個要素:
下表展現了不一樣數據源的最小區分粒度。
分類 | 最小區分粒度 |
---|---|
單機文件 | IP + 文件 |
Docker 標準輸出 | Container + STDOUT/STDERR |
Docker 文件 | Container + 文件 |
K8s 容器標準輸出 | Namespace + Pod + Container + STDOUT/STDERR |
K8s 容器文件 | Namespace + Pod + Container + 文件 |
SDK | 線程 |
Log Appender | 線程 |
在日誌集中式存儲的背景下,採集端和服務端都很難保證日誌原始的順序:
日誌服務經過給每條日誌附加一些額外的信息以及服務端的關鍵詞查詢能力巧妙地解決了上述難題。原理以下圖所示。
想了解更多有關上下文分析的功能可參考文章上下文查詢、分佈式系統日誌上下文查詢功能。
除了查看日誌的上下文信息,有時咱們也但願可以持續觀察容器的輸出。
下表展現了傳統模式下實時監控容器日誌的方法。
類別 | 步驟 |
---|---|
標準輸出 | 1. 定位容器,獲取容器 id; 2. 使用命令 docker logs –f <container id> 或kubectl logs –f <pod name> 在終端上觀察輸出;3. 使用 grep 或grep –v 過濾關鍵信息。 |
文本日誌 | 1. 定位容器,獲取容器 id; 2. 使用命令 docker exec 或kubectl exec 進入容器;3. 找到目標文件,使用命令 tail –f 觀察輸出;4. 使用 grep 或grep –v 過濾關鍵信息。 |
經過傳統方法監控容器日誌存在如下痛點:
針對這些問題,日誌服務推出了 LiveTail 功能。相比傳統模式,它有以下優勢:
在實現上,LiveTail 主要用到了上一章中提到的上下文查詢原理快速定位目標容器和目標文件。而後,客戶端按期向服務端發送請求,拉取最新數據。
您還能夠經過觀看視頻,進一步理解容器日誌的採集、查詢、分析和可視化等功能。
原文連接本文爲雲棲社區原創內容,未經容許不得轉載。