开源日志收集服务--Loki

关于Loki

官网

仓库 https://github.com/grafana/loki

官网 https://grafana.com/oss/loki/

文档 https://grafana.com/docs/loki/latest/

Loki项目

  • 由Grafana Labs开发的开源日志聚合系统,能够同Grafana生态组件紧密集成
  • 受启发于Prometheus指标系统
    • 以时序数据格式存储日志流,每个日志流由一组时序标签进行标识
    • 提供了类似于PromQL的专用的日志检索语言LogQL
  • Loki的关键特征
    • 最小化索引
      • Loki仅索引日志的元数据(标签信息),而非日志全文
      • 标签通常是主机名、容器名、日志文件名、应用程序名、日志级别、HTTP请求方法、HTTP响应码等
    • 日志流
      • 由同一组时序标签标识的日志信息,称为日志流(stream)
      • Loki的日志数据存储为索引(index)和压缩的数据块(chunk)两部分
    • 支持水平扩展和多租户
      • 微服务化设计,各组件可独立进行水平扩展
      • 支持多租户,能有效进行日志数据隔离和实施权限控制
    • 可插拔的存储后端
      • 支持多种存储后端,包括本地文件系统、主流的存储服务,以及多种云存储等
      • 支持根据需求分别为索引和日志选择选择不同的存储方案

Loki日志栈

架构图

各组件

Promtail

  • Promtail负责在节点上收集日志并push到Loki Server,它支持与Prometheus相同的服务发现机制,以及重新打标、格式转换和过滤功能
  • Promtail是专为Loki设计的日志收集器,它的职责包括:发现目标、向日志信息附加标签,向Loki推送日志流

Loki

  • Loki Server负责接收并存储日志信息,但它不会索引日志文本,而仅是完成标签索引,从而显著降低系统开销及接近实时的查询性能;

Grafana

  • 一个用于监控和可视化观测的开源平台,支持非常丰富的数据源,在 Loki 技术栈中它专门用来展示来自 Prometheus 和 Loki 等数据源的时间序列数据,可进行查询、可视化、报警等操作,可以用于创建、探索和共享数据 Dashboard,鼓励数据驱动。

AlertManager

  • 用户可编写告警规则并进行周期性评估,超出合理阈值或者阈值范围的日志信息,可由AlertManager通知给用户。

LogQL是Loki提供的日志查询语言,Grafana可对查询结果进行可视化,基于命令行的查询通常由LogCLI进行

Loki支持很多种客户端,包括Grafana Agent、Promtail,以及第三方的Docker Driver、Fluentd/Fluent-bit、Logstash等

Loki VS ElasticSearch

比较的关键点

存储、索引、查询语言、日志收集器、用户接口和成本等几个方面

Loki ElasticSearch
存储 空间需求量小 空间需求量大
索引 尽可能少的索引日志信息 索引整行日志
查询语言 LogQL Kibana查询语言(KQL),或Lucene查询语句
日志收集器 Promtail Logstash/Beats
用户接口 Grafana Kibana
成本 开销较低,但检索能力较差 开销大但提供全文索引机制

Loki组件

Loki的系统组件大体可以分为两类

  • Read path:处理读取日志样本请求的组件
  • Write path:处理存储日志样本请求的组件
    核心组件介绍
  • Distributor(write path)
  • 从Loki客户端(如Promtail)接收数据、检查数据,随后将其分成数据块(Chunks)并发往Ingester
  • 无状态应用,可接受LB进行数据分发
  • Ingester(write, read path)
    • 负责将数据存入外部的存储系统(如S3)以长期存储数据,以及接受客户端的查询请求并响应相关的数据
    • 为避免数据丢失,通常应该提供复制式多实例
  • Querier(read path)
    • 处理LogQL请求,并从Ingester或长期存储系统中加载数据
  • Query Frontend(read path)
    • 处理查询请求的前端组件

Loki 系统数据流(Data flow)

Read path
① Querier基于HTTP接收到查询请求
② 转发请求至Ingester,以检查缓存在内存中的日志数据
③ 若Ingester查询到了相关数据,则返回给Querier
④ 若Ingester未查询到相关数据,则Querier将会向存储系统发起请求
⑤ Querier基于HTTP协议响应查询请求
Write path
① Distributor基于HTTP协议接收到写请求,并将其附加到特定的stream
② Distributor将每个stream发往Ingester
③ Ingester创建一个新Chunk或附加至现有的Chunk上
④ Distributor将结果响应给客户端

Loki Architecture

Distributor收到的日志流基于标签进行consistent hashing计算后,分发至不同的Ingester,复制因子用于指定要存储的副本数以实现容错

Loki中的日志存储由两部分组成:索引数据(index)和 日志数据(chunk)

Chunks 数据块

日志内容存储

  • Loki会将每个日志流中的日志信息存储为Chunk
    • 每个Chunk存储有特定时间窗口内的日志条目,这些日志条目会被压缩后再进行存储
    • 每个Chunk的所有日志条目会按照timestamp进行排序
  • Chunk中的内容包括压缩的日志条目(Compressed log entries)、时序信息(Time series information)和 块标识符(Chunk identifiers)

Chunks由Ingester缓存于内存中,并周期性刷写至磁盘上

  • 触发刷写操作的条件:达到单个Chunk的存储上限,或者达到窗口时长

Loki通常将chunk存储在对象存储系统中,支持的存储包括

兼容S3存储协议的存储系统,均可作为Chunk的存储后端,例如MinIO等

索引

Loki会对Chunks基于标签集和时间范围进行索引以加快检索操作

  • Loki仅索引日志流的元数据(标签集),它不会索引日志内容
  • 索引中主要存储标签集、日志流标识符(Stream identifiers)和时间范围(内部日志流的时间边界)

索引信息通常存储于KV存储系统中,支持的存储包括如下几项

索引(index)和数据块(chunk)

Loki中的日志存储由两部分组成:索引数据(index)和日志数据(chunk)

  • Index
    • ki仅索引日志流的元数据(标签集),它不会索引日志内容
    • 存储标签集、日志流标识符(Stream identifiers)和时间范围(内部日志流的时间边界)
    • 数据存储于数据存储库,以提供较快的读取和查询性能

  • Chunk
    • Loki会将从Promtail等客户端接收到的日志信息存储于时序数据库TSDB中,这些日志数据被组织成chunk
    • chunk中的内容包括压缩的日志条目(Compressed log entries)、时序信息(Time series information)和块标识符(Chunk identifiers)
    • Loki通常将chunk存储在如Amazon S3或本地文件系统等对象存储中

Loki 的核心概念

存储纯文本信息,也支持存储为JSON或logfmt格式

基于“Log streams(共享同一组标签的日志信息)”存储日志数据

  • 同一stream中的数据将会存储在一起,以降低标签匹配(label matching)可能涉及到的stream数量
  • 日志信息的匹配将采用类似grep式的粗暴方式

尽量小心地避免时间线膨胀的问题

  • 时序数据库的典型难题之一“cardinality explosion(基数爆炸)”,即标签上的不同可用值过多

日志信息存入Loki的方式

  • 由Promtail一类的客户端请求基于HTTP API以push方式进行

基于LogQL进行日志查询

  • HTTP API
    • One-shot query
    • Live streaming
  • 专用的命令客户端:logcli
  • WebGUI:Grafana
posted @ 2024-07-17 18:00  厚礼蝎  阅读(45)  评论(0编辑  收藏  举报