Loki日志聚合系统

2022-10-31 14:40:07 浏览数 (2)

loki简介

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

与其他日志聚合系统相比,Loki具有下面的一些特性:

  • 不对日志进行全文索引。通过存储压缩非结构化日志和仅索引元数据,Loki 操作起来会更简单,更省成本。
  • 通过使用与 Prometheus 相同的标签记录流对日志进行索引和分组,这使得日志的扩展和操作效率更高。
  • 特别适合储存 Kubernetes Pod 日志; 诸如 Pod 标签之类的元数据会被自动删除和编入索引。
  • 受 Grafana 原生支持。

Loki 由以下3个部分组成:

  • loki是主服务器,负责存储日志和处理查询。
  • promtail是代理,负责收集日志并将其发送给 loki 。
  • Grafana用于 UI 展示

Loki 的功能组件

  • promtail
  • distributor
  • ingester
  • querler
  • query frontend
  • overrides
  • tablemanager
  • runtimeconfig

Loki架构图

Promtail

Promtail 是负责日志数据的采集、提取、匹配、过滤、打 lables、Push to loki 这写工作的

支持的采集方式包括 File Target、Journal Target、Syslog Target、Stdin Target

整个 Promtail 对日志数据处理流程如下 Promtail数据处理流程图

Distributor

Distributor 主要接收 Promtail Push 过来的日志数据,并把日志数据分发给 Ingester

Distributor 与 Ingester 之间以 RPC 的方式进行通信,它通过对元数据进行 hash 算法计算出将日志数据分发到哪一个 Ingester 上

Distributor 以日志数据的 TenantID、Labels 作为 Hash key

Ingester

Ingester 负责接收数据并构建 chunk,存储日志索引及数据

Ingester构建chunk

当一个 chunk 填充满之后,ingester 将其刷新到数据库,块和索引分别进行存储

Ingester存储chunk和index

刷新完一个 chunk 之后,Ingester 会创建一个空的 chunk

Querier

Querier 负责数据读取,它通过给定的一个时间范围和标签选择器,查看索引以确定哪些块匹配,并通过 greps 聚合各个 Ingester 中的数据,并将结果返回给 client

Grafana

Loki 的数据查询,都是通过 Grafana,在 Grafana 中支持 loki 的数据源,通过配置 Loki 的接口地址即可

Grafana 的查询,支持 LogQL,在 Grafana 中查询都是通过 Label 或 log 文本,支持语法如下:

Lable 的操作符:

  • = exactly equal
  • != not equal
  • =~ regex-match
  • !~ do not regex-match

Loki语法说明

选择器

对于查询表达式的标签部分,将其包装在花括号中{},然后使用键值对的语法来选择标签,多个标签表达式用逗号分隔,比如

  • |=:日志行包含字符串。
  • !=:日志行不包含字符串。
  • |~:日志行匹配正则表达式。
  • !~:日志行与正则表达式不匹配

精确匹配:|=“2020-11-16 "

代码语言:shell复制
{app_kubernetes_io_instance="x'x'x'x"}|="2020-11-16 "

模糊匹配:|~“2020-11-16 "

代码语言:shell复制
{app_kubernetes_io_instance="x'x'x'x'x"}|~"2020-11-16 "

排除过滤:!=/!~ “数据中心”

代码语言:shell复制
{app_kubernetes_io_instance="x'x'x'x'x"}!="数据中心"
{app_kubernetes_io_instance="x'x'x'x'x'x'x'x'x"}!~"数据中心"

正则匹配: |~ “()”

代码语言:shell复制
{app_kubernetes_io_instance="x'x'x'x'x'x"}!~"(admin|web)"
{app_kubernetes_io_instance="x'x'x'x'x'x'x"}|~"ERROR|error"
范围查询
  • rate:计算每秒的条目数
  • count_over_time:计算给定范围内每个日志流的条目

三十分钟日志行记录

代码语言:shell复制
count_over_time({app_kubernetes_io_instance="UUUU"}[30m]) 

12h小时内出现错误的速率

代码语言:shell复制
rate({app_kubernetes_io_instance=~".*UUUUU.*"} |~ "ERROR|error" [12h])
集合运算

与PromQL一样,LogQL支持内置聚合运算符的一个子集,可用于聚合单个向量的元素,从而产生具有更少元素但具有集合值的新向量:

  • sum:计算标签上的总和
  • min:选择最少的标签
  • max:选择标签上方的最大值
  • avg:计算标签上的平均值
  • stddev:计算标签上的总体标准差
  • stdvar:计算标签上的总体标准方差
  • count:计算向量中元素的数量
  • bottomk:通过样本值选择最小的k个元素
  • topk:通过样本值选择最大的k个元素

统计1个小时日志量最大的前10个服务

代码语言:shell复制
topk(10,sum(rate({app_kubernetes_io_instance=~".*uuuu.*"}[60m])) by(container))

统计最近6小时内错误日志计数

代码语言:shell复制
sum(count_over_time({app_kubernetes_io_instance=~".*uuuuuu.*"}|~"ERROR"[6h])) by (container)
Loki Url 表达式编写

url如下

代码语言:shell复制
https://localhost:3100/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"user-service"}|~"2020-11-05"|~"ERROR"|~".aaa."","maxLines":5000}]

分析

  • 1、| 表示|
  • 2、" 表示”
  • 3、时间:now-1h 可替换 now-1min或者 now-5min
  • 4、项目名称:user-service 可替换为 .service. 或者 web-service
  • 5、查询日志:2020-11-05 可替换为 2020-11-04
  • 6、删除一个管道 |"ERROR"|".aaa." 这一段删除
  • 最后生成的链接粘贴到浏览器访问 也可通过url加解密生成最终查询url链接

