轻量级日志系统 PLG(**Promtail + Loki + Grafana**)架构技术调研

Posted KKhasabigdream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了轻量级日志系统 PLG(**Promtail + Loki + Grafana**)架构技术调研相关的知识,希望对你有一定的参考价值。

开源的容器云日志方案

1、Promtail

Promtail 是代理,负责收集日志并将其发送给loki。对标ELK中的Logstash。

Promtail是一个日志收集的代理,它的主要工作模式是发现存储在磁盘上的日志文件,并将其与一组标签关联的日志文件转发到 Loki,它通常部署到需要监视应用程序的每台机器/容器上。Promtail主要是用来发现目标、将标签附加到日志流以及将日志推送到Loki。截止到目前,Promtail可以跟踪两个来源的日志:本地日志文件和systemd日志(仅支持AMD64架构)

2、Loki

Loki 是主服务器,负责存储日志和处理查询。对标ELK中的ElasticSearch。

Loki是一组可以组成一个功能齐全的日志堆栈组件,与其它日志系统不同的是,Loki只建立日志标签的索引而不索引原始日志消息,为日志数据设置一组标签,这意味着Loki的运营成本更低,效率也能提高几个数量级

(1)Loki标签(Labels)

  • 标签是Loki最核心的一项功能,它是一个键值对,通过给一个日志打上一个或多个标签,按标签查询可以精准快速地定位到所有符合条件的日志。标签可以在配置文件中配置,如下:

scrape_configs:
 - job_name: system
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: syslog
      env: dev
      __path__: /var/log/syslog
 - job_name: apache
   pipeline_stages:
   static_configs:
   - targets:
      - localhost
     labels:
      job: apache
      env: dev
      __path__: /var/log/apache.log
      
job="apache" <- 查询所有 key=job value = "apache"标签的日志
job="syslog" <- 查询所有key=job value = "syslog"标签的日志
job=~"apache|syslog" <- 查询所有key=job value = "syslog" 或者"syslog"标签的日志
env="dev" <- 查询所有 key=env value = "dev"标签的日志,本例中即是所有日志
  • 也可以通过正则表达式,动态地设置标签

    - job_name: system
       pipeline_stages:
          - regex:
            expression: "^(?P<ip>\\\\S+) (?P<identd>\\\\S+) (?P<user>\\\\S+) \\\\[(?P<timestamp>[\\\\w:/]+\\\\s[+\\\\-]\\\\d4)\\\\] \\"(?P<action>\\\\S+)\\\\s?(?P<path>\\\\S+)?\\\\s?(?P<protocol>\\\\S+)?\\" (?P<status_code>\\\\d3|-) (?P<size>\\\\d+|-)\\\\s?\\"?(?P<referer>[^\\"]*)\\"?\\\\s?\\"?(?P<useragent>[^\\"]*)?\\"?$"
        - labels:
            action:
            status_code:
       static_configs:
       - targets:
          - localhost
         labels:
          job: apache
          env: dev
          __path__: /var/log/apache.log

    上述表达式可以动态地将日志中的值(action="GET",action="POST",tatus_code="200",status_code="400")提取放入标签中。假设有如下日志:

    11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] "POST /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] "GET /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] "POST /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

    Loki会生成如下四条不同的流(标签key/value不同,job="apache",env="dev",action="GET",status_code="200"为一个标签组合),即4个新的日志,供之后查询调用;其他的日志行根据符合条件的标签加入到相应流中。

    job="apache",env="dev",action="GET",status_code="200" 11.11.11.11 - frank [25/Jan/2000:14:00:01 -0500] "GET /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    ​
    job="apache",env="dev",action="POST",status_code="200" 11.11.11.12 - frank [25/Jan/2000:14:00:02 -0500] "POST /1986.js HTTP/1.1" 200 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    ​
    job="apache",env="dev",action="GET",status_code="400" 11.11.11.13 - frank [25/Jan/2000:14:00:03 -0500] "GET /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"
    ​
    job="apache",env="dev",action="POST",status_code="400" 11.11.11.14 - frank [25/Jan/2000:14:00:04 -0500] "POST /1986.js HTTP/1.1" 400 932 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 GTB6"

