news 2026/9/12 17:58:39

Loki 2.8 版本深度解读:TSDB 索引转正、查询拦截器(Query Blocker)与 backend 目标

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Loki 2.8 版本深度解读:TSDB 索引转正、查询拦截器(Query Blocker)与 backend 目标

Loki 2.8 版本深度解读:TSDB 索引转正、查询拦截器(Query Blocker)与 backend 目标

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

本篇技术指南围绕 Grafana Loki 2.8 版本发布说明展开,聚焦该版本三大核心变化:TSDB 索引正式脱离实验状态成为推荐索引存储新增 Query Blocker 查询拦截能力(按租户运行时配置拦截高风险查询)以及新增backend目标(配合read/write形成三目标可扩展部署,令 read 目标彻底无状态化)。同时完整梳理 2.8 系列的升级注意事项与各补丁版本的安全修复。读完本文,你将能独立完成 TSDB 索引的迁移配置、通过blocked_queries保护集群免受昂贵查询冲击,并理解简单可扩展部署(Simple Scalable Deployment)中 read/write/backend 三目标的分工与组件归属。

一、版本概览

Loki 2.8 由 Grafana Labs 发布,是 2.x 生命周期中承上启下的一个重要版本。它既承载了此前数个版本积累的 TSDB 索引成熟度(该索引已在 Grafana Cloud Logs 产品中经受大规模生产验证),又为运维侧引入了两项直接影响日常使用体验的能力:按租户粒度的查询拦截,以及更合理的水平扩展目标划分。

除功能增强外,2.8 还包含一批针对依赖链的修复与安全加固,后续发布的 2.8.1 至 2.8.6 六个补丁版本均以升级 Go 版本、更新基础镜像、修复特定缺陷为主,详情可查阅仓库根目录的 CHANGELOG。

二、核心特性一:TSDB 索引不再实验

发布说明的第一条即为 TSDB 索引 "no longer experimental"。在经历 Grafana Cloud Logs 中大量生产环境的验证后,Loki 团队确认新 TSDB 索引已足够稳定,鼓励所有 Loki 部署迁移使用

2.1 什么是单存储 TSDB 索引

Loki 的存储层由"对象存储中的块数据 + 索引"两部分组成。TSDB 索引(Single Store TSDB)将原本 Prometheus 生态的 TSDB 索引格式用于 Loki 的日志索引,索引文件随块数据一同存放在对象存储中,由 ingester 生成、compactor 压缩合并、querier/index gateway 读取。仓库文档 operations/storage/_index.md 明确说明:Single Store TSDB 是Loki 2.8 及更新版本的推荐索引存储,用于替代已进入淘汰流程的 BoltDB Shipper(logs-deletion.md 亦指出 BoltDB Shipper 将在 Loki 4.0 移除,新部署应直接使用 TSDB)。

与旧的 BoltDB Shipper 相比,TSDB 索引带来几个显著优势:

  • 文件系统也可作为对象存储使用:由于索引文件随块数据"托运"到对象存储,querier 在独立进程中也能读取同一份数据,只要所有进程能访问同一目录(见 filesystem.md)。旧 BoltDB 索引一次仅允许一个进程持有数据库文件锁,无法做到这一点。
  • 支持动态分片(dynamic sharding):TSDB 可以按查询负载动态计算分片数量,这也是 2.8 将metrics.go日志中subqueries字段拆分为splitsshards的原因之一(详见第五节)。
  • 日志删除(logs deletion):基于 TSDB 的索引结构可实现精确的日志条目删除。

2.2 TSDB 索引配置示例

仓库 examples/getting-started/loki-config.yaml 给出了一个完整的最小 TSDB 配置:

schema_config: configs: - from: 2023-01-01 store: tsdb object_store: s3 schema: v13 index: prefix: index_ period: 24h

关键字段说明:

  • store: tsdb:指定索引存储类型为 TSDB;
  • object_store: s3:块数据与索引均存放在 S3(也支持 GCS、Azure Blob 等对象存储,以及filesystem);
  • schema: v13:2.8 时代的 schema 版本;
  • index.period: 24h:索引按天切分,配合 compactor 将同一天、同一租户的多个索引文件合并为单个文件,提升查询时的索引查找效率(见 components.md 中 Compactor 一节)。

2.3 TSDB 生态组件

TSDB 索引启用后,集群中与之紧密协作的组件包括:

  • Index Gateway:专门处理元数据查询(如查询日志量、定位 chunk 引用),仅在单存储 TSDB 模式下启用;支持simplering两种运行模式。
  • Compactor:将 ingester 上传的多个索引文件按"天 + 租户"合并为单一索引文件,同时承担日志保留(retention)与日志删除(deletion)职责,通常以单实例运行。
  • Querier / Query Frontend:查询路径上通过 Index Gateway 获取 chunk 引用后再拉取数据。

