您當前的位置:首頁 > 遊戲

Grafana Loki開源日誌聚合系統代替ELK或EFK

作者:由 王奧 發表于 遊戲時間:2020-11-03

Grafana Loki開源日誌聚合系統代替ELK或EFK

前言

在對公司容器雲的日誌方案進行設計的時候,發現主流的 ELK (Elasticsearch,

Logstash

, Kibana) 或者 EFK (Elasticsearch,

Filebeat

or

Fluentd

, Kibana) 比較重,再加上現階段對於 ES 複雜的搜尋功能很多都用不上,最終選擇了 Grafana 開源的 Loki 日誌系統。下面我們來介紹下 Loki 的一些基本概念和架構,當然 EFK 作為業界成熟的日誌聚合解決方案也是大家應該需要熟悉和掌握的。

Loki 2。0 released: Transform logs as you’re querying them, and set up alerts within Loki, Loki 2。0 大版本更新後更好用了

更新歷史

2020年10月02日 - 初稿

閱讀原文 -

https://

wsgzao。github。io/post/l

oki/

Loki簡介

Grafana Loki is a set of components that can be composed into a fully featured logging stack。

Unlike other logging systems, Loki is built around the idea of only indexing metadata about your logs: labels (just like Prometheus labels)。 Log data itself is then compressed and stored in chunks in object stores such as S3 or GCS, or even locally on the filesystem。 A small index and highly compressed chunks simplifies the operation and significantly lowers the cost of Loki。

Loki 是 Grafana Labs 團隊最新的開源專案,是一個水平可擴充套件,高可用性,多租戶的日誌聚合系統。它的設計非常經濟高效且易於操作,因為它不會為日誌內容編制索引,而是為每個日誌流編制一組標籤,專門為 Prometheus 和 Kubernetes 使用者做了相關最佳化。該專案受 Prometheus 啟發,官方的介紹就是:

Like Prometheus,But For Logs。

,類似於 Prometheus 的日誌系統。

專案地址:

https://

github。com/grafana/loki

/

與其他日誌聚合系統相比, Loki 具有下面的一些特性:

不對日誌進行全文索引。透過儲存壓縮非結構化日誌和僅索引元資料,Loki 操作起來會更簡單,更省成本。

透過使用與 Prometheus 相同的標籤記錄流對日誌進行索引和分組,這使得日誌的擴充套件和操作效率更高。

特別適合儲存 Kubernetes Pod 日誌; 諸如 Pod 標籤之類的元資料會被自動刪除和編入索引。

受 Grafana 原生支援。

背景和動機

當我們的容器雲執行的應用或者某個節點出現問題了,解決思路應該如下:

Grafana Loki開源日誌聚合系統代替ELK或EFK

我們的監控使用的是基於 Prometheus 體系進行改造的,Prometheus 中比較重要的是 Metric 和 Alert,Metric 是來說明當前或者歷史達到了某個值,Alert 設定 Metric 達到某個特定的基數觸發了告警,但是這些資訊明顯是不夠的。

我們都知道,Kubernetes 的基本單位是 Pod,Pod 把日誌輸出到 Stdout 和 Stderr,平時有什麼問題我們通常在介面或者透過命令檢視相關的日誌。

舉個例子:當我們的某個 Pod 的記憶體變得很大,觸發了我們的 Alert。這時管理員,去頁面查詢確認是哪個 Pod 有問題,然後要確認 Pod 記憶體變大的原因,我們還需要去查詢 Pod 的日誌,如果沒有日誌系統,那麼我們就需要到頁面或者使用命令進行查詢:

Grafana Loki開源日誌聚合系統代替ELK或EFK

如果,這個時候應用突然掛了,這個時候我們就無法查到相關的日誌了。所以需要引入日誌系統,統一收集日誌。而使用 ELK 的話,就需要在 Kibana 和 Grafana 之間切換,影響使用者體驗。所以 ,Loki 的第一目的就是最小化度量和日誌的切換成本,有助於減少異常事件的響應時間和提高使用者的體驗。

ELK 存在的問題

