Grafana Loki 轻量级日志系统小记
优采云 发布时间: 2022-04-29 14:18Grafana Loki 轻量级日志系统小记
前言
最近几个月,广告团队一直在 Web 模块化、服务化的方向进行探寻。在这一背景下,我们对现有系统的模块进行了划分,(在一定程度上)理清了模块间的边界与关系,并采用“服务化架构”的对 37 网游 UAD 广告后台进行了重构,落地了“开天辟地、继往开来”的“盘古”系统。
”盘古“一期的开发涉及到3个微服务,意味着我在本地开发的过程中如果需要涉及到整个链路的调整/验证的话,至少需要跑起来 3 个站点,以前简单的单文件日志查找也变得繁琐了起来。转念一想,我们的服务日志无论是在本地开发环境、测试环境还是在生产环境都已经对输出字段做了标准化处理,并且采用 JSON 格式输出,那么能否在本地搭建一套类似 ELK 的日志系统用于统一收集、检索我们的日志呢?想法自然是没有问题的,但是对于本地开发机配置不高、又需要多开 IDE、浏览器的我而言,要跑起来 ElasticSearch 这个极耗内存的”庞然大物“似乎不太现实,几经查找,终于寻得一套极具性价比的日志系统解决方案 Grafana Loki,很好的解决了我在本地开发环境下日志查询效率低下的问题。
对于经常关注业界新闻的小伙伴应该对 Loki 不陌生,它是我们数据部看板所采用的工具 Grafana 的官方团队最新的开源项目之一。下面我就站在一个小白的角度,与大家浅谈一下 Loki 是什么,它与我们熟悉的 ELK 方案(如运维平台的海纳日志系统)相比有什么优缺点以及怎么部署、接入与检索吧。
简介
Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。与其他日志系统不同,Loki 的构想是仅对日志建立标签索引,而使原始日志消息保持未索引状态。这意味着 Loki 的运营成本更低,并且效率更高。
Loki 具有下面的一些特性与 ELK 相比部署
基于 Loki 的日志系统想要在本地开发机跑起来,需要这 3 大模块:Promtai、Loki、Grafana。其中 Promtail 的功能与 ELK 他们家的 Filebeat 功能相似,用于采集日志文件使其转换为流;Loki 则是日志系统中负责收集、存储、检索的模块;而 Grafana 自然是日志内容的呈现以及检索入口。这三者之间的关系如图所示:
为了在本地实现简单快捷的部署,我直接采用了官方的 docker 镜像,shell 命令参考如下:
## 部署 promtaildocker run --name promtail -d -v /Users/rytia/Software/dev/Loki:/mnt/config -v /Users/rytia/37Code/uad-quantum/logs:/uad-quantum/logs grafana/promtail:2.3.0 -config.file=/mnt/config/promtail-config.yaml ## 部署 lokidocker run -v /Users/rytia/Software/dev/Loki:/mnt/config -v /Users/rytia/37Code/uad-quantum/logs:/uad-quantum/logs -d --name loki -p 3100:3100 grafana/loki:2.3.0 -config.file=/mnt/config/loki-config.yaml ## 部署 grafanadocker run -d --name grafana -p 3000:3000 \ -e GF_INSTALL_PLUGINS="grafana-clock-panel:1.1.0,grafana-kubernetes-app,worldpring=https://github.com/raintank/worldping-app/releases/download/v1.2.6/worldping-app-release-1.2.6.zip" \ bitnami/grafana:latest
其中:
接入
在接入前,请保证你的程序已经使用 JSON 格式打日志了,格式要求与运维平台的海纳日志系统一致,如图所示:
一、Promtail 部分
# cat /Users/rytia/Software/dev/Loki/promtail-config.yaml server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: http://172.17.0.1:3100/loki/api/v1/push scrape_configs:- job_name: uad-quantum static_configs: - targets: - localhost labels: # 自定义标签(job是一个自定义标签,比较好的是环境名称、应用名称或者微服务标识 job: ad-logs # 配置要将什么位置的日志发送到Loki __path__: /uad-quantum/logs/* pipeline_stages: - match: selector: '{job="ad-logs"}' stages: - json: expressions: level: level_name - labels: level: level
二、Loki 部分
# cat /Users/rytia/Software/dev/Loki/loki-config.yaml auth_enabled: false server: http_listen_port: 3100 grpc_listen_port: 9096 ingester: wal: enabled: true dir: /tmp/wal lifecycler: address: 127.0.0.1 ring: kvstore: store: inmemory replication_factor: 1 final_sleep: 0s chunk_idle_period: 1h # Any chunk not receiving new logs in this time will be flushed max_chunk_age: 1h # All chunks will be flushed when they hit this age, default is 1h chunk_target_size: 1048576 # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached first chunk_retain_period: 30s # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m) max_transfer_retries: 0 # Chunk transfers disabled schema_config: configs: - from: 2020-10-24 store: boltdb-shipper object_store: filesystem schema: v11 index: prefix: index_ period: 24h storage_config: boltdb_shipper: active_index_directory: /tmp/loki/boltdb-shipper-active cache_location: /tmp/loki/boltdb-shipper-cache cache_ttl: 24h # Can be increased for faster performance over longer query periods, uses more disk space shared_store: filesystem filesystem: directory: /tmp/loki/chunks compactor: working_directory: /tmp/loki/boltdb-shipper-compactor shared_store: filesystem limits_config: reject_old_samples: true reject_old_samples_max_age: 168h chunk_store_config: max_look_back_period: 0s table_manager: retention_deletes_enabled: false retention_period: 0s ruler: storage: type: local local: directory: /tmp/loki/rules rule_path: /tmp/loki/rules-temp alertmanager_url: http://localhost:9093 ring: kvstore: store: inmemory enable_api: true
三、Grafana 部分
2.新增面板
与其他我们所熟悉的数据源一致,新增面板(或者从官方市场导入面板也可以)
新增 Panel,数据源选择 Loki,根据自己所需要的图形、表格进行可视化的调整即可。(如有特殊需求,具体查询语法见下文)
3.整体效果
本人的本地开发环境接入“盘古”微服务的日志后,效果如图
在这里附带一下官方面板市场中大牛们采用 Loki 做出来的面板效果图供大家参考,我们常用的几大数据呈现形式基本都能通过 Loki 实现:
检索
官方文档:LogQL | Grafana Labs()
与 ElasticSearch 之于 lucene query 相似,Loki 也有自己的查询语言 LogQL。基本的 LogQL 查询由两部分组成:日志流选择器(Log Stream Selector)、搜索表达式(Filter Expression)
日志流选择器(Log Stream Selector)
它由一个或多个键值对组成,每个键是一个日志标签,值的话是标签的值,例如:
{job="ad-logs",level="warning"}
在这个例子中,记录具有的标签job,其值是采集时所赋予的ad-logs;另一个标签level来源于采集时对 JSON 格式日志文件的解析。适用于Prometheus标签选择器的相同规则也适用 于Loki日志流选择器
搜索表达式(Filter Expression)
在使用日志流选择器(Log Stream Selector)进行初步的筛选之后,可以使用搜索表达式(Filter Expression)进一步过滤生成的日志集
搜索表达式可以只是文本或正则表达式,举个简单的例子如下:
{job=“mysql”} |= “error”<br />{name=“kafka”} |~ “tsdb-ops.*io:2003”<br />{instance=~“kafka-[23]”,name=“kafka”} !=<br />kafka.server:type=ReplicaManager<br /><br />|=:日志行包含字符串。<br />!=:日志行不包含字符串。<br />|~:日志行匹配正则表达式。<br />!~:日志行与正则表达式不匹配。
此外,与 Prometheus 的 PromQL 一样,LogQL 支持内置聚合运算符如max()、avg()等。
后记
行文至此,已经深夜 2:19。本文所述为自己经历所沉淀,只是粗浅的介绍了一下 Loki 以及基于 docker 且使用文件进行持久化的一种部署方式,并没有对 Loki 本身的模块设计以及实现方式展开过多讨论。回到“盘古”的项目开发本身,Loki 在我不需要修改一行程序代码的前提下,用极低的机器资源占用将我的日志做了统一收集,并且无缝接入了我们熟悉的Grafana面板,提高了我在本地环境排查问题的效率。希望能给目前尚不了解 Loki 或者同样有本地开发微服务需求的小伙伴开拓一下视野。
同时由于本人才学疏浅,文章难免会出现疏漏的地方,还请各位前辈不吝赐教。