(2)Loki组件

 

  • 数据写入流程如下

    1、分发器接收到HTTP请求后将数据按流的形式储存,每个流将会用哈希环转为哈希值

    2、分发器将各个流发送到相对应的日志存储器中

    3、分发器会把流数据压缩成块或追加到已有的(具有相同标签)的块中。对于每个租户和每个标签组,块都是独一无二的

    4、分发器通过HTTP连接响应回成功码

  • 数据读取流程

    1、查询器接收到获取数据的HTTP请求

    2、查询器将所有查询发送到日志存储器中

    3、日志存储器接收到请求后返回符合匹配查询条件的响应数据

    4、如果存储器没有返回数据,查询器将从后端仓库懒加载数据并运行查询语句

    5、查询器处理了接收到的数据后通过HTT连接返回数据

(3)Rules and the Ruler

  • Alerting Rules

    Alerting Rules可以定义基于LogQL表达式的的报警条件,当触发报警时可以向外部服务器发送通知信息,例子如下:

    groups:
      - name: should_fire
        rules:
          - alert: HighPercentageError
            expr: |
              sum(rate(app="foo", env="production" |= "error" [5m])) by (job)
                /
              sum(rate(app="foo", env="production"[5m])) by (job)
                > 0.05
            for: 10m
            labels:
                severity: page
            annotations:
                summary: High request latency
      - name: credentials_leak
        rules: 
          - alert: http-credentials-leaked
            annotations: 
              message: " $labels.job  is leaking http basic auth credentials."
            expr: 'sum by (cluster, job, pod) (count_over_time(namespace="prod" |~ "http(s?)://(\\\\w+):(\\\\w+)@" [5m]) > 0)'
            for: 10m
            labels: 
              severity: critical

    当标签为app="foo", env="production" 的错误日志占比超过5%的情况,发送告警信息

  • Recording Rules

    Recording Rules可以周期性地预计算所需的或统计性的表达式,并储存成一组新的度量数据

    name: nginxRules
    interval: 1m
    rules:
      - record: nginx:requests:rate1m
        expr: |
          sum(
            rate(container="nginx"[1m])
          )
        labels:
          cluster: "us-central1"

    该查询语句每隔一分钟会被执行,统计一分钟内nginx的请求的请求次数

(4)LogQL

LogQL是受到PromQL启发的查询语句,但是为Loki量身定制的。LogQL相当于是分布式系统中聚合日志源的grep命令,通过使用标签和运算符来过滤。

3、Grafana

Grafana提供用户界面。对标ELK中的Kibana

Grafana是一款开源的可视化和分析软件,它允许用户查询、可视化、警告和探索监控指标。Grafana主要提供时间序列数据的仪表板解决方案,支持超过数十种数据源

集成Loki

(1)Loki query editor

在Loki查询编辑器中可以使用LogQL语句创建日志和统计性查询

(2)Log browser

使用Loki日志浏览器,可以非常容易的浏览到所有的标签列表从而查询到相应的日志,也可以通过LogQL按需查询相应日志

Expolre

Grafana Explore模块支持深入探究、监察日志(支持Loki),查询的日志结果将已图表的形式进行可视化,对应的日志会在图表下方展示。用户也可以自定义日志的展示方法和图表的展现形式。

Alerts

Grafana Alerts模块支持发现系统运行时发生的问题,主要包括两个部分:

  • Alert rules - 报警何时会被触发,是根据一个或多个条件定义的规则,Grafana会周期性地进行评估

  • Notification channel-报警通过何种方式发送,支持钉钉,邮件等

当创建了Grafana仪表盘后,可在仪表盘下方配置报警条件、参数等,当前只有图形面板支持配置告警规则