現有的很多日誌採集的方案都是採用全文檢索對日誌進行索引(如 ELK 方案),優點是功能豐富,允許複雜的操作。但是,這些方案往往規模複雜,資源佔用高,操作苦難。很多功能往往用不上,大多數查詢只關注一定時間範圍和一些簡單的引數(如:host、service 等),使用這些解決方案就有點殺雞用牛刀的感覺了。

Grafana Loki開源日誌聚合系統代替ELK或EFK

因此,Loki 的第二個目的是,在查詢語言的易操作性和複雜性之間可以達到一個權衡。

成本考量

全文檢索的方案也帶來成本問題,簡單的說就是全文搜尋(如:ES)的倒排索引的切分和共享的成本較高。後來出現了其他不同的設計方案,如:

OKlog

專案地址:

https://

github。com/oklog/oklog

採用最終一致的、基於網格的分佈策略。這兩個設計決策提供了大量的成本降低和非常簡單的操作,但是查詢不夠方便。因此,Loki 的第三個目的是,提供一個更具成本效益的解決方案。

整體架構

Loki 的架構如下:

Grafana Loki開源日誌聚合系統代替ELK或EFK

不難看出,Loki 的架構非常簡單,主要由以下 3 個部分組成:

Loki 是主伺服器,負責儲存日誌和處理查詢。

Promtail是代理,負責收集日誌並將其傳送給 Loki 。

Grafana 用於 UI 展示。

Loki 使用了和 Prometheus 一樣的標籤來作為索引。也就是說,你透過這些標籤既可以查詢日誌的內容也可以查詢到監控的資料,不但減少了兩種查詢之間的切換成本,也極大地降低了日誌索引的儲存。

Loki 使用與 Prometheus 相同的服務發現和標籤重新標記庫,編寫了 Pormtail。在 Kubernetes 中 Promtail 以 DaemonSet 方式執行在每個節點中,透過 Kubernetes API 得到日誌的正確元資料,並將它們傳送到 Loki。下面是日誌的儲存架構:

Grafana Loki開源日誌聚合系統代替ELK或EFK

讀寫

日誌資料的寫主要依託的是 Distributor 和 Ingester 兩個元件,整體的流程如下:

Grafana Loki開源日誌聚合系統代替ELK或EFK

Distributor

一旦 Promtail 收集日誌並將其傳送給 Loki,Distributor 就是第一個接收日誌的元件。由於日誌的寫入量可能很大,所以不能在它們傳入時將它們寫入資料庫。這會毀掉資料庫。我們需要批處理和壓縮資料。

Loki 透過構建壓縮資料塊來實現這一點,方法是在日誌進入時對其進行 Gzip 操作。元件 Ingester 是一個有狀態的元件,負責構建和重新整理 Chunck,當 Chunk 達到一定的數量或者時間後,重新整理到儲存中去。每個流的日誌對應一個 Ingester,當日志到達 Distributor 後,根據元資料和 Hash 演算法計算出應該到哪個 Ingester 上面。

Grafana Loki開源日誌聚合系統代替ELK或EFK

此外,為了冗餘和彈性,我們將其複製 n(預設情況下為 3)次。

Ingester

Ingester 接收到日誌並開始構建 Chunk:

Grafana Loki開源日誌聚合系統代替ELK或EFK

基本上就是將日誌進行壓縮並附加到 Chunk 上面。一旦 Chunk 填滿(資料達到一定數量或者過了一定期限),Ingester 將其重新整理到資料庫。我們對塊和索引使用單獨的資料庫,因為它們儲存的資料型別不同。

Grafana Loki開源日誌聚合系統代替ELK或EFK

重新整理一個 Chunk 之後,Ingester 然後建立一個新的空 Chunk 並將新條目新增到該 Chunk 中。

Querier

讀取就非常簡單了,由 Querier 負責給定一個時間範圍和標籤選擇器,Querier 檢視索引以確定哪些塊匹配,並透過 Greps 將結果顯示出來。它還從 Ingester 獲取尚未重新整理的最新資料。

對於每個查詢,一個查詢器將為您顯示所有相關日誌。實現了查詢並行化,提供分散式 Grep,使即使是大型查詢也是足夠的。

Grafana Loki開源日誌聚合系統代替ELK或EFK

可擴充套件性

