使用 Loki 來觀察 TiDB 日誌

對於一個系統來說,日誌具有非常重要的作用,當我們遇到某個問題,可以直接登錄到機器上面,看看日誌,grep 下關鍵信息,在輔助其他一些手段,多數就能快速定位問題了。但是,對於分佈式系統來說,因爲日誌散落在很多的機器上面,我們不可能人工的登錄到不同的機器查看,而且也沒法對多臺機器上面的日誌進行彙總聚合分析,所以,這裏,我們一定需要一個統一的 Log 管理工具,它不光能幫我們自動的收集所有機器上面的 Log,同時也能讓我們方便的使用各種條件來查詢特定的信息。

在 TiDB 裏面,我們使用的是 fluentbit + Elasticsearch,兩者結合,很好的幫我們解決了上面的需求。不過這裏我要說的,是另一套解決方案 Loki,雖然它現在還不成熟,但因爲是 Grafana 團隊開發的, 所以沒準會成爲 K8s 下面的一套標準。

Loki

根據官網的介紹,Loki 是一個可水平擴展的,高可靠的,支持多租戶的 Log 聚合系統,有點類似於 Prometheus,不過是針對 Log 的。網上已經有很多針對 Loki 的介紹,這裏不重點說明了,我覺得 Loki 有兩點吸引我的地方:

  1. 非常類似 Prometheus,如果大家熟悉了 Prometheus,用 Loki 會非常的習慣,畢竟 Label 這些概念都是一致的。而且 Loki 裏面還可以支持將 Log entry 提取成一個 metrics。
  2. 跟 Grafana 完美結合,不過這需要 Grafana 6.0 及以上版本的支持。

除了 Loki 自身,我們有時候還需要使用另外兩個組件:

  1. Promtail : 用來將不同機器上面的 Log 收集並且發給 Loki
  2. Logcli:Loki 的 cli 客戶端,如果沒有 Grafana,就可以用這個來操作

其實對於 Promtail,大家也可以使用其他的 Log 收集器,譬如著名的 fluentd,fluentbit 這些,然後寫個插件能將 Log 發給 Loki 就成,畢竟 Loki 的 API 足夠簡單,很容易對接。

我是直接從源碼來安裝 Loki 的,參考的這裏,沒什麼難度,唯一想吐槽的就是現在都什麼年代了,Loki 竟然還是使用的 dep + vendor 的方式來管理項目的依賴(貌似最新的已經換成 go mod 方式了)。

運行

首先,我們啓動 Loki,這裏,因爲我只是在本機驗證,所以直接使用的是 Loki 裏面自帶的配置文件:

./loki --config.file=./cmd/loki/loki-local-config.yaml

默認的配置裏面,Loki 是監聽 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”,因爲整個 TiDB 的日誌格式跟 Loki 默認能處理的不一樣,我們需要自己解析出來,這個就是在 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 進行分組聚合。

再就是 timestamp 的處理,因爲我們的日誌裏面包含了時間,所以需要顯示的告訴 Promtail 用我們日誌裏面的時間,不然 Promtail 就會用它自己的當前時間作爲日誌的時間,這個其實就不對了。

TiDB 其他組件也會按照同樣的方式來配置, 當然最後,我們還要啓動整個 TiDB 集羣,參考這裏

Grafana

當整個都啓動起來之後,我們就可以打開 Grafana,參考這裏,將 Loki 加入到 Grafana 中,然後就可以做查詢操作了,譬如下面,我按照 job 來簡單的查詢,得到如下的輸出:

看起來還是挺不錯的,不過唯一讓我有點不爽的就是 timestamp 有點冗餘,Grafana 顯示了兩次時間,這個主要原因在於 Promtail 在處理的時候,仍然會把原始 message 發給 Loki。我沒找到比較好的辦法來解決,沒準用 template 能搞定。

於是我嘗試了另一種方法,自己寫了一個 tidb-to-loki,將 TiDB 的日誌發給 Loki,畢竟我們只需要使用 Loki 的 Push API 就可以了,而且它還支持 JSON 格式,都不用去折騰 Protobuf 的,然後 Grafana 展示如下:

界面清爽了很多,但現在 tidb-to-loki 還只是一個玩具,不可能用於生產,後面還不如增強 Promtail 或者用 fluentbit 這些來搞定吧。

總結

總的來說,受益於 Grafana,我對於 Loki 的未來還是蠻期待的,寫到這裏,不由的現編了一個段子:

曾經,有一位程序員新手跑到一位大師面前,問道:『大師,我寫的服務器程序出現了問題,請告訴我如何快速找到問題?』

大師:『日誌』。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章