透過 Filebeat 收集 Infrastructure 中各種服務的細節資訊
本篇學習重點
使用 Filebeat 收集使用主機 (Host) 所佈署的 Infrastructure 當中 Logs 的方式
使用 Filebeat 收集使用容器 (Container) 佈署的 Infrastructure 當中 Logs 的建議做法
使用 Filebeat 收集使用主機 (Host) 所佈署的 Infrastructure 當中的 Logs
當我們使用非容器化的佈署方式,也就是直接在各主機上安裝服務或應用程式時,我們要收集這些機器上的 Logs 時,可能會有二種方式:
直接在服務的機器上安裝 Filebeat
例如我們在一個單純的三層式服務架構之中,有以下三種服務的主機:
Apache Web Server
Java Backend Service
MySQL Database
而我們要收集這幾台機器上的 Logs 時,我們會建議直接在每台主機上安裝 Filebeat,並且在不同的機器上配置不同的 Inputs 與 Modules 設定值,來收取我們希望取得的 Logs,例如:
Apache Web Server
Apache access & error logs
Apache
透過 Apache
module 指定 access
與 error
Logs 的檔案路徑。
Java Backend Service
Application logs
Log
或 filestream
由於 Logs 的格式是自訂義的,直接使用 filestream
來指定要 Logs 的檔案來源路徑,甚至要特別處理的 processors
。
MySQL Database
MySQL logs
MySQL
透過 MySQL
module 指定 error
與 slowlog
Logs 的檔案路徑。
主機本身
主機本身的系統日誌,或是 auth logs
System
透過 System
module 指定 syslog
與 auth
Logs 的檔案路徑。
使用 Shared Drive 的方式收集 Logs
如果有使用 Shared drive 的方式,來簡化『集中化收集日誌』這件事的話,基本上就是在專門運行 Filebeat 的機器上,透過 NFS 之類的 Shared drives 取得各服務的日誌。
使用這種方式,在 Filebeat 的 Inputs 與 Modules 的配置上,沒有特別的差異,只是會一口氣將這些配置設定在同一個 Filebeat 身上,不過有個地方要特別注意,Filebeat 的 Log
與 filestream
input,在使用網路共享或是雲端應商的儲存空間時,因為會使用磁碟機的 inode
資訊與 device id
當作檔案的唯一識別,有時 shared drive 的這個值會改變,導致於已經處理過的檔案,又重新被判斷成是新的檔案,造成重覆的傳送,這部份會要透過自行產生唯一的識別 ID,並且指定 inode_maker
來避免這件事發生,細節請參考 官方文件 - Filebeat Input - Logs。
使用 Filebeat 收集使用容器 (Container) 佈署的 Infrastructure 當中的 Logs
Docker 環境的 Log 產生方式
當我們使用 Docker 來佈署服務時,一般的做法都是在 Container 之中直接把 log 輸出到 stdout
或是 stderr
,並透過 Docker logging driver 去進行處理,而實際的檔案預設會寫在 Docker host 身上,例如在 linux 環境中,會寫到 /var/lib/docker/containers/
的路徑底下。
注意:因為容器的生命週期可能隨時會中斷,一個有良好 scalability 的容器化架構的設計,會是 stateless 的,也就是當容器被關閉時,存在裡面的 logs 就消失了,所以一般絕對不建議把 logs 直接寫在 container 之中,至少也要使用 volume 的方式將 logs 寫到會持久保存的另外的儲存空間裡。
收集所有 Docker Conainer 產生的 Logs
因此我們要使用 Filebeat 來收集所有 Docker Container 產生的 logs 時,我們其實就是針對 Docker host 的這個路徑裡的 logs 下手,這也是 Filebeat Container Inputs 所使用的方法。
注意:Docker Input 已經在 7.2 版時棄用 (deprecated) 了,之後請直接使用 Container Input。
而 Container Input 的設定方式如下:
裡面也可以在 stream
屬性去設定只要針對 stdout
或是 stderr
的內容進行收集,細節可以參考 官方文件 - Filebeat Input - Container。
注意:在這種使用一口氣收集所有 Containers 產生的 logs 時,應該要搭配一些內建的 Processors,例如
add_docker_metadata
、add_kubernetes_metadata
、add_cloud_metadata
,將產生 logs 的 container 或是 pod 的資訊增加在 logs 之中,以便於後續使用時能進行分辨。
使用 Kubernetes DaemonSet 收集 K8S Nodes 身上各 Pods 的 Logs
如同我們前面 使用 Metricbeat 掌握 Infrastructure 的健康狀態 Kubernetes 篇 在介紹 Metricbea 時,提到在 Kubernetes 使用 DaemonSet 的方式同樣的考量,可以確保每個 Node 身上有一個獨立的 Filebeat pod 來進行收集整個 Nodes 上所有 Pods 裡的 logs,並且傳送到 Elasticsearch。
而在 Kubernetes 裡,也如同前面『 Docker 環境的 Log 產生方式』運作的方式一樣,因為 Pods 會是 stateless,因此一般我們也都會直接將 logs 透過 stdout
或是 stderr
送出,並且由運行這些 Pods 所在的 Node,寫在實體的 disk 路徑 /var/log/containers/*.log
之中,因此我們也就可以使用 DaemonSet 的方式來佈署 Filebeat,並且將主機的 /var/log
mount 到 Filebeat 身上,讓他可以直接使用 Container Inputs 的方式,取的這個所有 Pods 產生的 logs。
例如以官方的 filebeat-kubernetes.yaml 為例 (以下僅截取 ConfigMap 與 DaemonSet 的主要配置,完整版請參考原始檔案):
DaemonSet 有宣告 mount
/var/lib/docker/container
以及/var/log
,讓 Filebeat 可以取得 container 的 logs。DaemonSet 有另外宣告
/var/lib/filebeat-data
當作 data 的 volumeMounts 來掛載到 container 內的/var/share/filebeat/data
路徑,讓這個 DaemonSet 的 Filebeat 運作時的檔案,是寫到實體主機的 disk 之中,不會因為重啟而造成資料的遺失。另外有特別使用
add_kubernetes_metadata
的 processor,讓這些一口氣收集進來的各種 Pod 產生的 logs,加上Pod Name
、Pod UID
、Namespace
、Labels
的資訊,讓我們在後續分析處理時,能分辨得出來是哪邊產生的 log。有一段是註解掉的 autodiscovery 的配置,若是使用 Docker、Kubernetes、或是使用 Nomad 時,可以考慮使用 autodiscovery 的機制,讓 container 或是 pod 動態增加時,也能夠由 DaemonSet 自動開始收集新增加容器產生的 logs。
使用 Kubernetes SideCar 的方式收集 K8S Pod 裡服務產生的實體 Logs
如果 Service container 寫的是實體的 Logs 檔案,另一種方式是我們可以使用 SideCar 的方法將 Logs 轉成 stdout
與 stderr
的方式往外傳送,以使用我們先前建議的容器化收集 logs 的方法。
首先將 Pod 中的 Service container 與 Sidecar container 使用 Shared Volume,讓 Sidecar container 能夠直接取得 Service container 產生 的 logs,並且 SideCar container 再負責將這個 logs tail
出來,輸出到 stdout
或 stderr
,這樣後續就能同樣的使用 DaemonSet 或是專門收集 log 的 pod 的機制,進行後續的處理。
參考資料
Last updated