三、核心特性二:Query Blocker 查询拦截器

在无法控制客户端查询行为的环境中,某些查询可能无意或有意地代价高昂(例如无过滤的大范围聚合),进而影响整个集群的稳定性与成本。2.8 引入的Query Blocker允许在 Querier / Ruler 中通过每租户的运行时配置(runtime configuration file)直接拦截这类查询,且配置变更无需重启进程

3.1 配置方式与完整示例

拦截规则定义在 runtime 配置文件的overrides.<tenant-id>.blocked_queries中。仓库中的权威操作文档 operations/blocking-queries.md 给出了完整示例:

overrides: "tenant-id": blocked_queries: # 精确拦截这一条查询 - pattern: 'sum(rate({env="prod"}[1m]))' # 拦截任何匹配该正则的查询 - pattern: '.*prod.*' regex: true # 拦截所有 metric 类型查询(pattern/regex 省略时默认匹配全部) - types: metric # 仅拦截 filter 与 limited 类型中匹配正则的查询 - pattern: '.*prod.*' regex: true types: filter,limited # 按查询哈希精确拦截(32 位 FNV-1 哈希) - hash: 2943214005 # {stream="stdout",pod="loki-canary-9w49x"} 的哈希 types: filter,limited # 通过 X-Query-Tags 请求头按来源拦截(键值均不区分大小写) - pattern: '.*' # 省略 pattern/regex 时默认分别为 '.*' 与 true regex: true query_tags: source: grafana feature: beta

3.2 规则字段与匹配语义

每条blocked_queries规则支持以下字段:

字段含义说明
pattern查询文本匹配串省略时默认为.*(匹配所有查询)
regex是否将 pattern 视为正则省略时默认为true
types仅拦截指定查询类型可多值,见下
hash查询文本的 32 位 FNV-1 哈希避免长查询字符串的转义麻烦
query_tags仅拦截携带指定X-Query-Tags键值对的请求所有指定键值都必须匹配

三种查询类型(types)定义如下:

  • metric:带聚合函数的查询,如sum(rate({env="prod"}[1m]))
  • filter:带日志过滤器的查询,如{env="prod"} |= "error"
  • limited:既无过滤器也无聚合的查询。

hash字段使用查询字符串的 32 位 FNV-1 哈希(32 位无符号整数)。实际使用中无需自行计算——query-frontend 与 querier 会在每次请求的日志中输出query_hash字段,例如:

level=info ts=2023-03-30T09:08:15.2614555Z caller=metrics.go:152 component=frontend org_id=29 latency=fast query="{stream=\"stdout\",pod=\"loki-canary-9w49x\"}" query_hash=2943214005 query_type=limited range_type=range ...

3.3 源码实现剖析

Query Blocker 的核心逻辑位于 pkg/logql/blocker.go。从源码结构看,其实现要点如下:

  • 规则读取isBlocked方法通过qb.q.limits.BlockedQueries(ctx, tenant)获取当前租户的拦截规则(该接口由 pkg/validation/limits.go 中的Overrides.BlockedQueries实现,从每租户覆盖配置中读取blocked_queries字段,配置声明见同文件 L190)。
  • 匹配优先级:先比较hashb.Hash > 0时精确比对util.HashedQuery(query));否则依次处理 pattern:空 pattern 视为匹配全部、regex: true时编译正则匹配、否则做去除空白的精确字符串比较。
  • 类型与标签双重校验block方法先校验查询类型是否命中types列表,命中后再由tagsMatch校验请求上下文中的X-Query-Tags(通过httpreq.ExtractQueryTagsFromContext提取),要求规则中声明的所有键值对全部匹配才真正拦截。
  • 首个命中即停:注释明确写道 "The order of patterns is preserved, so the first matching pattern will be used"——规则的顺序被保留,Loki 在第一条 pattern 或 hash 命中的规则处停止。若该规则的typesquery_tags约束不满足,则查询不会被拦截,且不再继续检查后续规则(即使后续规则本可拦截)。因此文档建议:多条规则共享同一 pattern 时,应合并约束到单条规则,而非依赖后面的规则兜底。
  • 并发安全:对共享配置对象采用局部副本处理,使isBlocked可被并发安全调用。

3.4 观测拦截结果

