對于一個系統(tǒng)來說,日志具有非常重要的作用,當(dāng)我們遇到某個問題蜂林,可以直接登錄到機(jī)器上面耗跛,看看日志,grep 下關(guān)鍵信息,在輔助其他一些手段,多數(shù)就能快速定位問題了。但是脚作,對于分布式系統(tǒng)來說,因?yàn)槿罩旧⒙湓诤芏嗟臋C(jī)器上面犁河,我們不可能人工的登錄到不同的機(jī)器查看鳖枕,而且也沒法對多臺機(jī)器上面的日志進(jìn)行匯總聚合分析,所以桨螺,這里宾符,我們一定需要一個統(tǒng)一的 Log 管理工具,它不光能幫我們自動的收集所有機(jī)器上面的 Log灭翔,同時也能讓我們方便的使用各種條件來查詢特定的信息魏烫。
在 TiDB 里面,我們使用的是 fluentbit + Elasticsearch肝箱,兩者結(jié)合哄褒,很好的幫我們解決了上面的需求。不過這里我要說的煌张,是另一套解決方案 Loki呐赡,雖然它現(xiàn)在還不成熟,但因?yàn)槭?Grafana 團(tuán)隊(duì)開發(fā)的骏融, 所以沒準(zhǔn)會成為 K8s 下面的一套標(biāo)準(zhǔn)链嘀。
Loki
根據(jù)官網(wǎng)的介紹萌狂,Loki 是一個可水平擴(kuò)展的,高可靠的怀泊,支持多租戶的 Log 聚合系統(tǒng)茫藏,有點(diǎn)類似于 Prometheus,不過是針對 Log 的霹琼。網(wǎng)上已經(jīng)有很多針對 Loki 的介紹务傲,這里不重點(diǎn)說明了,我覺得 Loki 有兩點(diǎn)吸引我的地方:
- 非常類似 Prometheus枣申,如果大家熟悉了 Prometheus售葡,用 Loki 會非常的習(xí)慣,畢竟 Label 這些概念都是一致的糯而。而且 Loki 里面還可以支持將 Log entry 提取成一個 metrics天通。
- 跟 Grafana 完美結(jié)合泊窘,不過這需要 Grafana 6.0 及以上版本的支持熄驼。
除了 Loki 自身,我們有時候還需要使用另外兩個組件:
- Promtail : 用來將不同機(jī)器上面的 Log 收集并且發(fā)給 Loki
- Logcli:Loki 的 cli 客戶端烘豹,如果沒有 Grafana瓜贾,就可以用這個來操作
其實(shí)對于 Promtail,大家也可以使用其他的 Log 收集器携悯,譬如著名的 fluentd祭芦,fluentbit 這些,然后寫個插件能將 Log 發(fā)給 Loki 就成憔鬼,畢竟 Loki 的 API 足夠簡單龟劲,很容易對接。
我是直接從源碼來安裝 Loki 的轴或,參考的這里昌跌,沒什么難度,唯一想吐槽的就是現(xiàn)在都什么年代了照雁,Loki 竟然還是使用的 dep + vendor 的方式來管理項(xiàng)目的依賴(貌似最新的已經(jīng)換成 go mod 方式了)蚕愤。
運(yùn)行
首先,我們啟動 Loki饺蚊,這里萍诱,因?yàn)槲抑皇窃诒緳C(jī)驗(yàn)證,所以直接使用的是 Loki 里面自帶的配置文件:
./loki --config.file=./cmd/loki/loki-local-config.yaml
默認(rèn)的配置里面污呼,Loki 是監(jiān)聽 3100 端口裕坊。
然后就是啟動 Promtail 了,這里要在配置文件里面配置如何讓 Promtail 去抓取 TiDB 集群的日志:
scrape_configs:
- job_name: tikv
pipeline_stages:
- regex:
expression: '\[(?P<time>\d{4}\/\d{2}\/\d{2}.\d{2}:\d{2}:\d{2}.\d{3}.\+\d{2}:\d{2})\].\[(?P<level>\w*)\].\[(?P<source>\w.*):(?P<line>\d*)\].(?P<message>.*$)'
- labels:
level:
- timestamp:
format: 2006/01/02 15:04:05.000 -07:00
source: time
static_configs:
- targets:
- localhost
labels:
job: tikv
__path__: /var/tikv*.log
上面的例子是 Prometheus 抓取 TiKV 日志的配置燕酷,job 的名字就是 “tikv”籍凝,因?yàn)檎麄€ TiDB 的日志格式跟 Loki 默認(rèn)能處理的不一樣映企,我們需要自己解析出來,這個就是在 regex 的 expression 定義的正則静浴,用來匹配類似如下的 Log 格式:
[2019/07/21 17:26:36.484 +08:00] [INFO] [peer.rs:142] ["create peer"] [peer_id=31] [region_id=30]
具體格式定義堰氓,大家可以參考這里。
然后我們在額外定義了一個 label level苹享,也就是 Loki 到時候會按照 Log level 對 log 進(jìn)行分組聚合双絮。
再就是 timestamp 的處理,因?yàn)槲覀兊娜罩纠锩姘藭r間得问,所以需要顯示的告訴 Promtail 用我們?nèi)罩纠锩娴臅r間囤攀,不然 Promtail 就會用它自己的當(dāng)前時間作為日志的時間,這個其實(shí)就不對了宫纬。
TiDB 其他組件也會按照同樣的方式來配置焚挠, 當(dāng)然最后,我們還要啟動整個 TiDB 集群漓骚,參考這里蝌衔。
Grafana
當(dāng)整個都啟動起來之后,我們就可以打開 Grafana蝌蹂,參考這里噩斟,將 Loki 加入到 Grafana 中,然后就可以做查詢操作了孤个,譬如下面剃允,我按照 job 來簡單的查詢,得到如下的輸出:
看起來還是挺不錯的齐鲤,不過唯一讓我有點(diǎn)不爽的就是 timestamp 有點(diǎn)冗余斥废,Grafana 顯示了兩次時間,這個主要原因在于 Promtail 在處理的時候给郊,仍然會把原始 message 發(fā)給 Loki牡肉。我沒找到比較好的辦法來解決,沒準(zhǔn)用 template 能搞定丑罪。
于是我嘗試了另一種方法荚板,自己寫了一個 tidb-to-loki,將 TiDB 的日志發(fā)給 Loki吩屹,畢竟我們只需要使用 Loki 的 Push API 就可以了跪另,而且它還支持 JSON 格式,都不用去折騰 Protobuf 的煤搜,然后 Grafana 展示如下:
界面清爽了很多免绿,但現(xiàn)在 tidb-to-loki 還只是一個玩具,不可能用于生產(chǎn)擦盾,后面還不如增強(qiáng) Promtail 或者用 fluentbit 這些來搞定吧嘲驾。
總結(jié)
總的來說淌哟,受益于 Grafana,我對于 Loki 的未來還是蠻期待的辽故,寫到這里徒仓,不由的現(xiàn)編了一個段子:
曾經(jīng),有一位程序員新手跑到一位大師面前誊垢,問道:『大師掉弛,我寫的服務(wù)器程序出現(xiàn)了問題,請告訴我如何快速找到問題喂走?』
大師:『日志』殃饿。