url加解密

进入指定网站中,https://www.sojson.com/encodeurl.html

上例中解密如下:

代码语言:shell复制
https://localhsot/explore?orgId=1&left=["now-1m","now","Loki",{"expr":"{app_kubernetes_io_instance="user-service-"}|"2020-11-05"|"ERROR"|".aaaaa."","maxLines":5000}]
根据自定义查询语句

根据日期查询

  • 编写查询语句
代码语言:shell复制
https://lcoalhsot/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"user-service"}|~"2020-11-18"","maxLines":5000}]
  • 加密
代码语言:shell复制
https://lcoalhsot/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"user-service"}|~"2020-11-18"","maxLines":5000}]

根据服务名称查询

  • 编写查询语句
代码语言:shell复制
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"data-service"}|~"2020-11-18"","maxLines":5000}]
  • 加密
代码语言:shell复制
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"data-service"}|~"2020-11-18"","maxLines":5000}]

根据对应的数据库查询

  • 编写查询语句
代码语言:shell复制
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"data-service"}|~"2020-11-18"|~"database"","maxLines":5000}]
  • 加密
代码语言:shell复制
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~"data-service"}|~"2020-11-18"|~"database"","maxLines":5000}]

加密好的url直接粘贴到浏览器中即可查询

Loki api使用

查询标签

代码语言:shell复制
curl -G -s  "http://localhost:3100/loki/api/v1/labels" | jq
代码语言:shell复制
curl -G -s  "http://lcoalhpst:3100/loki/api/v1/labels" | jq .data[]
"__name__"
"app"
"app_kubernetes_io_component"
"app_kubernetes_io_instance"
"app_kubernetes_io_managed_by"
"app_kubernetes_io_name"
"app_kubernetes_io_version"
"chart"
"component"
"container"
"controller_revision_hash"
"filename"
"helm_sh_chart"
"heritage"
"job"
"k8s_app"
"name"
"namespace"
"pod"
"pod_template_generation"
"pod_template_hash"
"release"
"releaseRevision"
"statefulset_kubernetes_io_pod_name"
"stream"
"task"

根据标签查询对应标签值

代码语言:shell复制
curl -G -s http://localhost:3100/loki/api/v1/label/<name>/values |jq
代码语言:shell复制
curl -G -s  "http://lcoalhost:3100/loki/api/v1/label/app_kubernetes_io_instance/values" | jq .data[]
"web-service"
"user-service"

根据标签查询对应的日志

代码语言:shell复制

curl -G -s http://localhost:3100/loki/api/v1/query_range | jq
  • 查询对应日志
代码语言:shell复制
curl -G -s  "http://lcoalhost:3100/loki/api/v1/query_range" --data-urlencode 'query={app_kubernetes_io_instance=~".*user-service.*"}|~"ERROR|error"' | jq .data.result | jq .[].values[0][1]

Loki安装部署

使用Helm安装Loki
前提

首先需要确保已经部署了 Kubernetes 集群,并安装配置了 Helm 客户端,然后添加 Loki 的 chart 仓库:

代码语言:shell复制
helm repo add loki https://grafana.github.io/loki/charts

可以使用如下命令更新chart仓库:

代码语言:shell复制
helm repo update
部署Loki

使用默认配置部署

代码语言:shell复制
helm upgrade --install loki loki/loki-stack

指定命名空间

代码语言:shell复制
helm upgrade --install loki --namespace=logging loki/loki

指定配置

代码语言:shell复制
helm upgrade --install loki loki/loki --set "key1=val1,key2=val2,..."

部署 Loki 工具栈(Loki, Promtail, Grafana, Prometheus)

代码语言:shell复制
helm upgrade --install loki loki/loki-stack 
    --set fluent-bit.enabled=true,promtail.enabled=false,grafana.enabled=true,prometheus.enabled=true,prometheus.alertmanager.persistentVolume.enabled=false,prometheus.server.persistentVolume.enabled=false
部署grafana

使用 Helm 安装 Grafana 到 Kubernetes 集群,可以使用如下所示命令:

代码语言:shell复制
helm install stable/grafana -n loki-grafana

要获取 Grafana 管理员密码,可以使用如下所示命令:

代码语言:shell复制
kubectl get secret --namespace <YOUR-NAMESPACE> loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

要访问 Grafana UI 页面,可以使用下面的命令:

代码语言:shell复制
kubectl port-forward --namespace <YOUR-NAMESPACE> service/loki-grafana 3000:80

然后在浏览器中打开http://localhost:3000,用 admin 和上面输出的密码进行登录。然后 按照提示添加 Loki 数据源,Loki 地址为http://loki:3100

使用Docker安装Loki
前提
  • Docker
  • Docker-compose
使用docker安装

执行完成后,loki-config.yaml 和 promtail-config.yaml 两个配置文件会被下载到我们使用的目录下面,Docker 容器会使用这些配置文件来运行 Loki 和 Promtail

代码语言:shell复制
wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml
docker run -v $(pwd):/mnt/config -p 3100:3100 grafana/loki:1.5.0 -config.file=/mnt/config/loki-config.yaml
$ wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/cmd/promtail/promtail-docker-config.yaml -O promtail-config.yaml
docker run -v $(pwd):/mnt/config -v /var/log:/var/log grafana/promtail:1.5.0 -config.file=/mnt/config/promtail-config.yaml
使用Docker Compose安装
代码语言:shell复制
wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/production/docker-compose.yaml -O docker-compose.yaml
docker-compose -f docker-compose.yaml up

0 人点赞