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

        Loki日志系统同ELK在结构上基本一样,也是由三部分组成:

  • Loki:为主服务器,负责日志存储和查询处理;
  • Promtail:为代理,负责收集日志并将其发送给Loki主服务器;
  • Grafana:用于UI展示;

 

Promtail:

        Promtail是Loki的官方日志采集器,原生支持journal、syslog、file、docker类型的日志,作用同ELK中Logstash相同。Promtail作为一个采集器,首先自然是要找到文件在哪里,然后才能做下面的收集与打标签推送等功能。

        首先,对于找日志文件,普通静态类型的日志是比较好发现的,直接根据Promtail配置文件中写的路径信息进行匹配即可,比如Promtail中path为"/var/log/*.log"的路径,即将/var/log目录下所有的以.log结尾的后缀文件作为要采集的对象。但是要采集Kubernetes内的日志就稍显麻烦。如果需要采集Kubernetes中容器应用的日志,需要弄清楚日志存放在哪里,容器应用通常有以下两种方式存放:

  • 写入本地文件:这种日志一般存放在自定义的路径上,如果这个路径没有被挂载出来,那么日志只存在于容器内部的自定义路径上;如果挂载了,在宿主机上也可以看到日志文件。这种类型的日志相当于普通的静态类型日志,Promtail是无法动态发现的,必须手工一个个在配置文件中设置,且每个服务的日志目录均需要挂载进Promtail。
  • 标准输出:这种是Kubernetes推荐的日志输出方式,这类日志其实就是我们日常用kubectl log命令看到的日志,其存储路径在宿主机上,路径遵循/var/log/pods/{namespace}_{pod_id}_UUID/{container_name}/*.log这种格式,如下图中ApiServer这个Kubernetes系统组件的日志存放路径。这个路径下的日志即是Promtail读取的日志,只需要将/var/log/pods作为hostpath挂载进Promtail容器内部,就可以让 Promtail动态访问到这些日志。

         然后,对于Promtail收集和打标签推送,其设计完全复用了Prometheus的服务发现机制与label机制。以Kubernetes服务发现为例,Prometheus可以通过Pod的Annotations与 Labels等信息来确定Pod是否需要抓取指标、指标暴露在哪个端口上,以及这个Pod本身有哪些label,即target label。确定了上述信息之后,Prometheus就可以去拉取应用的指标了,同时这些指标都会被打上target label,用于标注指标的来源。在后续查询的时候,就可以通过target label(如pod_name=foo-123512、service=user-service)来获取特定的一个或一组Pod上的指标信息。Promtail是相同的道理,它也是通过Pod的一些元信息来确定该Pod的日志文件位置,同时为日志打上特定的target labe。但要这个target labe并不是标注在每一行日志事件上的, 而是被标注在“整个日志”上的,这里“整个日志”在Loki中抽象为stream(日志流)。最终在查询端,通过这些label就可以快速查询一个或一组特定的stream。

Loki:

        Loki是日志存储和查询处理系统,作用同ELK中Elasticsearch相同。Loki只会对日志元数据标签(同Prometheus的标签一样)进行索引,而不会对原始的日志数据进行全文索引。而且,日志数据本身会被压缩,并以 chunks(块)的形式存储在对象存储(比如S3 或者GCS)或本地文件系统中。一个小的索引和高度压缩的chunks可以大大简化操作和降低 Loki 的使用成本。Loki包含Distributor、Ingester、Querier和可选的Query frontend组件。每个组件都会起一个用于处理内部请求的gRPC服务器和一个用于处理外部API请求的 HTTP/1服务器。

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

(2)Ingester:用于接收来自Distributor的日志流,并将日志压缩后存放到所连接的存储后端。Ingester接受日志流并构建数据块,其操作通常是压缩和追加日志,将收到的日志流在内存中打包成 chunks,并定期同步到存储后端。

(3)Querier:用来查询日志,可以直接从 Ingester 和后端存储中查询数据。当客户端给定时间区间和标签选择器之后,Querier就会查找索引来确定所有匹配chunk ,然后对选中的日志进行grep并返回查询结果。查询时,Querier先访问所有Ingester用于获取其内存数据,只有当内存中没有符合条件的数据时,才会向存储后端发起同样的查询请求。

(4)Query frontend:是可选组件,其提供了Querier的API并可用于读加速。当系统中有该组件时,所有的读请求都会经由Query frontend而非Querier处理。Query frontend是无状态的,生产环境中推荐2副本来达到调度的均衡。Query frontend会对请求做一些调整,并将请求放入一个内部的队列中。在该场景中,Querier作为workers 不断从队列中获取任务、执行任务,并将结果返回给Query frontend用于聚合。

Grafana:

        Grafana是一个跨平台的开源的度量分析和可视化工具,作用同ELK中Kibana相同,但Grafana是专门针对Prometheus和Loki等数据源的时间序列数据定制的。Grafana可以将采集的数据查询然后可视化的展示,并及时通知。它主要有以下六大特点:

  • 展示方式:快速灵活的客户端图表,面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件,比如热图、折线图、图表等多种展示方式;
  • 数据源:Graphite、InfluxDB、OpenTSDB、Prometheus、Loki、Elasticsearch、CloudWatch和KairosDB等;
  • 通知提醒:以可视方式定义最重要指标的警报规则,Grafana不断计算并发送通知,在数据达到阈值时通过Slack、PagerDuty等获得通知;
  • 混合展示:在同一图表中混合使用不同的数据源,可以基于每个查询指定数据源,甚至自定义数据源;
  • 注释:使用来自不同数据源的丰富事件注释图表,将鼠标悬停在事件上会显示完整的事件元数据和标记;
  • 过滤器:Ad-hoc过滤器允许动态创建新的键/值过滤器,这些过滤器会自动应用于使用该数据源的所有查询。

        与ELK相比,Loki日志系统具有多方面优势:

(1)成本:ELK对日志采用全文检索,优点是功能丰富且允许复杂操作,但是其规模复杂、资源占用高、操作困难,且很多功能往往用不上,大多数查询只关注一定时间范围和一些简单的参数。而在Loki中,日志以纯文本格式存储,每个日志流带有一组标签名称和值,其中仅对标签对进行索引,这种设置使得它比全索引更加节省空间。

(2)标签管理:Loki通过一组标签表示日志的方式与Prometheus表示监控指标的方式类似。当与Prometheus一起部署在环境中时,由于使用了相同的服务发现机制,来自Promtail的日志通常与监控指标具有相同的标签。拥有相同级别的日志和指标,使用户可以在监控指标和日志之间无缝切换,帮助进行根本性原因分析。

(3)Kubernetes支持:Loki特别适合储存Kubernetes中Pod日志。诸如Pod标签之类的元数据会被自动删除和编入索引,且可以动态发现Pod日志。


链接:移动云开发者社区

来源:移动云官网开发者社区

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