作者:大飛哥,視源電子運維工程師,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 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/538726.html
標籤:其他