Loki 的索引儲存可以是 Cassandra/Bigtable/Dynamodb,而 Chuncks 可以是各種物件儲存,Querier 和 Distributor 都是無狀態的元件。

對於 Ingester,它雖然是有狀態的。但是,當新的節點加入或者減少,整節點間的 Chunk 會重新分配,已適應新的雜湊環。而 Loki 底層儲存的實現 Cortex 已經在實際的生產中投入使用多年了。

安裝Loki

Installation methods

Instructions for different methods of installing Loki and Promtail。

Install using Tanka (recommended)

Install through Helm

Install through Docker or Docker Compose

Install and run locally

Install from source

General process

In order to run Loki, you must:

Download and install both Loki and Promtail。

Download config files for both programs。

Start Loki。

Update the Promtail config file to get your logs into Loki。

Start Promtail。

Loki官方已經寫得很詳細了,我以docker-compose為例做個簡單的演示

Install with Docker Compose

version: “3”

networks:

loki:

services:

loki:

image: grafana/loki:latest

ports:

- “3100:3100”

command: -config。file=/etc/loki/local-config。yaml

networks:

- loki

promtail:

image: grafana/promtail:latest

volumes:

- /var/log:/var/log

command: -config。file=/etc/promtail/config。yml

networks:

- loki

grafana:

image: grafana/grafana:latest

ports:

- “3000:3000”

networks:

- loki

Run the following commands in your command line。 They work for Windows or Linux systems。

wget https://raw。githubusercontent。com/grafana/loki/v2。0。0/production/docker-compose。yaml -O docker-compose。yaml

docker-compose -f docker-compose。yaml up -d

[root@localhost loki]# docker-compose ps

Name Command State Ports

————————————————————————————————————————-

loki_grafana_1 /run。sh Up 0。0。0。0:3000->3000/tcp

loki_loki_1 /usr/bin/loki -config。file 。。。 Up 0。0。0。0:3100->3100/tcp

loki_promtail_1 /usr/bin/promtail -config。 。。。 Up

Loki使用

安裝完成後,訪問上面節點的 3000 埠訪問 grafana,預設情況下使用(admin:admin)訪問 -> 選擇新增資料來源:

Grafana Loki開源日誌聚合系統代替ELK或EFK

grafana-loki-dashsource

在資料來源列表中選擇

Loki

,配置 Loki 源地址:

Grafana Loki開源日誌聚合系統代替ELK或EFK

grafana-loki-dashsource-config

源地址配置

http://loki:3100

即可,儲存。

儲存完成後,切換到 grafana 左側區域的

Explore

,即可進入到

Loki

的頁面:

Grafana Loki開源日誌聚合系統代替ELK或EFK

grafana-loki

然後我們點選

Log labels

就可以把當前系統採集的日誌標籤給顯示出來,可以根據這些標籤進行日誌的過濾查詢:

Grafana Loki開源日誌聚合系統代替ELK或EFK

grafana-loki-log-labels

比如我們這裡選擇

/var/log/messages

,就會把該檔案下面的日誌過濾展示出來,不過由於時區的問題,可能還需要設定下時間才可以看到資料:

Grafana Loki開源日誌聚合系統代替ELK或EFK

grafana-loki-logs

選擇器

對於查詢表示式的標籤部分,將其包裝在花括號中

{}

,然後使用鍵值對的語法來選擇標籤,多個標籤表示式用逗號分隔,比如:

{app=“mysql”,name=“mysql-backup”}

目前支援以下標籤匹配運算子:

=

等於

!=

不相等

=~

正則表示式匹配

!~

不匹配正則表示式

比如:

{name=~“mysql。+”}

{name!~“mysql。+”}

適用於

Prometheus

標籤選擇器規則同樣也適用於

Loki

日誌流選擇器。

想要了解

Loki

的原始設計文件的可以點選檢視這裡的文件:

ref=“https://docs。google。com/document/d/11tjK_lvp1-SVsFZjgOTr1vV3-q6vBAsZYIQ5ZeYBkyM/view”>Loki設計文件

Loki Cheat Sheet

See your logs

Start by selecting a log stream from the Log labels selector。

Alternatively, you can write a stream selector into the query field:

