与其他日志系统相比, Loki 的使用方式是有一定差异性的,需要用不同的思维方式。本文分享一下这些差异以及我们应该如何使用
作为 Loki 用户或操作人员,我们目标应该是使用尽可能少的标签来存储日志。
更少的标签则意味着更小的索引,从而能带来更好的性能。
以上这些话听起来可能觉得有问题。因为在我们以往工作中比如使用 elk、数据库的经验告诉我们,如果想让它更快,需要对其建立索引。而Loki 是以完全相反的方式构建和优化的, Loki 的设计目标是保持较低的运营成本和复杂性,这是通过保持非常小的索引并利用商用硬件性能和并行化查询来实现的。
因此,作为 Loki 的用户或操作员,在添加标签之前我一定要三思而后行。
如何查询给定traceID 的所有日志?
ts=2020-08-25T16:55:42.986960888Z caller=spanlogger.go:53 org_id=29 traceID=2612c3ff044b7d02 method=Store.lookupIdsByMetricNameMatcher level=debug matcher="pod="loki-canary-25f2k"" queries=16
我们可能会想,应该提取traceID作为标签,然后可以这样查询:
{cluster="ops-cluster-1",namespace="loki-dev", traceID=”2612c3ff044b7d02”}
但不建议这么做,这种方式会导致Loki 查询效率很低,因为它的值就是个无界的,每次请求都会产生新的traceID,这种情况属于典型无界的动态标签值,在Loki里面用Cardinality来表示,Cardinality值越高,Loki的查询效率越低。如果想在日志中查找高基数数据,请使用如下过滤表达式:
{cluster="ops-cluster-1",namespace="loki-dev"} |= “traceID=2612c3ff044b7d02”
提取的内容基数低,能否提取到标签中?
比如日志级别,只有几个固定值:
{cluster="ops-cluster-1",namespace="loki-dev", level=”debug”}
这里也要注意!因为标签对索引和存储具有倍增效应,刚开始的一个日志流,如果使用日志级别标签后,现在已变成4个日志流,所以在我们添加标签时要考虑这些,以下是一个示意图
尽量使用静态标签
静态标签开销更小,在发送到Loki之前,就会获取相关 lablel,在k8s 中通过 helm 部署,默认采集以下静态标签
- 应用名:__meta_kubernetes_pod_label_app
- 命名空间:__meta_kubernetes_namespace
- 节点名称:__meta_kubernetes_pod_node_name
- pod名称:__meta_kubernetes_pod_name
- 容器名称:__meta_kubernetes_pod_container_name
使用并行化来提高Loki 性能
使用大量数值的标签是不好的,那么我们如何查询日志?如果没有日志没有索引,查询能快吗?
在我们使用ELK 或者其他日志系统时,我们会创建大量的索引来提高查询速度,但是在 loki 中我们需要忘记这些东西
因为loki 是通过并行化的方式来提交查询速度的。
Loki 的超能力是将查询分解成小块,并将其并行调度,这样就可以在小时间内查询大量的日志数据,最后在进行汇总返回
总结
Loki 利用水平扩展和查询时间来查询我们的数据。这与使用多索引的解决方案一样快吗?可能不是!但它运行和部署要容易很多,而且还省资源。
Grafana Lab 的 Loki 部分集群的数据,在过去 7 天内,它摄入了 14TB 的数据。该时间段对应的索引使用量约为500MB;14TB 日志的索引可以放入树莓派的内存中。
这就是为什么Loki专注于保持标签集较小的原因。也许标签只能将搜索范围缩小到 100GB 的日志数据 —但是运行 20 个查询器(可以以 30GB/s 的速度并行搜索 100GB 数据)比维护一个 14TB 索引要便宜得多,尤其是当我们使用不了几次的时候。
因此,更少的标签 = 更好的性能。