一 前言
前段時間, iLogtail [1]阿里千萬例項可觀測採集器開源,其中介紹了iLogtail採集效能可以達到單核100MB/s,相比開源採集Agent有5-10倍效能優勢。很多小夥伴好奇iLogtail具體的效能資料和資源消耗如何,本文將針對目前業界使用度較高且效能相對較優的Agent FileBeat進行對比,測試這兩個Agent在不同壓力場景下的表現如何。
二 測試試驗描述
隨著Kubernetes 普及,Kubernetes 下的日誌收集的需求也日益常態化,因此下文將分別進行容器標準輸出流採集與容器內靜態檔案採集對比試驗(使用靜態檔案採集的小夥伴可以參考容器內靜態檔案採集對比試驗, iLogtail 純靜態檔案採集會略優於試驗2容器內檔案靜態採集),試驗項具體如下:
-
實驗1:恆定採集配置4,Filebeat & iLogtail 在原始日誌產生速率 1M/s、2M/s、 3M/s 下的標準輸出流採集效能對比。
-
實驗2:恆定採集配置4,Filebeat & iLogtail 在原始日誌產生速率 1M/s、2M/s、 3M/s 下的容器內檔案採集效能對比。
而在真實的生產環境中,日誌採集元件的可運維性也至關重要,為運維與後期升級便利,相比於Sidecar模式,K8s下采用Daemonset模式部署採集元件更加常見。但由於Daemonset 同時將整個叢集的採集配置下發到各個採集節點的特性,單個採集節點正在工作的配置必定小於全量採集配置數目,因此我們還會進行以下2部分試驗,驗證採集配置的膨脹是否會影響採集器的工作效率:
-
實驗3:恆定輸入速率3M/s,Filebeat & iLogtail 在採集配置50、100、500、1000 份下的標準輸出流採集效能對比。
-
實驗4:恆定輸入速率3M/s,Filebeat & iLogtail 在採集配置50、100、500、1000 份下的容器內檔案採集效能對比。
最後會進行iLogtail 的大流量壓測,具體如下:
-
實驗5:iLogtail 在 5M/s、10M/s、10M/s、40M/s 下的標準輸出流採集效能。
-
實驗6:iLogtail 在 5M/s、10M/s、10M/s、40M/s 下的容器內檔案採集效能。
三 試驗環境
所有對比實驗配置儲存於[2], 感興趣的同學可以自己動手進行整個對比測試實驗, 以下部分分別描述了不同採集模式的具體配置,如果只關心採集對比結果,可以直接跳過此部分繼續閱讀。
1 環境
節點配置:ecs.g6.xlarge (4 vCPU 16GB) 磁碟ESSD
2 資料來源
對於資料來源,我們首先去除因正則解析或多行拼接能力帶來的差異,僅僅以最基本的單行採集進行對比,資料產生源模擬產生nginx訪問日誌,單條日誌大小為283B,以下配置描述了1000條/s 速率下的輸入源:
apiVersion: batch/v1
kind: Job
metadata:
name: nginx-log-demo-0
namespace: default
spec:
template:
metadata:
name: nginx-log-demo-0
spec:
restartPolicy: Never
containers:
-name: nginx-log-demo-0
image: registry.cn-hangzhou.aliyuncs.com/log-service/docker-log-test:latest
command: ["/bin/mock_log"]
args: ["--log-type=nginx", "--path=/var/log/medlinker/access.log", "--total-count=1000000000", "--log-file-size=1000000000", "--log-file-count=2", "--logs-per-sec=1000"]
volumeMounts:
-name: path
mountPath: /var/log/medlinker
subPath: nginx-log-demo-0
resources:
limits:
memory: 200Mi
requests:
cpu: 10m
memory: 10Mi
volumes:
-name: path
hostPath:
path: /testlog
type: DirectoryOrCreate
nodeSelector:
kubernetes.io/hostname: cn-beijing.192.168.0.140
3 Filebeat 標準輸出流採集配置
Filebeat 原生支援容器檔案採集,透過add_kubernetes_metadata元件增加kubernetes 元資訊,為避免輸出元件導致的效能差異,透過drop_event外掛丟棄資料,避免輸出,filebeat測試配置如下(harvester_buffer_size 調整設定為512K,filebeat.registry.flush: 30s,queue.mem 引數適當擴大,增加吞吐):
filebeat.yml: |-
filebeat.registry.flush: 30s
processors:
-add_kubernetes_metadata:
host: ${NODE_NAME}
matchers:
-logs_path:
logs_path: "/var/log/containers/"
-drop_event:
when:
equals:
input.type: container
output.console:
pretty: false
queue:
mem:
events: 4096
flush.min_events: 2048
flush.timeout: 1s
max_procs: 4
filebeat.inputs:
-type: container
harvester_buffer_size: 524288
paths:
-/var/log/containers/nginx-log-demo-0-*.log
4 Filebeat 容器檔案採集配置
Filebeat 原生不支援容器內檔案採集,因此需要人工將日誌列印路徑掛載於宿主機HostPath,這裡我們使用 subPath以及DirectoryOrCreate功能進行服務列印路徑的分離, 以下為模擬不同服務日誌列印路徑獨立情況。
filebeat 使用基礎日誌讀取功能讀取/testlog路徑下的日誌,為避免輸出元件導致的效能差異,透過drop_event外掛丟棄資料,避免輸出,測試配置如下(harvester_buffer_size 調整設定為512K,filebeat.registry.flush: 30s,queue.mem 引數適當擴大,增加吞吐):
filebeat.yml: |-
filebeat.registry.flush: 30s
output.console:
pretty: false
queue:
mem:
events: 4096
flush.min_events: 2048
flush.timeout: 1s
max_procs: 4
filebeat.inputs:
-type: log
harvester_buffer_size: 524288
paths:
-/testlog/nginx-log-demo-0/*.log
processors:
-drop_event:
when:
equals:
log.file.path: /testlog/nginx-log-demo-0/access.log
5 iLogtail 標準輸出流採集配置
iLogtail 原生同樣支援標準輸出流採集,service_docker_stdout 元件已經會提取kubernetes 元資訊,為避免輸出元件導致的效能差異,透過processor_filter_regex,進行所有日誌的過濾,測試配置如下:
{
"inputs":[
{
"detail":{
"ExcludeLabel":{
},
"IncludeLabel":{
"io.kubernetes.container.name":"nginx-log-demo-0"
}
},
"type":"service_docker_stdout"
}
],
"processors":[
{
"type":"processor_filter_regex",
"detail":{
"Exclude":{
"_namespace_":"default"
}
}
}
]
}
6 iLogtail 容器檔案採集配置
iLogtail 原生支援容器內檔案採集,但由於檔案內採集元資訊存在於tag標籤,暫無過濾外掛,為避免輸出元件導致的效能差異,因此我們使用空輸出外掛進行輸出,測試配置如下:
{
"metrics":{
"c0":{
"advanced":{
"k8s":{
"IncludeLabel":{
"io.kubernetes.container.name":"nginx-log-demo-0"
}
}
},
......
"plugin":{
"processors":[
{
"type":"processor_default"
}
],
"flushers":[
{
"type":"flusher_statistics",
"detail":{
"RateIntervalMs":1000000
}
}
]
},
"local_storage":true,
"log_begin_reg":".*",
"log_path":"/var/log/medlinker",
......
}
}
}
四 Filebeat與iLogtail對比測試
Filebeat 與 iLogtail 的對比項主要包含以下內容:標準輸出流採集效能、容器內檔案採集效能、標準輸出流多使用者配置效能、容器內檔案多使用者配置效能以及大流量採集效能。
1 標準輸出流採集效能對比
輸入資料來源: 283B/s, 底層容器contianerd,標準輸出流膨脹後為328B, 共4個輸入源:
以下顯示了標準輸出流不同採集的效能對比,可以看到iLogtail相比於Filebeat 有十倍級的效能優勢(CPU的百分比為單核的百分比):
以下顯示了標準輸出流不同採集的記憶體對比,可以看到logtail 和filebeat 整體記憶體相差不大,沒有出現隨採集流量上升記憶體暴漲情況:
2 容器內檔案採集效能對比
以下顯示了容器內檔案不同採集的效能對比,Filebeat 容器內檔案由於與container 採集共用採集元件,並省略了Kubernets meta 相關元件,所以相比於標準輸出流採集有大效能提升,iLogtail 的容器內檔案採集採用Polling + inotify機制,同樣相比於容器標準輸出流採集有效能提升, 但可以看到iLogtail相比於Filebeat 有5倍級的效能優勢(CPU的百分比為單核的百分比):
以下顯示了標準輸出流不同採集的記憶體對比,可以看到logtail 和filebeat 整體記憶體相差不大,沒有出現隨採集流量上升記憶體暴漲情況:
3 採集配置膨脹效能對比
採集配置膨脹效能對比,輸入源設定為4,總輸入速率為3M/s, 分別進行50採集配置,100採集配置,500採集配置,1000採集配置 對比。
標準輸出流採集配置膨脹對比
以下顯示了標準輸出流不同採集的效能對比,可以看到Filebeat 由於容器採集與靜態檔案採集底層共用相同靜態檔案採集邏輯,會在標準輸出流採集路徑var/log/containers下存在大量正則匹配的工作,可以看到雖然採集資料量沒有增加由於採集配置的增加,CPU消耗增加10%+,而iLogtail 針對容器採集模型全域性共享容器路徑發現機制,所以避免了正則邏輯帶來的效能損耗(CPU的百分比為單核的百分比)。
在記憶體膨脹方面,可以看到不論是Filebeat 還是iLogtail 都存在由於採集配置增加導致的記憶體膨脹,但2者的膨脹大小都處於可接受範圍。
容器內檔案採集配置膨脹對比
以下顯示了容器內檔案採集不同採集器的效能對比,可以看到Filebeat 靜態檔案採集由於避免標準輸出流通用路徑正則,相較於標準增加CPU消耗較少,而iLogtail CPU 變化同樣很小,且相比於標準輸出流採集效能略好(CPU的百分比為單核的百分比)。
在記憶體膨脹方面,同樣可以看到不論是Filebeat 還是iLogtail 都存在由於採集配置增加導致的記憶體膨脹,但2者的膨脹大小都處於可接受範圍。
4 iLogtail 採集效能測試
由於FileBeat在日誌量大的場景下出現採集延遲問題,所以以下場景僅針對iLogtail進行測試,分別在5M/s、10M/s、20M/s 下針對iLogtail 進行容器標準輸出流採集與容器內檔案採集的效能壓測。
-
5M/s 對應日誌速率 18526條/s,單輸入源產生速率1852條/s
-
10M/s 對應日誌速率 37052條/s,單輸入源產生速率3705條/s
-
20M/s 對應日誌速率 74104條/s,單輸入源產生速率7410條/s
-
40M/s 對應日誌速率 148208條/s,單輸入源產生速率14820條/s
和上述試驗類似可以看到CPU消耗方面容器檔案採集略好於容器標準輸出流採集效能(CPU的百分比為單核的百分比),主要是由於容器檔案採集底層Polling + inotify機制。
在記憶體方面,由於標準輸出流採集主要依賴於GO,而容器檔案採集主要依賴於C,可以由於GC機制的存在,隨著速率的上升,標準輸出流採集消耗的記憶體會逐漸超過容器內檔案採集消耗的記憶體。
5 對比總結
|
|
|
同流量輸入下,iLogtail 相較於Filebeat 十倍級別效能
|
iLogtail 與Filebeat 記憶體消耗差異不大。
|
|
同流量輸入下,iLogtail 相較於Filebeat 5倍級別效能
|
iLogtail 與Filebeat 記憶體消耗差異不大。
|
|
同流量輸入下,隨著採集配置增加,Filebeat CPU 增加量為iLogtail CPU增加量的3倍。
|
iLogtail 與Filebeat 都會因採集配置增加產生記憶體膨脹,都處於可接受範圍。
|
|
同流量輸入下,隨著採集配置增加,Filebeat CPU 增加量為iLogtail CPU增加量的2倍。
|
iLogtail 與Filebeat 都會因採集配置增加產生記憶體膨脹,都處於可接受範圍。
|
五 為什麼Filebeat 容器標準輸出與檔案採集差異巨大?
透過上述試驗可以看到FIlebeat 在不同工作模式下有較大的CPU差異,透過dump 容器標準輸出流採集的pprof 可以得到如下火焰圖,可以看到Filebeat 容器採集下的add_kubernets_meta 外掛是效能瓶頸,同時FIlebeat 的add_kubernets_meta 採用與每個節點監聽api-server 模式,也存在api-server 壓力問題。
而iLogtail 取kubernetes meta 完全是相容kubernetes CRI 協議,直接透過kubernets sandbox 進行meta 資料讀取,保證了iLogtail 的高效能採集效率。
六 iLogtail DaemonSet 場景最佳化
透過以上對比,可以看到iLogtail 相比於Filebeat 具有了優秀的記憶體以及CPU 消耗,有小夥伴可能好奇iLogtail 擁有如此極致效能背後原因,下文主要講解iLogtail Daemonset 場景下的最佳化,如何讓容器資料採集擁有與靜態檔案採集同樣的使用與效能體驗,其他最佳化特性如inotify 等請參考 Logtail技術分享一與 Logtail技術分享二。
首先對於標準輸出流場景,相比於其他開源採集器,例如Filebeat 或Fluentd。一般都是透過監聽var/log/containers 或 /var/log/pods/ 實現容器標準輸出流檔案的採集,比如/var/log/pods/ 的路徑結構為: /var/log/pods/<namespace>_<pod_name>_<pod_id>/<container_name>/, 透過此路徑複用物理機靜態檔案採集模式進行採集。
而對於iLogtail,做到了容器化的全支援,iLogtail 透過發現機制,全域性維護對Node 節點容器的列表,並即時監聽與維護此容器列表。當我們擁有容器列表後,我們便具有了如下優勢:
-
採集路徑不在依賴於靜態配置路徑,可以靠容器標籤動態選擇採集源,從而簡化使用者接入成本。
-
可以根據容器元資訊探測容器自動掛載節點的動態路徑,所以iLogtail 無需掛載即可採集容器內檔案,而如Filebeat 等採集器需要將容器內路徑掛載於宿主機路徑,再進行靜態檔案採集。
-
對於新接入採集配置複用歷史容器列表,快速接入採集,而對於空採集配置,由於容器發現全域性共享機制的存在,也就避免了存在空輪訓監聽路徑機制的情況,進而保證了在容器這樣動態性極高的環境中,iLogtail 可運維性的成本達到可控態。
七 結語
綜上所述,在動態性極高的Kubernetes 環境下,iLogtail不會因為採用Daemonset 的部署模型帶來的多配置問題,造成記憶體大幅度膨脹,而且在靜態檔案採集方面,iLogtail 擁有5倍左右的效能優勢,而對於標準輸出流採集,由於iLogtail 的採集機制,iLogtail 擁有約10倍左右的效能優勢。但是相比於Filebeat 或Fluentd 等老牌開源產品,在文件建設與社群建設上還欠缺很多,歡迎對iLogtail 感興趣的小夥伴一起參與進來,共同打造易用且高效能的iLogtail產品。
參考文獻
https://zhuanlan.zhihu.com/p/29303600
https://www.sohu.com/a/205324880_465959
https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-container.html
https://www.elastic.co/guide/en/beats/filebeat/current/running-on-kubernetes.html