4、方案对比

(1)首先,ELK/EFK架构功能确实强大,也经过了多年的实际环境验证,其中存储在Elasticsearch中的日志通常以非结构化JSON对象的形式存储在磁盘上,并且Elasticsearch为每个对象都建立了索引,以便进行全文搜索,然后用户可以特定查询语言来搜索这些日志数据。与之对应的Loki采用Golang开发,相比ES,Loki它更加轻量也更容易部署Loki中的日志带有一组标签名和值,其中只有标签对被索引,通过存储压缩的非结构化日志和仅索引元数据, Loki操作更简单,运行更便宜除此之外Loki特别适合存放 Kubernetes Pod日志; 诸如Pod标签之类的元数据会被自动删除和编入索引

(2)和Fluentd相比,Promtail是专门为Loki量身定制的,它可以为运行在同一节点上的Kubernetes Pods做服务发现,从指定文件夹读取日志。Loki采用了类似于Prometheus的标签方式。因此,当与Prometheus部署在同一个环境中时,因为相同的服务发现机制,来自Promtail的日志通常具有与应用程序指标相同的标签,统一了标签管理

(3)Kibana提供了许多可视化工具来进行数据分析,高级功能比如异常检测等机器学习功能。Grafana专门针对Prometheus和Loki等时间序列数据打造,可以在同一个仪表板上查看日志的指标

相关背景

官方对Loki的介绍:Like Prometheus,But For Logs.,是类似于 Prometheus 的日志系统

(1)Prometheus

Prometheus是Google监控系统BorgMon类似实现的开源版,整套系统由, 监控服务、告警服务、时序数据库等几个部分,及周边生态的各种指标收集器(Exporter)组成,是在当下主流的云原生监控告警系统

(2)PromQL

PromQL是Prometheus内置的一个强大的数据查询语言。 通过PromQL可以实现对监控数据的查询、聚合。同时PromQL也被应用于数据可视化(如Grafana)以及告警当中

使用loki+promtail实现云原生日志分析

                              **                      loki配置使用**

1 1. Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流配置一组标签。项目受 Prometheus 启发,官方的介绍就是:Like Prometheus, but for logs,类似于 Prometheus 的日志系统。

     2.  和其他日志系统不同的是,Loki 只会对你的日志元数据标签(就像 Prometheus 的标签一样)进行索引,而不会对原始的日志数据进行全文索引。然后日志数据本身会被压缩,并以 chunks(块)的形式存储在对象存储(比如 S3 或者 GCS)甚至本地文件系统。一个小的索引和高度压缩的 chunks 可以大大简化操作和降低 Loki 的使用成本。
  1. 对比其他日志系统

EFK(Elasticsearch、Fluentd、Kibana)用于从各种来源获取、可视化和查询日志。

Elasticsearch 中的数据以非结构化 JSON 对象的形式存储在磁盘上。每个对象的键和每个键的内容都有索引。然后可以使用 JSON 对象来定义查询(称为 Query DSL)或通过 Lucene 查询语言来查询数据。

相比之下,单二进制模式下的 Loki 可以将数据存储在磁盘上,但在水平可扩展模式下,数据存储需要在云存储系统中,如 S3、GCS 或 Cassandra。日志以纯文本的形式存储,并标记了一组标签的名称和值,其中只有标签会被索引。这种权衡使其操作起来比完全索引更便宜。Loki 中的日志使用 LogQL 进行查询。由于这种设计上的权衡,根据内容(即日志行内的文本)进行过滤的 LogQL 查询需要加载搜索窗口内所有与查询中定义的标签相匹配的块。

Fluentd 通常用于收集日志并转发到 Elasticsearch。Fluentd 被称为数据收集器,它可以从许多来源采集日志,并对其进行处理,然后转发到一个或多个目标。

