8WvVk8.jpg

Loki

简介

Loki是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签,为 Prometheus和 Kubernetes用户做了相关优化。项目受 Prometheus 启发,类似于 Prometheus 的日志系统。

整体架构

8RyAWd.png

不难看出,Loki的架构非常简单,使用了和prometheus一样的标签来作为索引,也就是说,你通过这些标签既可以查询日志的内容也可以查询到监控的数据,不但减少了两种查询之间的切换成本,也极大地降低了日志索引的存储。 Loki将使用与prometheus相同的服务发现和标签重新标记库,编写了pormtail, 在k8s中promtail以daemonset方式运行在每个节点中,通过kubernetes api等到日志的正确元数据,并将它们发送到Loki。

日志存储架构

8Ry1YQ.png

读写

日志数据的写主要依托的是Distributor和Ingester两个组件, 整体的流程如下: 8Rysp9.png

Distributor

一旦promtail收集日志并将其发送给loki,Distributor就是第一个接收日志的组件。由于日志的写入量可能很大,所以不能在它们传入时将它们写入数据库。这会毁掉数据库。我们需要批处理和压缩数据。

Loki通过构建压缩数据块来实现这一点,方法是在日志进入时对其进行gzip操作,组件ingester是一个有状态的组件,负责构建和刷新chunck,当chunk达到一定的数量或者时间后,刷新到存储中去。每个流的日志对应一个ingester,当日志到达Distributor后,根据元数据和hash算法计算出应该到哪个ingester上面。 8Ry5fH.png 此外,为了冗余和弹性,我们将其复制n(默认情况下为3)次。

Ingester

ingester接收到日志并开始构建chunk: 8R6J4e.png 基本上就是将日志进行压缩并附加到chunk上面。一旦chunk“填满”(数据达到一定数量或者过了一定期限),ingester将其刷新到数据库。我们对块和索引使用单独的数据库,因为它们存储的数据类型不同。 8R60DP.png 刷新一个chunk之后,ingester然后创建一个新的空chunk并将新条目添加到该chunk中。

Querier

读取就非常简单了,由Querier负责给定一个时间范围和标签选择器,Querier查看索引以确定哪些块匹配,并通过greps将结果显示出来。它还从Ingester获取尚未刷新的最新数据。

对于每个查询,一个查询器将为您显示所有相关日志。实现了查询并行化,提供分布式grep,使即使是大型查询也是足够的。 8R6Rvn.png

特点

与其他日志聚合系统相比, Loki具有下面的一些特性:

  • 不对日志进行全文索引。通过存储压缩非结构化日志和仅索引元数据,Loki 操作起来会更简单,更省成本。
  • 通过使用与 Prometheus 相同的标签记录流对日志进行索引和分组,这使得日志的扩展和操作效率更高。
  • 特别适合储存 Kubernetes Pod 日志; 诸如 Pod 标签之类的元数据会被自动删除和编入索引。
  • 受 Grafana 原生支持。

组成

  • loki是主服务器,负责存储日志和处理查询。
  • promtail是代理,负责收集日志并将其发送给 loki。
  • Grafana 用于 UI 展示。

环境搭建

loki 下载

1
2
3
4
5
wget https://github.com/grafana/loki/releases/download/v1.3.0/loki-linux-amd64.zip
mkdir /usr/local/loki
unzip loki-linux-amd64.zip
mv loki-linux-amd64 loki
mv loki /usr/local/loki

loki 启动

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
cd /usr/local/loki
vim loki-local-config.yaml
# 写入以下内容
auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 5m
  chunk_retain_period: 30s
  max_transfer_retries: 1

schema_config:
  configs:
  - from: 2018-04-15
    store: boltdb
    object_store: filesystem
    schema: v9
    index:
      prefix: index_
      period: 168h

storage_config:
  boltdb:
    directory: /tmp/loki/index

  filesystem:
    directory: /tmp/loki/chunks

limits_config:
  enforce_metric_name: false
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 0

table_manager:
  chunk_tables_provisioning:
    inactive_read_throughput: 0
    inactive_write_throughput: 0
    provisioned_read_throughput: 0
    provisioned_write_throughput: 0
  index_tables_provisioning:
    inactive_read_throughput: 0
    inactive_write_throughput: 0
    provisioned_read_throughput: 0
    provisioned_write_throughput: 0
  retention_deletes_enabled: false
  retention_period: 0
  • 启动命令
1
2
cd /usr/local/loki
./loki -config.file=loki-local-config.yaml

配置系统服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vim /etc/systemd/system/loki.service

# 写入以下内容

[Unit]
Description=loki
Wants=network-online.target
After=network-online.target
[Service]
Restart=on-failure
ExecStart=/usr/local/loki/loki --config.file=/usr/local/loki/loki-local-config.yaml
[Install]
WantedBy=multi-user.target

配置好均需要执行以下命令

1
systemctl daemon-reload
  • 相关启动,停止命令
1
2
3
4
systemctl start loki.service
systemctl status loki.service
systemctl stop loki.service
systemctl restart loki.service

promtail 下载

1
2
3
4
5
wget https://github.com/grafana/loki/releases/download/v1.3.0/promtail-linux-amd64.zip
unzip promtail-linux-amd64.zip
mkdir /usr/local/promtail
mv promtail-linux-amd64 promtail
mv promtail /usr/local/promtail

promtail 启动

  • promtail-local-config.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
cd /usr/local/promtail
vim promtail-local-config.yaml
# 写入以下内容
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://localhost:3100/loki/api/v1/push

scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /var/log/*
  • 启动命令
1
2
cd /usr/local/promtail
./promtail -config.file=promtail-local-config.yaml

配置系统服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
vim /etc/systemd/system/promtail.service
#写入以下内容


[Unit]
Description=promtail
Wants=network-online.target
After=network-online.target
[Service]
Restart=on-failure
ExecStart=/usr/local/promtail/promtail --config.file=/usr/local/promtail/promtail-local-config.yaml
[Install]
WantedBy=multi-user.target

配置好执行以下命令

1
systemctl daemon-reload
  • 相关启动,停止命令
1
2
3
4
systemctl start  promtail.service
systemctl status  promtail.service
systemctl restart  promtail.service
systemctl stop  promtail.service

grafana loki 接入

添加Data Source

8RhMGT.png

Grafana Explore

选择Loki 8Rhtd1.png

LogQL 语法

选择器

对于查询表达式的标签部分,将放在{}中,多个标签表达式用逗号分隔:

1
{app="mysql",name="mysql-backup"}

支持的符号有:

  • = 完全相同。
  • != 不平等。
  • =~ 正则表达式匹配。
  • !~ 不要正则表达式匹配。

过滤表达式

编写日志流选择器后,您可以通过编写搜索表达式进一步过滤结果。搜索表达式可以文本或正则表达式。 如:

  • {job=“mysql”} |= “error”
  • {name=“kafka”} |~ “tsdb-ops.*io:2003”
  • {instance=~“kafka-[23]”,name=“kafka”} != kafka.server:type=ReplicaManager 支持多个过滤
  • {job=“mysql”} |= “error” != “timeout” 目前支持的操作符:

  • |= line包含字符串。

  • != line不包含字符串。

  • |~ line匹配正则表达式。

  • !~ line与正则表达式不匹配。 8RImdA.png

查看更多

在查询出来的结果行后面有一个show context (查看上下文),点击这个按钮,默认展示结果行前10行和后10行。 8RI0zT.png