loki
第一部分组件
loki分为服务端(loki)和客户端日志收集工具(promtail),以及客户端查询工具(grafana),
接下来主要介绍服务端的组件(loki)。
服务端(loki)
loki是使用go语言编写的,编译完成的loki虽然是一个二进制文件,但是服务内各个组件是以微服务形式运行的,包括: Distributor、Ingrestor、Query frontend、Querier、Ruler
第二部分安装部署
loki服务端支持多种安装方式
- 单片模式,即所有微服务组件运行在同一个进程中。适用于每天小于100GB 的小型读/写量。
- 读写分离模式,将Distributor和Ingestro部署在一个进程中(写入相关),将Query frontend、Querier、Ruler部署在一个进程中(查询相关)。适用于每天几百GB的读写量
- 微服务部署,将各个微服务组件分开部署。此方案维护成本较高。
本案例选择读写分离的方式部署:
由于loki各个组件都有相对应的配置参数,需要不断调优。该部署并非最优,需要结合使用情况不断调整
-
部署对象存储minio
kubectl apply -f http://10.4.7.1/minio/deploy.yaml -n loki -
部署loki-read
kubectl apply -f http://10.4.7.1/loki-read/deploy.yaml -n loki -
部署loki-write
kubectl apply -f http://10.4.7.1/loki-write/deploy.yaml -n loki kubectl apply -f http://10.4.7.1/memberlist/deploy.yaml -n loki -
部署gateway
kubectl apply -f http://10.4.7.1/NGINX/deploy.yaml -n loki -
部署客户端(promtail)
kubectl apply -f http://10.4.7.1/promtail/deploy.yaml -n loki -
部署cache,主要缓存查询(可选)
kubectl apply -f http://10.4.7.1/redis/deploy.yaml -n loki -
安装grafana(省略)
-
登录minio 创建名称为loki-data的bucket,用于存储pormtail采集回来的日志对象。
至此已经完成了安装操作,接下来可以在grafana中配置数据源,使用简单的logql可以查询到日志信息
第三部分查询语言
loki使用了一种logQL的查询语言,类似prometheus的promQL 。例如: {app="gateway"}
按照功能可以分为日志查询和指标查询。如图:
日志查询
以这个查询语句展开来分析日志查询的结构
{container="query-frontend",namespace="loki-dev"} |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500
我们把这条复杂的查询拆分开来主要包括两部分:
日志流选择器: {container="query-frontend",namespace="loki-dev"}
日志管道选择器: |= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500
日志流选择器
日志流选择器 格式可以总结为 包含在大括号中的k=v 格式的键值对,并且做到支持正则匹配(这里的正则需要完整匹配,类似^query
可能你匹配不到具体内容)
支持的标签 | 释义 | 举例 |
---|---|---|
= | 保留标签完全相等日志 | {container = "query-frontend} |
!= | 保留标签不相等日志 | {container != "query-frontend} |
=~ | 保留标签正则匹配日志 | {container =~ "^query.*frontend$"} |
!~ | 保留标签正则不匹配日志 | {container !~ "query-frontend"} |
日志管道选择器
介绍完日志流选择器我们看下日志管道选择器。日志管道附加到日志流选择器后,以进一步处理和筛选日志流。例如:
|= "metrics.go" | logfmt | duration > 10s and throughput_mb < 500
日志管道选择器比较灵活,下面主要介绍常用到的一些功能,包括 行过滤表达式、解析表达式
-
行过滤表达式
支持的标签 释义 举例 |= 日志行包含字符串 {job="mysql"} |= "error"
!= 保留标签不相等日日志 {job="mysql"} |= "error" != "timeout"
|~ 保留标签正则匹配日志 ~ ".*go$"
!~ 保留标签正则不匹配日志 !~ ".*go$"
-
解析表达式
日志管道解析可以更加灵活的为日志添加标签,并可以使用新增标签进行进一步的过滤。
json类型支持两种:
-
不带参数的json格式 例如 :
原有日志行: {"a.b": {"c": "d"},"e": "f"} 解析: {source="Name-of-your-source"} | json |a_b_c="d" -
带参数的json 格式 例如:
{source="Name-of-your-source"} | json new="e"| new="f" 原有日志行: ip=1.1.1.1 status=200 duration=30001000 解析: {source="Name-of-your-source"} | logfmt | line_format "{{.ip}} {{.status}} {{div .duration 1000}}"
logfmt
原有日志行: at=info method=GET path=/ host=grafana.net fwd="124.133.124.161" service=8ms status=200 解析: {source="Name-of-your-source"} | logfmt | at="info"
pattern
原有日志行: 0.191.12.2 - - [10/Jun/2021:09:14:29 +0000] "GET /api/plugins/versioncheck HTTP/1.1" 200 2 "-" "Go-http-client/2.0" "13.76.247.102, 34.120.177.193" "TLSv1.2" "US" "" 解析: {source="Name-of-your-source"} | pattern `<ip> - - <_> "<method> <uri> <_>" <status> <size> <_> "<agent>" <_>` | agent=~"^Go.*"
regexp
原有日志行: POST /api/prom/api/v1/query_range (200) 1.5s 解析: {source="Name-of-your-source"}| regexp "(?P<method>\\w+) (?P<path>[\\w|/]+) \\((?P<status>\\d+?)\\) (?P<duration>.*)"
指标查询
指标查询用于计算错误日志的比率或3小时内产生日志的ktop。可以用于生成告警
Loki supports two types of range vector aggregations: log range aggregations and unwrapped range aggregations.
日志范围聚合器
log range aggregations: 通过日志范围生成指标,时间范围可以放在log stream selector 后或者管道结尾
函数 | 含义 | 举例 |
---|---|---|
rate() | 计算每秒日志数量 | rate({container="etcd"}[5m]) |
count_over_time() | 计算指定时间范围内日志数量 | count_over_time({container="etcd"}[5m]) |
bytes_rate() | 计算每秒日志字节数 | bytes_rate({container="etcd"}[5m]) |
bytes_over_time() | 计算指定时间范围内日志字节数 | bytes_over_time({container="etcd"}[5m]) |
absent_over_time() | 如果范围向量有值,返回空。否则返回1 | absent_over_time({container="etcd"}[5m]) |
解包范围聚合器
日后用到补充...
第四部分告警
告警规则在loki的ruler微服务组件中实现,有loki 的ruler微服务组件评估生成告警然后发送给alertmanagery由具体的媒介发出通知
配置告警
-
启用loki告警功能
#catloki-config.yaml ruler: storage: # 支持local,s3等类型 type: local local: # 告警规则放在这个位置,类似于prometheus的rules: [] directory: /tmp/rules # rules临时规则文件存储路径 需要提前创建 rule_path: /tmp/scratch # alertmanager的地址 alertmanager_url: http://10.4.7.250:30093 ring: kvstore: store: inmemory enable_api: true -
定义告警规则
#cat /tmp/rules/fake/rules1.yaml groups: - name: should_fire rules: - alert: HighRequestGateway expr: (rate({app="gateway"}[5m]) > 2) for: 1m labels: severity: warning annotations: summary: High request latency -
重启loki 服务
注意事项:
-
需要提前创建好/tmp/rules/fake 目录并创建告警规则。例如: /tmp/rules/fake/rules1.yaml
这里的fake是loki的用户名称(loki支持多租户,默认租户名称是fake)
-
需要提前创建好/tmp/scratch 目录。例如: mkdir /tmp/scratch
-
-
观察loki日志。(没有找到类似prometheus如何在网页中查看告警状态)
kubectl logs -f loki-read-0 -n loki # 日志中显示已经触发了规则的评估,可以看到该次查询是一个metric类型的查询而不是log类型 level=info ts=2023-01-10T08:32:54.444362252Z caller=metrics.go:133 component=ruler org_id=fake latency=fast query="(rate({app=\"gateway\"}[5m]) > 1)" query_type=metric range_type=instant length=0s step=0s duration=10.488427ms status=200 limit=0 returned_lines=0 throughput=7.2MB total_bytes=76kB total_entries=1 queue_time=0s subqueries=1 -
检查alertmanager
到这里我们基本实现了告警的功能,接下来需要根据业务规则生成我们需要的告警
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