相比之下,Promtail 是为 Loki 量身定做的。它的主要工作模式是发现存储在磁盘上的日志文件,并将其与一组标签关联的日志文件转发到 Loki。Promtail 可以为在同一节点上运行的 Kubernetes Pods 做服务发现,作为 Docker 日志驱动,从指定的文件夹中读取日志,并对 systemd 日志不断获取。

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

Kibana 被用于可视化和搜索 Elasticsearch 数据,并且在对这些数据进行分析时非常强大。Kibana 提供了许多可视化工具来做数据分析,例如地图、用于异常检测的机器学习,以及关系图。也可以配置报警,当出现意外情况时,可以通知用户。

相比之下,Grafana 是专门针对 Prometheus 和 Loki 等数据源的时间序列数据定制的。仪表板可以设置为可视化指标(即将推出的日志支持),也可以使用探索视图对数据进行临时查询。和 Kibana 一样,Grafana 也支持根据你的指标进行报警。

3.安装

  为了方便,我们使用helm安装(其他安装方法可参考github上的方式https://grafana.com/docs/loki/latest/installation/)
  1. 首先需要确保已经部署了 Kubernetes 集群,并安装配置了 Helm 客户端,然后添加 Loki 的 chart 仓库:

    这边我们使用的是helm3的版本

helm repo add loki https://grafana.github.io/loki/charts
helm repo add loki
更新chart仓库
helm repo update

[root@k8s-1 ~]# helm repo list
NAME URL
nginx-stable https://helm.nginx.com/stable
incubator http://mirror.azure.cn/kubernetes/charts-incubator/
jetstack https://charts.jetstack.io
harbor https://helm.goharbor.io
loki https://grafana.github.io/loki/charts

可以查看chart包有没有添加进来
使用namespace安装

helm upgrade --install loki --namespace=loki loki/loki

如果没有namespace可以创建

kubectl create ns loki

[root@k8s-1 ~]# kubectl get pods -n loki
NAME READY STATUS RESTARTS AGE
loki-0 1/1 Running 1 17h
promtail-dpdx7 1/1 Running 0 31m
promtail-kndlm 1/1 Running 0 31m
promtail-w7gbw 1/1 Running 0 31m

可以看到loki的pod已经running了
下面我们来安装Promtail(其他安装方式可以参考文档https://grafana.com/docs/loki/latest/clients/promtail/installation/)
也是使用的helm安装

?helm repo add loki https://grafana.github.io/loki/charts
helm repo update
?helm upgrade --install promtail loki/promtail --namespace=loki --set "loki.serviceName=loki" (指定namespace)
?[root@k8s-1 ~]# kubectl get pods -n loki
NAME READY STATUS RESTARTS AGE
loki-0 1/1 Running 1 17h
promtail-dpdx7 1/1 Running 0 31m
promtail-kndlm 1/1 Running 0 31m
promtail-w7gbw 1/1 Running 0 31m

可以看到promtail的pod已经running起来了
接下来我们在grafana页面配置
因为我已经装过grafana了,所以这里就没有安装grafana
我们先配置datasource

[root@k8s-1 ~]# kubectl get svc -n loki
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki ClusterIP 10.10.42.224 <none> 3100/TCP 17h
loki-headless ClusterIP None <none> 3100/TCP 17h

先查到cluster ip
技术图片
添加datasource
技术图片
可以看到数据源已经添加成功了
技术图片
按照箭头选择
技术图片
可以使用这种方式选择
技术图片
也可以使用这种方式选择
可以看到下面已经有日志信息了

以上是关于轻量级日志系统 PLG(**Promtail + Loki + Grafana**)架构技术调研的主要内容,如果未能解决你的问题,请参考以下文章

Linux搭建Promtail + Loki + Grafana 轻量日志监控系统

轻量级日志系统Loki stack

日志系统之 EFK vs. PLG Stack

Loki 日志系统分布式部署实践七 promtail 安装

Promtail + Loki + Grafana 日志监控系统搭建

轻量级日志采集系统Loki+grafana搭建