日志收集

日志就是用于记录系统运行时的信息,对一个事件的记录

日志的作用

  • 调试程序
  • 可以用来判断程序是否运行正常
  • 可以用来分析和定位问题
  • 可以用来做用户行为分析和数据统计

日志的级别

  • 调试级别DEBUG 记录的一些代码的调试信息
  • 信息级别INFO 记录一些正常的操作信息
  • 警告级别Warring 记录的是一些警告日志信息,但不会影响系统的功能及正常运行
  • 错误级别Error 记录的是系统运行时的错误信息,说明系统的某些功能不能正常运行 。
  • 严重错误级别critical 记录的系统运行时的严重错误信息,有可能导致整个系统都不能运行

背景和动机

当我们的容器云运行的应用或者某个节点出现问题了,解决思路应该如下:

【日志】Loki_数据

我们的监控使用的是基于Prometheus体系进行改造的,Prometheus中比较重要的是Metric和Alert,Metric是来说明当前或者历史达到了某个值,Alert设置Metric达到某个特定的基数触发了告警,但是这些信息明显是不够的。我们都知道,Kubernetes的基本单位是Pod,Pod把日志输出到stdout和stderr,平时有什么问题我们通常在界面或者通过命令查看相关的日志,举个例子:当我们的某个Pod的内存变得很大,触发了我们的Alert,这个时候管理员,去页面查询确认是哪个Pod有问题,然后要确认Pod内存变大的原因,我们还需要去查询Pod的日志,如果没有日志系统,那么我们就需要到页面或者使用命令进行查询了:

【日志】Loki_公众号_02

如果,这个时候应用突然挂了,这个时候我们就无法查到相关的日志了,所以需要引入日志系统,统一收集日志,而使用ELK的话,就需要在Kibana和Grafana之间切换,影响用户体验。所以 ,loki的第一目的就是最小化度量和日志的切换成本,有助于减少异常事件的响应时间和提高用户的体验。

Loki日志系统

Loki日志系统是受Prometheus启发由Grafana Labs团队开源的水平可扩展,高度可用的[多租户日志聚合系统。它被设计得非常轻量高效且易于操作,使用标签来作为索引,而不是对全文进行检索,即通过这些标签既可以查询日志的内容也可以查询到监控的数据签,极大地降低了日志索引的存储。
Loki 日志系统由以下3个部分组成:

  • loki是主服务器,负责存储日志和处理查询
  • promtail是专为loki定制的代理,负责收集日志并将其发送给 loki
  • Grafana用于查询和显示日志
    整体架构
    【日志】Loki_日志系统_03
    Loki 包含Distributor、Ingester、Querier和可选的Query frontend五个组件。每个组件都会起一个用于处理内部请求的 gRPC 服务器和一个用于处理外部 API 请求的 HTTP/1服务器。


grpc相关


三丰,公众号:soft张三丰​​【通讯】以json的方式访问grpc​

Distributor

Distributor 是客户端连接的组件,用于收集日志
在 promtail 收集并将日志发送给Loki 之后, Distributor 就是第一个接收它们的组件,每秒可以接收数百万次写入。Distributor会对接收到的日志流进行正确性校验,并将验证后的chunk日志块分批并行发送到Ingester。


事件驱动


三丰,公众号:soft张三丰​​事件驱动​

Ingester

Ingester 接收来自Distributor的日志流,并将日志压缩后存放到所连接的存储后端。

Ingester接受日志流并构建数据块,其操作通常是压缩和追加日志。每个Ingester 的生命周期有PENDING, JOINING, ACTIVE, LEAVING 和 UNHEALTHY 五种状态。处于JOINING和ACTIVE状态的Ingester可以接受写请求,处于ACTIVE和LEAVING状态时可以接受读请求。
Ingester 将收到的日志流在内存中打包成 chunks ,并定期同步到存储后端。由于存储的数据类型不同,Loki 的数据块和索引可以使用不同的存储

当满足以下条件时,chunks 会被标记为只读:

  • 当前 chunk 达到配置的最大容量
  • 当前 chunk 长时间没有更新
  • 发生了定期同步
  • 当旧的 chunk 经过了压缩并被打上了只读标志后,新的可写的 chunk 就会生成

Querier

Querier 用来查询日志,可以直接从 Ingester 和后端存储中查询数据。当客户端给定时间区间和标签选择器之后,Querier 就会查找索引来确定所有匹配 chunk ,然后对选中的日志进行 grep并返回查询结果。查询时,Querier先访问所有Ingester用于获取其内存数据,只有当内存中没有符合条件的数据时,才会向存储后端发起同样的查询请求。
需要注意的是,对于每个查询,单个 Querier 会 grep 所有相关的日志。目前 Cortex 中已经实现了并行查询,该功能可以扩展到 Loki,通过分布式的 grep 加速查询。此外,由于副本因子的存在,Querier可能会接收到重复的数据,所以其内置了去重的功能,对拥有同样时间戳、标签组和消息内容的日志进行去重处理。
Loki与其他日志聚合系统差别:

  • 不对日志进行全文本索引。通过存储压缩的,非结构化的日志以及仅索引元数据,Loki更加易于操作且运行成本更低
  • 使用与Prometheus相同的标签对日志流进行索引和分组,从而使您能够使用与Prometheus相同的标签在指标和日志之间无缝切换。
  • 特别适合存储Kubernetes Pod日志。诸如Pod标签之类的元数据会自动被抓取并建立索引
  • 在Grafana中原生支持(需要Grafana v6.0及以上)

成本

全文检索的方案也带来成本问题,简单的说就是全文搜索(如ES)的倒排索引的切分和共享的成本较高。后来出现了其他不同的设计方案如:OKlog,采用最终一致的、基于网格的分布策略。这两个设计决策提供了大量的成本降低和非常简单的操作,但是查询不够方便。因此,Loki的第三个目的是,提高一个更具成本效益的解决方案。

Loki与ELK抉择

在Loki之前,你要问运维开源的日志解决方案,似乎只有ELK

不可否认,ELK通过对日志全文索引及列式存储,为日志存储及分析带来极大的便利性

但是从另一个角度来讲,这样的便利是通过极高的成本换来的,包括服务器成本和运维成本,而存储的日志中,高价值的日志却很少,这样的成效比是极低的

而Loki则恰恰相反,Loki不会对日志数据建立全文索引,取而代之的是对非结构化日志数据进行压缩存储,并且只对日志数据的metadata(时间戳、labels等)建立索引,所以相比ELK,它的存储成本更低,查询效率也更高

但是Loki也有缺点,就是如果想实现项ELK一样的复杂度比较高的查询,需要设计好Labels,如果对labels设计不合理,会使Loki对数据流的存储和查询带来极大的挑战,会使Loki崩溃。




关注公众号 soft张三丰 

【日志】Loki_公众号_04