最佳实践
概述
参考:
标签设计最佳实践: https://grafana.com/docs/loki/latest/get-started/labels/bp-labels/
最近很多同学的 Loki 在上线过程中经常遇见丢日志的情况,一查 Loki 日志的发现是日志流的时序问题导致的。这也从侧方面反映出大家对 Loki 的日志流和标签之间的关系还是明确清楚。几个月前,偶然看见博客上原作者对 Loki 标签有过简明指南,深感有责任翻译给大家,用于理解这部分概念。由于原文写于 Loki1.x 时代,译文对于部分于差异的部分进行了相关删减,如小伙伴们要阅读原文,点击文末【阅读原文】即可
作为 Loki 的用户或操作员,我们的目标应该是使用尽可能少的标签来存储你的日志。
这意味着,更少的标签带来更小的索引,从而导致更好的性能 再重复一遍 更少的标签=更好的性能
这可能听起来有悖直觉。大部分数据库的管理经验告诉我们,如果你想让查询更加快速,我们通常通过需要建立更多的索引。但是,Loki 是以完全相反的方式构建和优化的。我们围绕 Loki 的设计初衷是为了保持运营成本和复杂性低,这是通过保持一个非常小的索引和利用硬件能力和并行化运算来实现的。
因此,作为 Loki 的用户或操作者,我们在添加标签之前一定要三思而行。
我举个例子:
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 查询所有日志?
你可能会想,“我应该提取 traceID 作为标签”,然后我可以这样查询。
{cluster="ops-cluster-1",namespace="loki-dev", traceID=”2612c3ff044b7d02”}
千万不要这样做! 我们要避免将日志中的内容提取成标签!如果你想在你的日志中找到高基的数据,可以使用下面这样的过滤表达式。
{cluster="OPS-cluster-1",namespace="loki-dev"} |= "traceID=2612c3ff044b7d02"
但是如果标签是一个较低的基数怎么办?如果把日志级别提取到标签中,而我们的日志级别只有五个值,怎么办?
{cluster="OPS-cluster-1",namespace="loki-dev", level="debug"}
在这里要小心!记住标签对索引和存储有多重的, 增加一个标签,那么对Loki的索引和存储有倍增的效应。一开始是我们是一个日志流,现在变成了多达五个流(按照日志级别)。然后我们考虑是否添加另一个标签?但是不幸的是,即使它只有几个值,事情也会很快失控。
相反,我们应该按照过滤表达式如下编写 LogQL 语法:
{cluster="OPS-cluster-1",namespace="loki-dev"} |= "level=debug" |= "status=200" |= "path=/api/v1/query"
是否可以将日志内容提取为标签?
是的,我们可以这么做,不过在这样做之前应该仔细考虑下,新增的标签是否是用于描述日志,以帮助你缩小搜索范围,如果是那你应当慎重。或者说,我们在 Loki 使用标签,主要是它们描述了我们的应用运行在各种环境、服务器等物理的拓扑结构,通过他们来描述日志的来源。
这是 Loki 目前一个艰难的用例,我们正在努力消除对有序条目的限制,但这是一个棘手的问题。目前,这种环境将需要对你的代码的并行性进行限制。或者可以采取另一种变通方法,即把你的程序日志发送到一个可以做提取时间戳的服务上做好聚合后再发送给 Loki。
这是 Loki 需要改进的地方,我们正在积极努力。
总结
Loki 利用水平缩放和查询器的蛮力来查找数据。这和完全索引的解决方案一样快吗?不,它可能不会! 但它的运行(其实非常快)却容易得多!让我们看看一个从 Grafana Lab 上 Loki 集群的一些实际数据。在过去的七天里,它摄入了 14TB 的数据。该时间段对应的索引使用量约为 500MB。14TB日志的索引可以装进一个树莓派的内存中。
这就是为什么我们注重保持标签集小的原因。也许你的标签只能将搜索范围缩小到 100GB 的日志数据。
不用担心! 运行 20 个查询器,它们可以以 30GB/s 的速度并行搜索这 100GB 的数据,这比维护一个 14TB 的索引要便宜得多,因为 Loki 可以告诉你到底在哪里查找,特别是当你考虑到你可以在查询完成后将查询器关闭,从成本上来看它非常划算!
最后,再一次重申,更少的标签 = 更好的性能。
OTel Collector 采集日志入到 Loki
https://grafana.com/docs/loki/latest/send-data/otel/
当 Loki 使用 使用 OpenTelemetry 协议 (OTLP) 储存日志时,部分数据将存储为结构化元数据 。
Loki 会将 OTel Collector 的资源属性会作为结构化元数据保存。若想将资源数据作为标签,则需要将结构化元数据转为标签
Loki 接收 OTLP 的数据的 API 与默认的不同,是 http://<LOKI-ADDR>/otlp
Loki 的配置示例如下
limits_config:
ingestion_rate_mb: 10
retention_period: 30d
# 将 OTLP 的 Resource attributes 映射为 Loki 的 Indexed label,以便可以通过标签过滤
# https://grafana.com/docs/loki/latest/send-data/otel/#changing-the-default-mapping-of-otlp-to-loki-format
otlp_config:
resource_attributes:
attributes_config:
- action: index_label
attributes:
- host_ip
- province
- region
- custom_house_name
- log_type
- docking_system
这个配置会把 host_ip, province, region, custom_house_name, log_type, docking_system 这几个来自于 OTel 的资源属性转为标签。
注意,这个转换是指配置中 key 的所有值都转换,要避免某些 key 会产生高基数的问题。
反馈
此页是否对你有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.