作者:大飛哥,視源電子運維工程師,KubeSphere 使用者委員會廣州站站長
採集落盤日誌
日誌採集,通常使用 EFK 架構,即 ElasticSearch
,Filebeat
,Kibana
,這是在主機日誌採集上非常成熟的方案,但在容器日誌採集方面,整體方案就會複雜很多。我們現在面臨的需求,就是要採集容器中的落盤日誌。
容器日誌分為標準輸出日誌和落盤日誌兩種。應用將日誌列印在容器標準輸出 STDOUT
中,由容器執行時(Docker 或 Containerd)把標準輸出日誌寫入容器日誌檔案中,最終由採集器匯出。這種日誌列印採集是業界推薦方案。但對於不列印標準輸出而直接將日誌落盤的情況,業界最常用見的方案是,使用 Sidecar
採集落盤日誌,把落盤日誌列印到容器標準輸出中,再利用標準輸出日誌的採集方式輸出。
對於 KubeSphere 使用者,只需要兩步即可:第一在專案中開啟收集捲上日誌
,第二在工作負載中配置落盤檔案路徑。具體操作見下圖所示。
上述兩個步驟,會自動在容器中注入 Filebeat Sidecar
作為 logging-agent,將落盤日誌列印輸出在容器標準輸出中。Filebeat 配置可透過 ConfigMap 修改。
$ kubectl get cm -n kubesphere-logging-system logsidecar-injector-configmap -o yaml
## Filebeat 配置
filebeat.inputs:
- type: log
enabled: true
paths:
{{range .Paths}}
- {{.}}
{{end}}
output.console:
codec.format:
string: '%{[log.file.path]} %{[message]}'
logging.level: warning
接入第三方日誌服務
預設 KubeSphere 將日誌採集到叢集內建 Elasticsearch 中,資料儲存週期為 7 天,這對於生產服務動輒 180 天的日誌儲存需求,顯然無法滿足。企業運維團隊都會建立集中化的日誌服務,將叢集內日誌接入到第三方日誌服務中,已是必然選擇。我們來看如何操作。
上文說到,容器執行時會將標準輸出日誌,落盤寫入到叢集節點的日誌檔案中,Linux 系統預設在 /var/log/containers/*.log
。KubeSphere 使用 FluentBit
以 DemonSet
形式在各叢集節點上採集日誌,由 FluentBit 輸出給 ElasticSearch 服務。具體配置可參考如下兩個配置:
$ kubectl get Input -n kubesphere-logging-system tail -o yaml
$ kubectl get Output -n kubesphere-logging-system es -o yaml
我們把日誌匯出到第三方日誌服務,那就需要定製 FluentBit 輸入輸出。使用 tail
外掛採集 /var/log/containers/flux-wms-*.log
檔案中的日誌,輸出到 Kafka
中。可參考如下配置:
---
apiVersion: logging.kubesphere.io/v1alpha2
kind: Input
metadata:
labels:
logging.kubesphere.io/component: logging
logging.kubesphere.io/enabled: "true"
name: kafka-flux-wms
namespace: kubesphere-logging-system
spec:
tail:
db: /fluent-bit/tail/pos.db
dbSync: Normal
memBufLimit: 5MB
path: /var/log/containers/flux-wms-*.log
refreshIntervalSeconds: 10
tag: fluxwms.*
---
apiVersion: logging.kubesphere.io/v1alpha2
kind: Output
metadata:
annotations:
kubesphere.io/creator: admin
labels:
logging.kubesphere.io/component: logging
logging.kubesphere.io/enabled: "true"
name: kafka-flux-wms
namespace: kubesphere-logging-system
spec:
kafka:
brokers: xxx.xxx.xxx.xxx:9092
topics: my-topic
match: fluxwms.*
值得注意的是,目前 FluentBit 不支援 Kafka 認證。
多行日誌的尷尬
原本以為至此就可萬事大吉,沒想到消費 kafka 日誌時突然看到,某些日誌被拆得七零八碎,不忍入目。為了支援多行日誌,直觀的想法,就是逐個元件往前排查。
前方有坑,請小心閱讀。
配置 FluentBit 支援多行日誌
FluentBit 對多行日誌的支援,需要配置 Parser,並透過 parserFirstline
指定日誌 Parser,用以解析出多行日誌塊的第一行。官方參考文件,Parser 正規表示式,根據 Filebeat 日誌輸出格式而定,可參考上文或直接看這段:string: '%{[log.file.path]} %{[message]}'
。
---
apiVersion: logging.kubesphere.io/v1alpha2
kind: Input
metadata:
labels:
logging.kubesphere.io/component: logging
logging.kubesphere.io/enabled: "true"
name: kafka-flux-wms
namespace: kubesphere-logging-system
spec:
tail:
db: /fluent-bit/tail/pos.db
dbSync: Normal
memBufLimit: 5MB
path: /var/log/containers/flux-wms-*.log
multiline: true
parserFirstline: kafka-flux-wms
refreshIntervalSeconds: 10
tag: fluxwms.*
---
apiVersion: logging.kubesphere.io/v1alpha2
kind: Parser
metadata:
labels:
logging.kubesphere.io/component: logging
logging.kubesphere.io/enabled: "true"
name: kafka-flux-wms
namespace: kubesphere-logging-system
spec:
regex:
regex: '^\/data\/business-logs\/[^\s]*'
配置 Filebeat 支援多行日誌
檢視 kakfka 訊息,多行日誌仍然被拆分。難道 Filebeat 沒有支援多行日誌嗎?整個落盤日誌採集鏈條中,只要有一個環節不支援多行日誌,就會導致結果不及預期。檢視專案原始日誌檔案,發現多行日誌以時間格式開頭,於是 Filebeat 增加如下配置:
filebeat.inputs:
- type: log
enabled: true
paths:
{{range .Paths}}
- {{.}}
{{end}}
multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'
multiline.negate: true
multiline.match: after
multiline.max_lines: 100
multiline.timeout: 10s
output.console:
codec.format:
string: '%{[log.file.path]} %{[message]}'
logging.level: warning
進入 Sidecar 容器,使用如下命令測試 Filebeat 輸出,確認正確分割多行日誌。
$ filebeat -c /etc/logsidecar/filebeat.yaml
不可忽視的容器執行時
按理說,FluentBit 和 Filebeat 都支援了多行日誌,kafka 應該可以正確輸出多行日誌,但結果令人失望。肯定還有哪個環節被遺漏了,在登入叢集節點主機檢視容器標準輸出日誌時,這個被忽視的點被發現啦!
## 此處直接檢視你的專案容器
$ tail -f /var/log/containers/*.log
你會發現,日誌都是 JSON
格式,並且日誌是逐行輸出的,也就是說,沒有支援多行日誌塊。本地 kubernetes 叢集使用 Docker 作為容器執行時,來檢視它的配置:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 10,
"bip": "192.168.100.1/24",
"storage-driver": "overlay2",
"storage-opts": ["overlay2.override_kernel_check=true"]
}
log-driver
配置為json-file
, 這也是官方預設配置,可參考官方說明,除 json 格式外,還支援如下格式:
- local
- gelf
- syslog
- fluentd
- loki
顯然其他格式也並不理想,而且對於生產環境,切換容器執行時日誌格式,影響還是蠻大的。探索至此,這條路子難度偏大風險過高,暫時先擱置,待到身心愜意時接著玩。
去掉中間商,直達 kafka
既然上面的路子走不通,那就換個思路。Filebeat 也是 logging-agent,是支援輸出日誌到 Kafka 的,為何不省去中間環節,直奔主題呢?
$ kubectl edit cm -n kubesphere-logging-system logsidecar-injector-configmap
filebeat.inputs:
- type: log
enabled: true
paths:
{{range .Paths}}
- {{.}}
{{end}}
multiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'
multiline.negate: true
multiline.match: after
multiline.max_lines: 100
multiline.timeout: 10s
output.kafka:
enabled: true
hosts:
- XXX.XXX.XXX.XXX:9092
topic: sycx-cmes-app
## output.console:
## codec.format:
## string: '%{[log.file.path]} %{[message]}'
logging.level: warning
當看到 Kafka 消費者輸出完美多行日誌塊時,腦後傳來多巴胺的快感!再看一眼架構圖,我們們來做總結!
總結
最初我去 KubeSphere 社群論壇搜尋日誌採集相關帖子時,有朋友說無法實現。看到他的回覆,心底一陣絕望。如今看來,某種角度上說,他的回答沒錯,他只是說那條路走不通,但他沒說那條路能走通。
本文由部落格一文多發平臺 OpenWrite 釋出!