[TOC]
0x00 快速入门 1.什么是 Loki ? 描述:在对公司容器的日志存储查询方案进行设计的时候,发现主流的 ELK (Elasticsearch, Logstash, Kibana)
或者 EFK (Elasticsearch, Filebeat or Fluentd, Kibana)
比较重,再加上现阶段对于 ES 复杂的搜索功能很多都用不上,最终选择了 Grafana 开源的 Loki 日志系统即 PLG 日志解决方案。
本篇文章将主要介绍使用 Loki 实现 Kubernetes 容器日志监控的相关知识,感兴趣的朋友一起看看吧!
本章完整原文首发地址 : 如何使用Grafana+Loki+Promtail日志聚合系统针对Kubernetes集群中Pods应用日志采集搜索展示-https://mp.weixin.qq.com/s/zRg9ePFbVKyLxgy-K2TJHg
什么是 Grafana Loki?
官方介绍: Like Prometheus, but for logs. Grafana Loki 是一个日志聚合系统,旨在存储和查询来自所有应用程序和基础架构的日志。 Grafana Loki 项目由 Grafana Labs 团队开发,并在 2018 年的 KubeCon 上发布 (在 AGPLv3 许可下发布), 其基于 Go 语言实现,它是一个受 Prometheus 启发的水平可扩展,高可用性,多租户的日志聚合系统, 其相对比于ELK更加轻量级,它的设计非常具有成本效益且易于操作。
那 Loki 与 Promethus 区别在什么地方呢?
答:Loki 与 Prometheus 的不同之处在于专注于日志而不是指标,并且通过推送而不是拉取来传递日志。
在生产实践环境中 Loki 常常与 Grafana 联合使用, 提供了一种界面化对 Loki 中存储的日志进行查询并可视化查询结果的方法,所以 Grafana Labs提供的另一个日志解决方案 PLG 目前也逐渐变得流行起来。
PLG 架构为 Promtail + Loki + Grafana
的组合,整体架构图下所示:
weiyigeek.top-PLG
其中所有组件说明:
Grafana 大家应该都比较熟悉,它是一款开源的可视化和分析软件,它允许用户查询、可视化、警告和探索监控指标.
Loki 是一组可以组成一个功能齐全的日志堆栈组件, 负责存储日志和处理查询。
Promtail 是一个日志收集的代理, 其类似于 ELk 中的 filebeat 的 日志采集端 agent,负责收集日志并将其发送给 Loki。
2.为什么要使用 Grafana Loki? 描述:Loki 采用了一种独特的方法,它只索引元数据而不是日志行的全文,并且为每个日志流设置一组标签,Loki 的最小索引方法意味着在 Loki 中存储同一组日志所需的存储空间比其他解决方案少得多,例如下图
weiyigeek.top-Loki-元数据
温馨提示: 从图纸中可以看到Loki针对时间戳和标签键值对进行了索引, 这极大的方便我们进行日志查询。
Loki 优点介绍
容易上手, 因为您可以使用各种客户端从任何来源以任何格式发送日志。
对象存储持久化, 意味着您可以获得 PB 级规模、高吞吐量和经济高效且耐用的存储。
告警通知, 可以通过采用的日志对比预定的告警阈值进行相应告警通知。
灵活的日志格式, 为您提供更大的灵活性和在查询时进行格式设置的选项。
实时跟踪应用日志, 以查看进入系统的日志、每隔特定时间更新日志、查看特定日期的日志等。
云原生环境集成, 可以非常方便的与 Prometheus、Grafana 和 K8s 原生集成.
与其他日志聚合系统相比
不像ELK对日志进行全文索引, 通过存储压缩的非结构化日志和仅索引元数据Loki 操作更简单,运行成本更低、效率也提升了。
使用已在 Prometheus 中使用的相同标签对日志流进行索引和分组,使您能够使用已在 Prometheus 中使用的相同标签在指标和日志之间无缝切换。
特别适合存储 Kubernetes Pod 日志, Pod 标签等元数据会被自动抓取和索引。
在 Grafana 中有原生支持(需要 Grafana v6.0)。
在 Loki 架构中类比与 EFK 几个概念:
Grafana:相当于 EFK 中的 Kibana ,用于 UI 的展示。
Loki:相当于 EFK 中的 ElasticSearch ,用于存储日志和处理查询。
Promtail:相当于 EFK 中的 Filebeat/Fluentd ,用于采集日志并将其发送给 Loki 。
LogQL:Loki 提供的日志查询语言,类似 Prometheus 的 PromQL,而且 Loki 支持 LogQL 查询直接转换为 Prometheus 指标。
3.Grafana Loki 是如何工作的? 描述: 我们可以官方图示中看出 Grafana Loki 的工作流程。
步骤 01.Promtail 是专门为 Loki 构建的日志收集器,我们使用 Promtail 拉入任何日志,它使用与 Prometheus 相同的服务发现功能,并包括在将日志摄取到 Loki 之前标记、转换和过滤日志的类似功能。
步骤 02.promtail 将采集到的日志存储在 Loki 存储空间中,Loki 不索引日志文本,只将时间戳与标签进行索引,这不仅可以降低成本,还意味着可以在 Loki 接收到的几毫秒内查询日志行。
步骤 03.使用 Grfana 接入 Loki 数据源, 然后直接在 Grafana 中运行 LogQL 查询,以将您的日志与其他数据源一起可视化,或者使用 LogCLI 来显示查询到可视化数据。
步骤 04.最后我们还可以为 Loki 设置警报规则以评估传入的日志数据,配置 Loki 以将生成的警报发送到 Prometheus Alertmanager 中,从而进行告警。
4.Grafana Loki 架构简述 描述: Loki 整体架构也是由不同的组件来协同完成日志收集、索引、存储等工作的各个组件如下图所示。
weiyigeek.top-Loki Architecture
架构图剖析: Loki 采用读写分离架构,关键组件有:
Distributor 分发器(日志分发):日志数据传输的“第一站”,Distributor 分发器接收到日志数据后,根据元数据和 hash 算法,将日志分批并行地发送到多个 Ingester 接收器上
Ingester 接收器(日志持久化):接收器是一个有状态的组件,在日志进入时对其进行 gzip 压缩操作,并负责构建和刷新 chunck 块,当 chunk 块达到一定的数量或者时间后,就会刷新 chunk 块和对应的 Index 索引存储到数据库中
Querier 查询器 (查询解析):给定一个时间范围和标签选择器,Querier 查询器可以从数据库中查看 Index 索引以确定哪些 chunck 块匹配,并通过 greps 将结果显示出来,它还会直接从 Ingester 接收器获取尚未刷新的最新数据
Query Frontend 查询前端(查询API):查询前端是一个可选的组件,运行在 Querier 查询器之前,起到缓存,均衡调度的功能,用于加速日志查询
Ruler 预警规则: Ruler 规则规定了何种情况向 altermanger 发送,其语法规则近似于 Prometheus Alertmanager 中告警规则。
Object Store:存储采集到的日志index索引与Chunks。
Memcaches: 缓存写入、查询结果,加快查询效率。
Cluster Services: 包含 compactor 与 consul 服务发现组件。
温馨提示: 我们可以通过 loki 二进制的 -target
参数指定运行角色(querier/inester/query-frontend/distributor)
.
5.Grafana Loki 参考来源 官方地址:https://grafana.com/oss/loki/
项目地址: https://github.com/grafana/loki
开始: https://grafana.com/docs/loki/latest/getting-started/
安装参考: https://grafana.com/docs/loki/latest/installation/
0x01 安装部署 描述: 我们可以使用多种方式进行安装 Loki 和 Promtail 组件,其中最常用的是使用 Helm 部署微服务、使用 Helm 进行简单的可扩展部署、通过 Docker 或 Docker Compose 安装、在本地安装和运行或者从源代码安装。
常规使用 Step 1.下载并安装 Loki 和 Promtail。 Step 2.下载两个程序的配置文件。 Step 3.启动 Loki。 Step 4.更新 Promtail 配置文件,让您的日志进入 Loki。 Step 5.开始在Grafana中浏览日志。
Loki 三种部署方式
单体模式 (Monolithic mode)
,ALL IN ONE : Loki 支持单一进程模式,可在一个进程中运行所有必需的组件。单进程模式非常适合测试 Loki 或以小规模运行。不过尽管每个组件都以相同的进程运行,但它们仍将通过本地网络相互连接进行组件之间的通信(grpc)。使用 Helm 部署就是采用的该模式。
简单可扩展模式 (Simple scalable deployment mode)
: 如果您每天的日志量超过几百 GB,或者如果您想分离读写关注点, Loki 提供了简单的可扩展部署模式, 该模式下每天存储的日志量可到TB级别,其分离读写路径有以下优点通过提供专用节点提高写入路径的可用性,可单独扩展的读取路径以按需添加/删除查询性能。
微服务模式 (Microservices mode)
:为了实现水平可伸缩性,Loki 支持组件拆分为单独的组件分开部署,从而使它们彼此独立地扩展。每个组件都产生一个用于内部请求的 gRPC 服务器和一个用于外部 API 请求的 HTTP 服务,所有组件都带有 HTTP 服务器,但是大多数只暴露就绪接口、运行状况和指标端点。
[TOC]
0x00 快速入门 1.什么是 Loki ? 描述:在对公司容器的日志存储查询方案进行设计的时候,发现主流的 ELK (Elasticsearch, Logstash, Kibana)
或者 EFK (Elasticsearch, Filebeat or Fluentd, Kibana)
比较重,再加上现阶段对于 ES 复杂的搜索功能很多都用不上,最终选择了 Grafana 开源的 Loki 日志系统即 PLG 日志解决方案。
本篇文章将主要介绍使用 Loki 实现 Kubernetes 容器日志监控的相关知识,感兴趣的朋友一起看看吧!
本章完整原文首发地址 : 如何使用Grafana+Loki+Promtail日志聚合系统针对Kubernetes集群中Pods应用日志采集搜索展示-https://mp.weixin.qq.com/s/zRg9ePFbVKyLxgy-K2TJHg
什么是 Grafana Loki?
官方介绍: Like Prometheus, but for logs. Grafana Loki 是一个日志聚合系统,旨在存储和查询来自所有应用程序和基础架构的日志。 Grafana Loki 项目由 Grafana Labs 团队开发,并在 2018 年的 KubeCon 上发布 (在 AGPLv3 许可下发布), 其基于 Go 语言实现,它是一个受 Prometheus 启发的水平可扩展,高可用性,多租户的日志聚合系统, 其相对比于ELK更加轻量级,它的设计非常具有成本效益且易于操作。
那 Loki 与 Promethus 区别在什么地方呢?
答:Loki 与 Prometheus 的不同之处在于专注于日志而不是指标,并且通过推送而不是拉取来传递日志。
在生产实践环境中 Loki 常常与 Grafana 联合使用, 提供了一种界面化对 Loki 中存储的日志进行查询并可视化查询结果的方法,所以 Grafana Labs提供的另一个日志解决方案 PLG 目前也逐渐变得流行起来。
PLG 架构为 Promtail + Loki + Grafana
的组合,整体架构图下所示:
weiyigeek.top-PLG
其中所有组件说明:
Grafana 大家应该都比较熟悉,它是一款开源的可视化和分析软件,它允许用户查询、可视化、警告和探索监控指标.
Loki 是一组可以组成一个功能齐全的日志堆栈组件, 负责存储日志和处理查询。
Promtail 是一个日志收集的代理, 其类似于 ELk 中的 filebeat 的 日志采集端 agent,负责收集日志并将其发送给 Loki。
2.为什么要使用 Grafana Loki? 描述:Loki 采用了一种独特的方法,它只索引元数据而不是日志行的全文,并且为每个日志流设置一组标签,Loki 的最小索引方法意味着在 Loki 中存储同一组日志所需的存储空间比其他解决方案少得多,例如下图
weiyigeek.top-Loki-元数据
温馨提示: 从图纸中可以看到Loki针对时间戳和标签键值对进行了索引, 这极大的方便我们进行日志查询。
Loki 优点介绍
容易上手, 因为您可以使用各种客户端从任何来源以任何格式发送日志。
对象存储持久化, 意味着您可以获得 PB 级规模、高吞吐量和经济高效且耐用的存储。
告警通知, 可以通过采用的日志对比预定的告警阈值进行相应告警通知。
灵活的日志格式, 为您提供更大的灵活性和在查询时进行格式设置的选项。
实时跟踪应用日志, 以查看进入系统的日志、每隔特定时间更新日志、查看特定日期的日志等。
云原生环境集成, 可以非常方便的与 Prometheus、Grafana 和 K8s 原生集成.
与其他日志聚合系统相比
不像ELK对日志进行全文索引, 通过存储压缩的非结构化日志和仅索引元数据Loki 操作更简单,运行成本更低、效率也提升了。
使用已在 Prometheus 中使用的相同标签对日志流进行索引和分组,使您能够使用已在 Prometheus 中使用的相同标签在指标和日志之间无缝切换。
特别适合存储 Kubernetes Pod 日志, Pod 标签等元数据会被自动抓取和索引。
在 Grafana 中有原生支持(需要 Grafana v6.0)。
在 Loki 架构中类比与 EFK 几个概念:
Grafana:相当于 EFK 中的 Kibana ,用于 UI 的展示。
Loki:相当于 EFK 中的 ElasticSearch ,用于存储日志和处理查询。
Promtail:相当于 EFK 中的 Filebeat/Fluentd ,用于采集日志并将其发送给 Loki 。
LogQL:Loki 提供的日志查询语言,类似 Prometheus 的 PromQL,而且 Loki 支持 LogQL 查询直接转换为 Prometheus 指标。
3.Grafana Loki 是如何工作的? 描述: 我们可以官方图示中看出 Grafana Loki 的工作流程。
步骤 01.Promtail 是专门为 Loki 构建的日志收集器,我们使用 Promtail 拉入任何日志,它使用与 Prometheus 相同的服务发现功能,并包括在将日志摄取到 Loki 之前标记、转换和过滤日志的类似功能。
步骤 02.promtail 将采集到的日志存储在 Loki 存储空间中,Loki 不索引日志文本,只将时间戳与标签进行索引,这不仅可以降低成本,还意味着可以在 Loki 接收到的几毫秒内查询日志行。
步骤 03.使用 Grfana 接入 Loki 数据源, 然后直接在 Grafana 中运行 LogQL 查询,以将您的日志与其他数据源一起可视化,或者使用 LogCLI 来显示查询到可视化数据。
步骤 04.最后我们还可以为 Loki 设置警报规则以评估传入的日志数据,配置 Loki 以将生成的警报发送到 Prometheus Alertmanager 中,从而进行告警。
4.Grafana Loki 架构简述 描述: Loki 整体架构也是由不同的组件来协同完成日志收集、索引、存储等工作的各个组件如下图所示。
weiyigeek.top-Loki Architecture
架构图剖析: Loki 采用读写分离架构,关键组件有:
Distributor 分发器(日志分发):日志数据传输的“第一站”,Distributor 分发器接收到日志数据后,根据元数据和 hash 算法,将日志分批并行地发送到多个 Ingester 接收器上
Ingester 接收器(日志持久化):接收器是一个有状态的组件,在日志进入时对其进行 gzip 压缩操作,并负责构建和刷新 chunck 块,当 chunk 块达到一定的数量或者时间后,就会刷新 chunk 块和对应的 Index 索引存储到数据库中
Querier 查询器 (查询解析):给定一个时间范围和标签选择器,Querier 查询器可以从数据库中查看 Index 索引以确定哪些 chunck 块匹配,并通过 greps 将结果显示出来,它还会直接从 Ingester 接收器获取尚未刷新的最新数据
Query Frontend 查询前端(查询API):查询前端是一个可选的组件,运行在 Querier 查询器之前,起到缓存,均衡调度的功能,用于加速日志查询
Ruler 预警规则: Ruler 规则规定了何种情况向 altermanger 发送,其语法规则近似于 Prometheus Alertmanager 中告警规则。
Object Store:存储采集到的日志index索引与Chunks。
Memcaches: 缓存写入、查询结果,加快查询效率。
Cluster Services: 包含 compactor 与 consul 服务发现组件。
温馨提示: 我们可以通过 loki 二进制的 -target
参数指定运行角色(querier/inester/query-frontend/distributor)
.
5.Grafana Loki 参考来源 官方地址:https://grafana.com/oss/loki/
项目地址: https://github.com/grafana/loki
开始: https://grafana.com/docs/loki/latest/getting-started/
安装参考: https://grafana.com/docs/loki/latest/installation/
0x01 安装部署 描述: 我们可以使用多种方式进行安装 Loki 和 Promtail 组件,其中最常用的是使用 Helm 部署微服务、使用 Helm 进行简单的可扩展部署、通过 Docker 或 Docker Compose 安装、在本地安装和运行或者从源代码安装。
常规使用 Step 1.下载并安装 Loki 和 Promtail。 Step 2.下载两个程序的配置文件。 Step 3.启动 Loki。 Step 4.更新 Promtail 配置文件,让您的日志进入 Loki。 Step 5.开始在Grafana中浏览日志。
Loki 三种部署方式
单体模式 (Monolithic mode)
,ALL IN ONE : Loki 支持单一进程模式,可在一个进程中运行所有必需的组件。单进程模式非常适合测试 Loki 或以小规模运行。不过尽管每个组件都以相同的进程运行,但它们仍将通过本地网络相互连接进行组件之间的通信(grpc)。使用 Helm 部署就是采用的该模式。
简单可扩展模式 (Simple scalable deployment mode)
: 如果您每天的日志量超过几百 GB,或者如果您想分离读写关注点, Loki 提供了简单的可扩展部署模式, 该模式下每天存储的日志量可到TB级别,其分离读写路径有以下优点通过提供专用节点提高写入路径的可用性,可单独扩展的读取路径以按需添加/删除查询性能。
微服务模式 (Microservices mode)
:为了实现水平可伸缩性,Loki 支持组件拆分为单独的组件分开部署,从而使它们彼此独立地扩展。每个组件都产生一个用于内部请求的 gRPC 服务器和一个用于外部 API 请求的 HTTP 服务,所有组件都带有 HTTP 服务器,但是大多数只暴露就绪接口、运行状况和指标端点。1 2 3 4 5 6 7 8 9 distributor ingester querier query-scheduler query-frontend index-gateway ruler compactor
三种部署模式参考: https://grafana.com/docs/loki/latest/fundamentals/architecture/deployment-modes/
以 二进制方式 安装 Loki 与 Promtail 描述: 在进行容器化部署时,建议初学者先使用单节点主机模式部署各个组件,熟悉一下整个流程,然后在进行容器化部署。
实践环境 1 2 3 4 ~$ cat /etc/issue.net Ubuntu 20.04.4 LTS ~$ uname -a Linux devtest-102 5.4.0-59-generic
实践步骤
Step 1.下载 Loki 与 Promtail 最新而二进制文件并准备安装配置文件, 当前最新版本release查看(https://github.com/grafana/loki/releases/)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 mkdir -vp /usr/local /loki/{config,data}; mkdir -vp /usr/local /loki/data/{loki,promtail} cd /usr/local /lokiLOKI_VERSION=v2.6.0 curl -O -L https://github.com/grafana/loki/releases/download/${LOKI_VERSION} /loki-linux-amd64.zip curl -O -L https://github.com/grafana/loki/releases/download/${LOKI_VERSION} /promtail-linux-amd64.zip curl -O -L https://github.com/grafana/loki/releases/download/${LOKI_VERSION} /logcli-linux-amd64.zip $ ls logcli-linux-amd64.zip loki-linux-amd64.zip promtail-linux-amd64.zip unzip "loki-linux-amd64.zip" unzip promtail-linux-amd64.zip unzip logcli-linux-amd64.zip chmod a+x logcli-linux-amd64 loki-linux-amd64 promtail-linux-amd64 ln -s $(pwd )/loki-linux-amd64 /usr/local /bin/loki ln -s $(pwd )/promtail-linux-amd64 /usr/local /bin/promtail ln -s $(pwd )/logcli-linux-amd64 /usr/local /bin/logcli
Step 2.使用 systemd 管理 loki 与 Promtail 准备的服务器清单如下。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 cat <<EOF > /usr/lib/systemd/system/loki.service [Unit] Description=loki.service Wants=network-online.target After=network-online.target [Service] Type=simple ExecStart=/usr/local /loki/loki-linux-amd64 -log.level=info -target all -config.file=/usr/local /loki/config/loki-config.yaml WorkingDirectory=/usr/local /loki/ LimitMEMLOCK=infinity LimitNPROC=65536 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF cat <<EOF > /usr/lib/systemd/system/promtail.service [Unit] Description=promtail.service Wants=network-online.target After=network-online.target [Service] Type=simple ExecStart=/usr/local /loki/promtail-linux-amd64 -config.file=/usr/local /loki/config/promtail.conf WorkingDirectory=/usr/local /loki/ LimitMEMLOCK=infinity LimitNPROC=65536 LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF
扩展补充: 我们也可使用 supervisor 管理进程, Supervisor 是Python编写的 Client/Server 模式的系统,通过supervisor,可以对类Unix操作系统的进程进行监控和管理,可以方便地进行进程集中管理,并监控进程的状态, 当程序异常退出时,可以自动拉起程序,起到守护进程的作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 sudo yum install epel-release -y sudo yum install supervisor -y sed -i '/forking/a LimitNOFILE=65536' /usr/lib/systemd/system/supervisord.service; sed -i '/forking/a LimitNPROC=65536' /usr/lib/systemd/system/supervisord.service; sed -i '/forking/a LimitMEMLOCK=infinity' /usr/lib/systemd/system/supervisord.service; systemctl daemon-reload systemctl enable supervisord systemctl start supervisord mkdir -vp /usr/local /loki/{loki,promtail,config} /var/log /loki/ cat <<EOF> /etc/supervisord.d/loki.ini [program:loki] command =/usr/local /loki/loki-linux-amd64 -log.level=info -target all -config.file=/usr/local /loki/config/loki-config.yamlautorestart=true autostart=true stderr_logfile=/var/log /loki/loki_err.log stdout_logfile=/var/log /loki/loki_out.log user=root stopsignal=INT startsecs=10 startretries=3 directory=/usr/local /loki/ EOF cat << EOF > /etc/supervisord.d/promtail.ini [program:promtail] command =/usr/local /loki/promtail-linux-amd64 -config.expand-env=true -config.file=/usr/local /loki/config/promtail.confautorestart=true autostart=true stderr_logfile=/var/log /loki/promtail_err.log stdout_logfile=/var/log /loki/promtail_out.log user=root stopsignal=INT startsecs=10 startretries=3 directory=/usr/local /loki/ EOF
Step 3.Loki 配置文件(loki-config.yaml) 与 promtail 配置文件(promtail.conf) 分别如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 tee /usr/local /loki/config/loki-config.yaml <<'EOF' auth_enabled: false server: http_listen_port: 3100 grpc_listen_port: 9096 ingester: wal: enabled: true dir: /usr/local /loki/data/loki/wal lifecycler: address: 127.0.0.1 ring: kvstore: store: inmemory replication_factor: 1 final_sleep: 0s chunk_idle_period: 1h max_chunk_age: 1h chunk_target_size: 10485760 chunk_retain_period: 30s max_transfer_retries: 0 schema_config: configs: - from: 2022-07-15 store: boltdb-shipper object_store: filesystem schema: v11 index: prefix: index_ period: 24h storage_config: boltdb_shipper: active_index_directory: /usr/local /loki/data/loki/boltdb-shipper-active cache_location: /usr/local /loki/data/loki/boltdb-shipper-cache cache_ttl: 24h shared_store: filesystem filesystem: directory: /usr/local /loki/data/loki/chunks compactor: working_directory: /usr/local /loki/data/loki/boltdb-shipper-compactor shared_store: filesystem limits_config: enforce_metric_name: false reject_old_samples: true reject_old_samples_max_age: 168h ingestion_rate_mb: 200 chunk_store_config: max_look_back_period: 0s table_manager: retention_deletes_enabled: true retention_period: 4368h ruler: storage: type : local local : directory: /usr/local /loki/data/loki/rules rule_path: /usr/local /loki/data/loki/rules-temp alertmanager_url: http://10.0.30.200:9093 ring: kvstore: store: inmemory enable_api: true EOF tee /usr/local /loki/config/promtail.conf <<'EOF' server: log_level: error http_listen_address: 0.0.0.0 http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /usr/local /loki/data/promtail/positions.yaml client: url: http://localhost:3100/loki/api/v1/push scrape_configs: - job_name: system pipeline_stages: static_configs: - targets: - localhost labels: job: systemd-logs host: 10.20.176.102 __path__: /var/log /*.log - job_name: messages static_configs: - targets: - localhost labels: job: messages-logs host: 10.20.176.102 __path__: /var/log /messages - job_name: dmesg static_configs: - targets: - localhost labels: job: dmesg-logs host: 10.20.176.102 __path__: /var/log /dmesg - job_name: journal journal: max_age: 12h labels: job: systemd-journal relabel_configs: - source_labels: ['__journal__systemd_unit' ] target_label: 'unit' EOF mkdir -vp /usr/local /loki/data/loki/rules/fake tee /usr/local /loki/data/loki/rules/fake/rules.yaml <<'EOF' groups: - name: service OutOfMemoryError rules: - alert: loki check words java.lang.OutOfMemoryError expr: sum by (env, hostname, log_type, filename) (count_over_time({env=~"\\w+" } |= "java.lang.OutOfMemoryError" [5m]) > 0) labels: severity: critical annotations: description: '{{$labels.env}} {{$labels.hostname}} file {{$labels.filename}} has {{ $value }} error' summary: java.lang.OutOfMemoryError - alert: loki java full gc count check expr: sum by (env, hostname, log_type, filename) (count_over_time({env=~"\\w+" } |= "Full GC (Allocation" [5m]) > 5) labels: severity: warning annotations: description: '{{$labels.env}} {{$labels.hostname}} {{$labels.filename}} {{ $value }}' summary: java full gc count check - alert: dbperform slowlog sql 慢查询 expr: 'sum by (env, hostname, log_type, filename) (count_over_time({env=~"\\w+"} |~ "time: [1-9]\\d{4,}" [5m]) > 5)' labels: severity: warning annotations: description: '{{$labels.env}} {{$labels.hostname}} file {{$labels.filename}} has {{ $value }} error' summary: sql slowlog EOF
温馨提示: 关于labels,官网建议labels个数越少越好,过多的labels将会影响Loki日志的检索速度。
Step 4.设置Loki与Promtail服务开机启动并启动服务。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 systemctl daemon-reload systemctl enable loki.service;systemctl enable promtail.service systemctl restart loki.service promtail.service $ systemctl status loki.service ● loki.service Loaded: loaded (/lib/systemd/system/loki.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2022-07-16 04:39:52 UTC; 26s ago Main PID: 174310 (loki-linux-amd6) Tasks: 11 (limit : 19112) Memory: 16.8M CGroup: /system.slice/loki.service └─174310 /usr/local /loki/loki-linux-amd64 -log.level=info -target all -config.file=/usr/local /loki/config/loki-config.yaml $ systemctl status promtail.service ● promtail.service Loaded: loaded (/lib/systemd/system/promtail.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2022-07-16 04:41:50 UTC; 47s ago Main PID: 174401 (promtail-linux-) Tasks: 15 (limit : 19112) Memory: 70.7M CGroup: /system.slice/promtail.service └─174401 /usr/local /loki/promtail-linux-amd64 -config.file=/usr/local /loki/config/promtail.conf Jul 16 04:41:50 devtest-102 systemd[1]: Started promtail.service.
分别访问Loki与Promtail监听服务部署结果验证如下命令与下图:1 2 $ curl http://10.20.176.102:3100/loki/api/v1/labels {"status" :"success" ,"data" :["filename" ,"host" ,"job" ,"unit" ]}
weiyigeek.top-loki-API与Promtail
温馨提示: 在启动Loki后当其日志中出现component=ruler
关键字集群rules时以及在/usr/local/loki/data/loki/rules-temp/fake/
自动生成rules.yaml
表示告警规则已经加载成功。1 2 $ journalctl -u loki.service | grep "component=ruler" Jul 17 08:35:12 devtest-102 loki-linux-amd64[178834]: level=info ts=2022-07-17T08:35:12.851099815Z caller =metrics.go:133 component=ruler org_id=fake latency=fast query="sum by(env,hostname,log_type,filename)((count_over_time({env=~\"\\\\w+\"} |= \"java.lang.OutOfMemoryError\"[5m]) > 0))" query_type=metric range_type=instant length=0s step=0s duration=3.590441ms status=200 limit =0 returned_lines=0 throughput=0B total_bytes=0B total_entries=0 queue_time=0s subqueries=1
Step 6.使用 Grafana 显示 Loki 与 Promtail 采集的日志, 添加 Loki 数据源。
weiyigeek.top-Loki 数据源
Step 7.使用 Explore 显示 Loki 采集的数据,例如 查询的表达式为{filename="/var/log/auth.log"}
, 当然我们也可使用其它标签进行查看对应服务采集到的日志。
weiyigeek.top-Loki 采集的数据展示
Step 8.除了使用Gafana查询Loki之外,它还提供了linux终端的查询客户端logcli
, 下面简单实践一下上面logcli客户端命令的使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 $ logcli labels --addr="http://localhost:3100" http://localhost:3100/loki/api/v1/labels?end=1657983404379212368&start=1657979804379212368 filename host job unit $ logcli labels filename --addr="http://localhost:3100" http://localhost:3100/loki/api/v1/label/filename/values?end=1657983492060973446&start=1657979892060973446 /var/log /auth.log /var/log /bootstrap.log /var/log /cloud-init-output.log /var/log /cloud-init.log /var/log /dmesg /var/log /dpkg.log /var/log /fail2ban.log /var/log /ubuntu-advantage-timer.log /var/log /vmware-network.1.log /var/log /vmware-network.log /var/log /vmware-vmsvc-root.1.log /var/log /vmware-vmsvc-root.2.log /var/log /vmware-vmsvc-root.3.log /var/log /vmware-vmsvc-root.log /var/log /vmware-vmtoolsd-root.log logcli query '{host="10.20.176.102",filename="/var/log/auth.log"}' --limit 100 --batch 5 logcli query '{host="10.20.176.102",filename="/var/log/auth.log"}' --limit =10000 --from="2022-03-12T14:00:05+08:00" --to="2022-03-18T14:30:05+08:00" logcli query '{host="10.20.176.102",filename="/var/log/auth.log"}|="ssh"' --limit =10000 --since=2h --timezone=UTC --output jsonl logcli series '{}' -q --analyze-labels logcli series '{filename="/var/log/auth.log"}' -q
weiyigeek.top-logcli简单使用
以 Helm3 在K8S集群里安装 Loki 与 Promtail 环境说明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ~$ kubectl get node NAME STATUS ROLES AGE VERSION devtest-master-212 Ready control-plane,master 32d v1.23.7 devtest-master-213 Ready control-plane,master 32d v1.23.7 devtest-master-214 Ready control-plane,master 32d v1.23.7 devtest-work-215 Ready work 32d v1.23.7 ~$ helm3 version version.BuildInfo{Version:"v3.9.0" , GitCommit:"7ceeda6c585217a19a1131663d8cd1f7d641b2a7" , GitTreeState:"clean" , GoVersion:"go1.17.5" } ~$ helm3 search repo grafana | egrep "loki|promtail" grafana/loki 2.13.1 v2.6.0 Loki: like Prometheus, but for logs. ...... grafana/promtail 6.2.1 2.6.0 Promtail is an agent which ships the contents o...
安装部署
描述: 以 Helm 部署 Loki (StatefulSet 方式) 和 Promtail(DaemonSet 方式)采集 k8s pod 应用的日志为例
1 2 3 4 5 6 7 8 9 10 helm repo add grafana https://grafana.github.io/helm-charts helm repo update && helm search repo grafana/loki helm search repo -l grafana/promtail helm pull grafana/loki --untar --version 2.13.1 helm pull grafana/promtail --untar --version 6.2.1
loki values.yaml 配置文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 /storage/dev/webapp/logging/loki Chart.yaml README.md templates values.yaml $ grep -E -v "^$|#" values.yaml image: repository: grafana/loki tag: 2.6.0 pullPolicy: IfNotPresent ...... tracing: jaegerAgentHost: config: auth_enabled: false memberlist: join_members: - '{{ include "loki.fullname" . }}-memberlist' ingester: chunk_idle_period: 3m chunk_block_size: 262144 chunk_retain_period: 1m max_transfer_retries: 0 wal: dir: /usr/local /loki/data/loki/wal lifecycler: ring: replication_factor: 1 limits_config: enforce_metric_name: false reject_old_samples: true reject_old_samples_max_age: 168h max_entries_limit_per_query: 5000 schema_config: configs: - from: 2022-07-15 store: boltdb-shipper object_store: filesystem schema: v11 index: prefix: index_ period: 24h server: http_listen_port: 3100 grpc_listen_port: 9095 storage_config: boltdb_shipper: active_index_directory: /usr/local /loki/data/loki/boltdb-shipper-active cache_location: /usr/local /loki/data/loki/boltdb-shipper-cache shared_store: filesystem filesystem: directory: /usr/local /loki/data/loki/chunks chunk_store_config: max_look_back_period: 0s table_manager: retention_deletes_enabled: true retention_period: 4368h compactor: working_directory: /usr/local /loki/data/loki/boltdb-shipper-compactor shared_store: filesystem .... persistence: enabled: true accessModes: - ReadWriteOnce size: 10Gi labels: {} annotations: {} storageClassName: nfs-dev podLabels: app: "loki" rbac: create: true pspEnabled: true resources: limits: cpu: 1 memory: 2Gi requests: cpu: 100m memory: 128Mi serviceMonitor: enabled: true interval: 10s additionalLabels: {} annotations: {} scrapeTimeout: 10s path: /metrics prometheusRule: enabled: false additionalLabels: {} rules: []
温馨提示: Loki 更多配置项解析参考地址 https://grafana.com/docs/loki/latest/configuration。
温馨提示: Storage中bolt-shipper与bolt的区别, Loki2.0版本之后,对于使用boltdb存储索引部分做了较大的重构,采用新的boltdb-shipper模式,可以让Loki的索引存储在S3上,而彻底摆脱Cassandra或者谷歌的BigTable。此后服务的横向扩展将变得更加容易。详见:https://grafana.com/docs/loki/latest/operations/storage/boltdb-shipper/
promtail values.yaml 配置文件: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 /storage/dev/webapp/logging/promtail Chart.yaml ci README.md README.md.gotmpl templates values.yaml daemonset: enabled: true ..... defaultVolumes: - name: run hostPath: path: /run/promtail - name: containers hostPath: path: /var/lib/docker/containers - name: pods hostPath: path: /var/log /pods defaultVolumeMounts: - name: run mountPath: /run/promtail - name: containers mountPath: /var/lib/docker/containers readOnly: true - name: pods mountPath: /var/log /pods readOnly: true extraVolumes: - name: host-time hostPath: path: /etc/localtime extraVolumeMounts: - name: host-time mountPath: /etc/localtime ...... config: logLevel: error serverPort: 3101 clients: - url: http://loki:3100/loki/api/v1/push .....
开始在K8S中部署 Loki 与 Promtail 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 kubectl create ns logging helm install --namespace logging loki loki/ helm install --namespace logging promtail loki/ helm list -n logging $ kubectl get sts,daemonsets.apps,pod,svc -n logging NAME READY AGE statefulset.apps/loki 1/1 4h55m NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/promtail 4 4 4 4 4 <none> 4h45m NAME READY STATUS RESTARTS AGE pod/loki-0 1/1 Running 0 4h55m pod/promtail-75xzp 1/1 Running 0 4h45m pod/promtail-hjttw 1/1 Running 0 4h45m pod/promtail-z9tcn 1/1 Running 0 4h45m pod/promtail-zr4hq 1/1 Running 0 4h45m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/loki ClusterIP 10.102.118.31 <none> 3100/TCP 4h55m service/loki-headless ClusterIP None <none> 3100/TCP 4h55m service/loki-memberlist ClusterIP None <none> 7946/TCP 4h55m root@devtest-master-212:/storage/dev/webapp/logging root@devtest-master-212:/storage/dev/webapp/logging cortex_distributor_ingester_clients 2 cortex_dns_failures_total{name="memberlist" } 0 cortex_dns_lookups_total{name="memberlist" } 0
0x02 实践使用 使用 Grafana 连接到 Loki 数据源 此处Grafana
的安装可以参考Grafana可视化快速入门[https://blog.weiyigeek.top/2019/5-17-39.html] .
此处 Grafana 我也是安装在K8S集群中, 所以我们可以直接采用SVC名称服务(loki.logging.svc:3100
-服务名称.名称空间.svc) 的方式接入Loki。
点击 设置⚙齿轮 -> Data Sources -> Loki -> 在 HTTP 选项下输入 http://loki.logging.svc:3100
-> 在 Maximum lines 最大显示行数为 5000 -> 最后点击 Save & test
, 如出现下图提示则表示连接配置成功。
weiyigeek.top-add Loki Data Sources
点击 Explore -> 选择 Loki (默认其实会选择) -> 在 Log Browser 选择查看指定标签的日志 -> 例如,此处查看 {app="loki"}
标签日志。
weiyigeek.top-Explore Loki日志查看
温馨提示: 在 Grafana 9.0 中,你将在 Explore 中看到一个全新的可视化查询生成器界面,允许任何人编写、编辑和理解一个查询的作用。你已经熟悉的 Explore 界面现在增加了切换字段,可以选择在文本编辑模式(Code)
或可视化生成器模式(Builder)
中编写 PromQL 查询。当你选择 Builder 模式时,一个新的可视化界面允许你通过多词搜索下拉菜单选择感兴趣的指标来制作你的查询。
使用 Grafana Dashboard 显示集群中 pods 日志 描述: grafana dashboard 商城 (https://grafana.com/grafana/dashboards/?plcmt=footer&search=Loki ) 中提供需要关于Loki的Dashboard数据显示面板。
其中 Lok i常用的 Dashboard 如下:
Grafana 添加 Dashboar -> 左边菜单应用 -> +Import -> 在 Import via grafana.com 下输入 15141 -> 点击 Load -> 然后选择我们添加的Loki数据源即可。
最后我们便可查看到如下界面选择查看对应Labels标签的日志:
weiyigeek.top-Loki Kubernetes Logs
扩展: 使用 Grafana Loki 进行日志告警 Loki 支持三种模式创建日志告警:
在 Promtail 中的 pipeline 管道的 metrics 的阶段,根据需求增加一个监控指标,然后使用 Prometheus 结合 Alertmanager 完成监控报警。
通过 Loki 自带的报警功能( Ruler 组件)可以持续查询一个 rules 规则,并将超过阈值的事件推送给 AlertManager 或者其他 Webhook 服务。
将 LogQL 查询转换为 Prometheus 指标。可以通过 Grafana 自带的 Alert rules & notifications
,定义有关 LogQL 指标的报警,推送到 Notification channels( Prometheus Alertmanager , Webhook )
等
以下主要介绍 LogQL 转化为 Prometheus 指标的方式实现告警。
首先,在 Grafana 添加 Prometheus 数据源,URL 只需要填入 http://loki.logging.svc:3100
即可将 LogQL 查询转换为 Prometheus 指标。
然后, 在告警规则配置中配置 Notification channels 。
之后, 新建一个 Dashboard ,配置一个面板,例如:当 nginx 出现 404 状态码,触发告警:
至此,在Kubernetes集群中查看Pod应用日志到此结束。