{job=“default/prometheus”}

Here are some example streams from your logs:

{job=“varlogs”}

Combine stream selectors

{app=“cassandra”,namespace=“prod”}

Returns all log lines from streams that have both labels。

Filtering for search terms。

{app=“cassandra”} |~ “(duration|latency)s*(=|is|of)s*[d。]+”

{app=“cassandra”} |= “exact match”

{app=“cassandra”} != “do not match”

LogQL supports exact and regular expression filters。

Count over time

count_over_time({job=“mysql”}[5m])

This query counts all the log lines within the last five minutes for the MySQL job。

Rate

rate(({job=“mysql”} |= “error” != “timeout”)[10s])

This query gets the per-second rate of all non-timeout errors within the last ten seconds for the MySQL job。

Aggregate, count, and group

sum(count_over_time({job=“mysql”}[5m])) by (level)

Get the count of logs during the last five minutes, grouping by level。

LogQL

Loki 使用一種稱為 LogQL 的語法來進行日誌檢索,語法類似 PromQL

LogQL: Log Query Language

Loki comes with its own PromQL-inspired language for queries called

LogQL

。 LogQL can be considered a distributed

grep

that aggregates log sources。 LogQL uses labels and operators for filtering。

There are two types of LogQL queries:

Log queries

return the contents of log lines。

Metric queries

extend log queries and calculate sample values based on the content of logs from a log query。

受PromQL的啟發,Loki也有自己的LogQL查詢語句。根據官方的說法,它就像一個

分散式的grep日誌聚合檢視器

。和PromeQL一樣,LogQL也是使用標籤和運算子進行過濾,它主要分為兩個部分:

log stream selector (日誌流選擇器)

filter expression (過濾器表示式)

Grafana Loki開源日誌聚合系統代替ELK或EFK

我們用這兩部分就可以在Loki中組合出我們想要的功能,通常情況下我們可以拿來做如下功能

根據日誌流選擇器檢視日誌內容

透過過濾規則在日誌流中計算相關的度量指標

Log Stream Selector

日誌流選擇器這部分和PromQL的語法一樣,主要也是透過採集上來的日誌label來確定你要查詢的日誌流。通常label的匹配運算支援以下幾種:

\=: 完全匹配

!=: 不匹配

\=~: 正則表示式匹配

!~: 正則表示式不匹配

{app=“mysql”,name=~“mysql-backup。+”}

=

: exactly equal。

!=

: not equal。

=~

: regex matches。

!~

: regex does not match。

Filter Expression

{instance=~“kafka-[23]”,name=“kafka”} != “kafka。server:type=ReplicaManager”

|=

: Log line contains string。

!=

: Log line does not contain string。

|~

: Log line matches regular expression。

!~

: Log line does not match regular expression。

Metric Queries

這個其實就跟prometheus中的很想像了。

rate({job=“mysql”} |= “error” != “timeout” [5m])

rate

: calculates the number of entries per second

count_over_time

: counts the entries for each log stream within the given range。

bytes_rate

: calculates the number of bytes per second for each stream。

bytes_over_time

: counts the amount of bytes used by each log stream for a given range。

Aggregation operators

當然還支援一些聚合操作,比如

avg(rate(({job=“nginx”} |= “GET”)[10s])) by (region)

sum

: Calculate sum over labels

min

: Select minimum over labels

max

: Select maximum over labels

avg

: Calculate the average over labels

stddev

: Calculate the population standard deviation over labels

stdvar

: Calculate the population standard variance over labels

count

: Count number of elements in the vector

bottomk

: Select smallest k elements by sample value

topk

: Select largest k elements by sample value

還有很多比如’and, or’的操作都是支援, 就不一一搬運了

https://

grafana。com/docs/loki/l

atest/logql/

五分鐘瞭解LogQL

參考文章

Loki Documentation

Loki Posts

Loki: Prometheus-inspired, open source logging for cloud natives

Loki日誌系統詳解

Grafana 日誌聚合工具 Loki

Grafana Loki 簡明教程

Loki最佳實踐(譯)

Loki迎來2。0重大更新,LogQL語法大幅增強​!

標簽: 日誌  Loki  Grafana  log