被拦截的查询会记录到日志,并累计到按租户统计的loki_blocked_queries指标。当 pattern/hash/regex 命中时,日志会输出类型与标签是否匹配:

level=warn msg="query blocker matched with regex policy" user=29 type=metric pattern=".*rate\\(.*\\).*" query="sum(rate({app=\"foo\"}[5m]))" typesMatched=true tagsMatched=false blocked=false

标签约束未命中时输出 debug 级日志,指明缺失的键与收到的原始头:

level=debug msg="query blocker tags mismatch: missing or mismatched key" key=feature tagsRaw="Source=grafana,Feature=alpha"

3.5 拦截范围与限制

Query Blocker 由 LogQL 查询引擎在求值阶段强制执行,覆盖:

  • /loki/api/v1/query(即时查询)与/loki/api/v1/query_range(范围查询)API;
  • 告警与记录规则(Alerting / Recording Rules),本地与远程评估模式均覆盖——远程评估模式下规则查询会经 query-frontend 与 querier 回传,与普通 API 查询同等拦截。

不适用的场景包括:

  • 日志 tail(/loki/api/v1/tail端点):tail 直接读取 ingester 与存储,不经过查询引擎;
  • 元数据端点:如labelsseriesindex/statsindex/volumedetected_fields等,不执行 LogQL 表达式,无对象可供匹配。

此外仓库文档特别警告:实验性的下一代查询引擎(query_engine.enable: true,面向 dataobj/columnar 存储的查询)完全不检查blocked_queries策略,这是一项已知限制而非延迟检查,拦截策略对其静默失效。

3.6 基于 X-Query-Tags 的定向拦截

除按查询文本拦截外,还可将规则限定到携带特定X-Query-Tags请求头的请求:

  • 头格式:逗号分隔的key=value对,例如Source=grafana,Feature=beta
  • 允许字符为字母数字加空格、逗号、等号、@.-,其他字符替换为_;仅保留规范的key=value标记,畸形标记被忽略;
  • 匹配规则:键与值均不区分大小写(服务端将键转为小写),规则中声明的所有query_tags键值对必须全部出现在请求中才生效。

一个典型场景是仅拦截来自测试特性开关的查询:

overrides: tenant-a: blocked_queries: - types: metric query_tags: feature: beta - pattern: '.*rate\\(.*\\).*' regex: true query_tags: source: grafana

Ruler 查询标签:当 ruler 以远程评估模式(-ruler.evaluation.mode=remote)运行时,会自动在查询上附带source=ruler,rule_name=<rule name>,rule_type=<rule type>标签,因此可以针对规则评估定向配置策略,例如拦截所有来自规则评估的查询:

overrides: "tenant-id": blocked_queries: - query_tags: source: ruler

注意:本地评估模式下 ruler 不设置X-Query-Tags,无法按此匹配;且规则名若含逗号或等号会被标签解析截断或丢弃,匹配rule_name时需谨慎。

四、核心特性三:新增backend目标

2.8 为 Loki 的scalable 配置(即 Loki helm chart 的默认部署方式,Simple Scalable Deployment / SSD)新增了第三个目标backend。至此 Loki 可以按readwritebackend三个目标分组运行,read目标因此变为无状态,可作为 Kubernetes Deployment 运行并自动水平扩缩容。

4.1 三目标模式下的组件归属

仓库文档 get-started/components.md 以表格形式明确了各组件在三目标模式下的归属(x表示该目标包含此组件):

组件allreadwritebackend
Distributorxx
Ingesterxx
Query Frontendxx
Query Schedulerxx
Querierxx
Index Gatewayxx
Compactorxx
Rulerxx
Pattern Ingesterxx
Bloom Planner / Builder / Gateway(实验性)xx

可以看到:

  • read:由 Query Frontend 与 Querier 组成,两者均为无状态组件,天然适合 Kubernetes Deployment + HPA 自动扩缩;
  • write:由 Distributor、Ingester、Pattern Ingester 组成,ingester 依赖 WAL 与对象存储保持有状态;
  • backend:收纳 Query Scheduler、Index Gateway、Compactor、Ruler 等"既不参与写入、也不直接处理用户查询"的组件,通常以 StatefulSet 或固定副本数部署。

4.2 目标机制与配置示例

Loki 的单二进制内聚了所有微服务组件,通过-target命令行参数(或target配置项)指定启动哪些模块。从 pkg/loki/loki.go 的源码可见,target默认值为all(单二进制模式),并支持-list-targets标志打印全部可用目标。

仓库 examples/getting-started/loki-config.yaml 展示了一个三目标部署共享的配置骨架:

memberlist: join_members: ["read", "write", "backend"] dead_node_reclaim_time: 30s gossip_to_dead_nodes_time: 15s left_ingesters_timeout: 30s bind_addr: ['0.0.0.0'] bind_port: 7946 gossip_interval: 2s common: path_prefix: /loki replication_factor: 1 compactor_address: http://backend:3100 storage: s3: endpoint: minio:9000 insecure: true bucketnames: loki-data access_key_id: loki secret_access_key: supersecret s3forcepathstyle: true ring: kvstore: store: memberlist

要点解读:

  • memberlist.join_members列出 read/write/backend 三个目标的服务名,使所有实例通过 memberlist 协议共享集群状态;
  • common.compactor_address指向 backend 目标的 compactor 地址,供需要对接 compactor 的组件(如查询删除相关流程)使用;
  • common.ring.kvstore.store: memberlist让所有内部 ring(ingester、distributor 等)共用 memberlist 集群。

运维上,三个目标各部署一个 Kubernetes Service(分别暴露端口供对应的客户端/组件访问),readwrite可按需横向扩容,backend保持较小规模即可。

4.3 与部署模式的衔接

从 get-started/deployment-modes.md 看,当前仓库的部署模式体系已演化为三种:Monolithic(单二进制,-target=allHA Monolithic(高可用单二进制)Microservices(微服务)。其中 HA Monolithic 模式已取代旧 SSD(Simple Scalable Deployment)成为推荐的折中方案,但 2.8 引入的backend目标仍是理解 SSD / helm chart 默认部署形态的关键:它将原本挤在read中的无状态查询组件与有状态/后台组件分离,为 read 路径的弹性伸缩扫清了障碍。

五、升级注意事项(2.8.0)

原发布说明强调升级前务必阅读 upgrade guide。结合仓库升级文档,2.8.0 的关键变更整理如下:

5.1retention_period默认值改为 0s

这是最具破坏性的一项变更。此前compactor.retention_enabled: true且未在limits_config中定义retention_period时,默认保留 744h(31 天);2.8 起默认改为0s,语义为"永久保留 / 禁用保留"。

注意:旧版本中00s会触发立即删除全部日志仅在 2.8 及之后的版本,零值才表示禁用保留。若希望维持旧行为,需显式配置:

limits_config: retention_period: 744h

5.2 LogQL 重复标签行为变化

当日志行中出现重复标签时,Loki 2.8 改为只保留第一个值,此前保留的是最后一个值。使用重复标签的查询结果可能因此变化。

5.3metrics.go日志字段:subqueries拆分为splitsshards

旧版metrics.go每行日志中的subqueries仅反映按时间拆分产生的子查询数,未包含分片数。2.8 起不再输出subqueries(统计 API 中为向后兼容仍返回该字段,但恒为 0),改为:

  • splits:按时间间隔拆分产生的查询段数量;
  • shards:为查询创建的总分片数(值为 0 通常表示该查询无法分片)。

这尤其适用于 TSDB 的动态分片能力,便于区分"时间拆分"与"分片"两种并行化来源。同时 2.8 在metrics.go中新增了 Store 与 Cache 统计:记录从存储下载 chunk、以及从缓存下载 chunk / 索引查询结果 / 结果缓存所耗费的时间(*_download_time字段),这些统计也可通过 LogCLI 的--stats标志查看。

5.4 Promtail:promtail_journal_enabled构建标签

Promtail 引入 Go 构建标签promtail_journal_enabled,只有传入该标签才启用 Journal 支持:

go build --tags=promtail_journal_enabled ./clients/cmd/promtail

此举旨在让无需 Journal 支持的 Linux/CentOS 用户(CGO 启用时)免于安装libsystemd-dev/systemd-devel依赖。

5.5 Ruler:ruler.wal-cleaer.period废弃

CLI 标志ruler.wal-cleaer.period拼写有误,2.8 废弃并以修正后的ruler.wal-cleaner.period取代;YAML 配置不变:

ruler: wal_cleaner: period: 5s

5.6 Querier:query-frontend Kubernetes 服务类型调整

此项仅影响使用 jsonnet 部署 Loki 到 Kubernetes 的用户。原query-frontendheadless 服务被拆分为两个服务:query-frontend改为负载均衡服务(公平分发查询请求),新增query-frontend-headless供 querier 发现前端 Pod IP 建立 worker 连接。使用 Query Scheduler(query_scheduler_enabled: true)的部署无需处理;未使用 Scheduler 时建议按"先建 headless 服务 → 滚动更新 querier → 再应用其余变更"的顺序灰度。

六、补丁版本与安全修复

2.8 系列共发布 2.8.1 至 2.8.6 六个补丁,主要内容为安全加固与缺陷修复(完整清单见仓库根目录 CHANGELOG):

版本日期要点
2.8.62023-10-17升级 Go 至 v1.20.10、golang.org/x/net 至 v0.17.0、grpc-go 至 v1.56.3,修复 CVE-2023-39325 / CVE-2023-44487
2.8.52023-09-14更新 Docker 基础镜像,缓解安全漏洞 CVE-2022-48174
2.8.22023-05-03升级 Go 至 1.20.4 修复安全漏洞;Promtail 新增decompression配置以自定义解压器行为
2.8.12023-04-21修复索引周期为零值时索引被丢弃的问题;修复 redis 客户端在本地地址下错误选择集群模式的问题;升级 Go 至 1.20.3;alpine 镜像更新至 3.16.5;修复 Promtail 在 amd64 二进制构建中的 journald 支持

这些补丁提醒生产用户:若运行 2.8 早期版本,应至少升级至 2.8.6,以规避 Go 依赖链与基础镜像层的历史 CVE。

七、总结

Loki 2.8 是 2.x 系列中"转正与治理"并重的一个版本:TSDB 索引经生产验证后成为官方推荐索引方案(配合 schema v13 与 compactor/index gateway 组件使用);Query Blocker 借助每租户运行时配置,为集群提供了按文本、哈希、类型、请求来源多维度的查询治理手段;backend目标的加入则完善了三目标可扩展部署的组件划分,让 read 路径可以无状态弹性伸缩。升级侧最需要留意的是retention_period默认值变更与 LogQL 重复标签语义调整。对于 2.7 及更早版本的用户,建议结合升级指南与本文第六节,制定"配置核对 → 灰度升级 → 安全补丁到位"的完整升级路径。

【免费下载链接】lokiLike Prometheus, but for logs.项目地址: https://gitcode.com/GitHub_Trending/lok/loki

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 17:58:31

多模数据质量问题的检测规则

文章目录每日一句正能量1. 背景与问题2. 环境与数据2.1 文档表2.2 知识块和向量表2.3 时序表2.4 规则和问题表3. 复现过程3.1 文档已发布但没有有效知识块3.2 文档和向量内容不一致3.3 向量模型和维度不一致3.4 孤儿向量3.5 跨租户关联错误3.6 时序数据时间倒退和缺口3.7 JSONB…

作者头像 李华
网站建设 2026/9/12 17:57:38

用 open_clip 做以文搜图:零样本分类与多模态检索入门

用 open_clip 做以文搜图&#xff1a;零样本分类与多模态检索入门 【免费下载链接】open_clip An open source implementation of CLIP. 项目地址: https://gitcode.com/GitHub_Trending/op/open_clip 想按一句话描述从几万张图里捞出目标&#xff0c;但不想标注数据、更…

作者头像 李华
网站建设 2026/9/12 17:54:45

济宁壁挂炉上门维修 本地靠谱师傅 不点火、故障码、漏水维修

济宁壁挂炉上门维修 本地靠谱师傅 不点火、故障码、漏水维修家里壁挂炉突发故障&#xff1f;不点火、无热水、采暖不热、屏幕跳故障码、漏水异响、水压异常&#xff0c;不用盲目找维修。壁挂炉集成燃气、水路、电控、采暖多套系统&#xff0c;维修需精准检测故障根源&#xff0…

作者头像 李华
网站建设 2026/9/12 17:54:35

LeetCode hot100——189.轮转数组

题目给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。示例 1:输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,…

作者头像 李华
网站建设 2026/9/12 17:54:02

合成数据vs真实网页数据:大模型训练的博弈

摘要&#xff1a; 深入剖析合成数据与真实网页数据在大模型训练中的根本性博弈。本文从模型崩溃的底层机制出发&#xff0c;结合真实世界的商业案例与代码实践&#xff0c;论证为什么真实网页数据在新鲜度、多样性和事实锚定三个维度上不可替代&#xff0c;并探讨如何使用AntsD…

作者头像 李华
网站建设 2026/9/12 17:54:02

ToF相机全链路解析:从硬件物理层到ROS应用的深度系统工程

1. ToF 相机从底层硬件到上层应用整体链路&#xff1a;这不是一个“相机”&#xff0c;而是一套精密协同的感知系统 你手头那台标着“ToF”字样的模组&#xff0c;或者调试时在V4L2设备列表里看到的 /dev/video0 &#xff0c;从来就不是一块简单的图像传感器。它是一条横跨物…

作者头像 李华