news 2026/9/29 7:39:38

Grafana Loki 日志删除实操:配置、API 与避坑全解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Grafana Loki 日志删除实操:配置、API 与避坑全解

Grafana Loki 日志删除实操:配置、API 与避坑全解

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

合规要求把敏感信息从日志里抹掉,可分布式日志系统不是删个文件就行。Grafana Loki 的日志删除功能让你通过 compactor 提交请求,保护窗口过后才真正抹除数据。几段 YAML 加几条 curl 命令就能跑通。

什么能删什么不能删:场景与边界

先说清楚什么时候需要删日志:

  • 合规擦除:用户要求删除其个人数据,对应的时间段必须真的消失
  • 测试数据清理:压测流量混进了生产流,要按时间窗口清掉
  • 敏感信息误入库:密码、token 被打进日志,需要尽快消除

Grafana Loki 能删的粒度是日志条目(一行一行)。一个删除请求由三个要素构成:流选择器(如{cluster="prod"})、起止时间窗口、可选的 LogQL 行过滤器(如|= "ERROR")。它做不到的是:不能删掉流本身,不能改动索引的既有结构,更不会实时生效——提交之后有一段保护窗口,窗口内还能反悔。

📌 索引类型有硬约束:

  • TSDB 索引:完整支持,新部署的标准选择
  • BoltDB Shipper:也支持删除,但已废弃并将在 Loki 4.0 移除,别在新环境上选它

删除由 compactor 组件承载,它在整体架构里的位置如下图(单体模式下所有组件跑在同一个 Loki 二进制里):

三步开启删除功能

Loki 日志保留与删除共用同一套底座:删除能力构建在 compactor 的 retention(日志保留,到期自动清数据)工作流之上。开启它只需三步:

  1. 打开 retention 开关
compactor: retention_enabled: true

只有开关打开时,删除 API 端点才会被注册。关闭状态下,无论deletion_mode取什么值,任何租户都访问不了删除接口。命令行等价写法是-compactor.retention-enabled;YAML 键与命令行 flag 一一对应,前缀都是-compactor.,后文不再重复。

  1. 配置删除请求桶delete_request_store:指定一个对象存储桶,用来存放删除请求的数据文件。retention 一旦启用,这一项就是必填——留空时 compactor 启动校验直接失败,进程起不来。

  2. 确认deletion_mode不是disabled:它是limits_config里的全局与按租户设置,默认值filter-and-delete意味着开箱即删。想限制某个租户时,在运行时配置文件中做按租户覆盖即可。

⚠️安全警告:开 retention 要谨慎。强烈建议同时在对象存储上开启版本控制——retention 配置写错时,还能从版本历史把数据捞回来。如果只想要删除能力、不想强制执行日志保留,把retention_period设为0s。

与删除相关的核心配置项如下(定义见 pkg/compactor/config.go):

配置项默认值一句话说明
retention_enabledfalseretention 与删除功能的总开关
delete_request_store空存放删除请求的桶,启用后必填
delete_request_store_key_prefixindex/请求数据在桶内的路径前缀
delete_request_cancel_period24h删除请求的保护窗口(可取消时长)
delete_max_interval24h带行过滤器请求的最大跨度,超出自动拆分
delete_batch_size70每个周期最多处理的删除请求数
retention_delete_delay2hchunk 真正删除前的额外缓冲
retention_delete_worker_count150删除 chunk 的并发工作协程数

一个最小可用配置示例:

limits_config: retention_period: 744h # 不想强制保留就改成 0s deletion_mode: filter-and-delete compactor: working_directory: /var/loki/compactor retention_enabled: true delete_request_store: gcs://bucket_for_delete_requests delete_request_cancel_period: 24h delete_max_interval: 24h

三种删除模式(deletion_mode)怎么选

deletion_mode决定删除请求对查询层和存储层各产生什么效果:

模式查询层行为存储层行为典型场景
disabled照常返回不删除未授权租户;删除 API 直接返回403
filter-only过滤掉匹配行不删除,数据仍在存储里先观察删除范围,或只做逻辑擦除
filter-and-delete过滤掉匹配行从存储中物理移除(默认)合规删除,数据必须真正消失

决策建议:✅ 先用filter-only跑一轮,在查询里确认命中范围符合预期,再切到filter-and-delete落地物理删除;不需要删除能力的租户用disabled锁死。配置拼写错误(比如filteranddelete)会导致请求解析失败,注意连字符。

动手:Loki compactor 删除 API 实操

提交、跟踪、取消三个端点都挂在 compactor 上,且仅在 retention 启用时存在。多租户环境用X-Scope-OrgID请求头指定租户,完整参数见官方 HTTP API 文档。

提交:删除请求的 curl 写法

通过POST /loki/api/v1/delete创建删除请求。参数要点:

  • query(必填):LogQL 流选择器,可带行过滤器,需做 URL 编码
  • start/end(必填):Unix 秒或 RFC3339 两种格式都行;不允许删除未来时间,且start必须小于end
  • max_interval(可选):单个请求允许的最大跨度,不能超过delete_max_interval,合法单位s、m、h

下面这条命令提交一个删除请求,-g参数用于关掉 curl 对花括号的大括号展开:

curl -g -X POST \ 'http://loki-compactor:3100/loki/api/v1/delete?query={cluster="prod"}&start=1704067200&end=1704153600' \ -H 'X-Scope-OrgID: tenant1'

成功返回204 No Content,响应头X-Delete-Request-ID里带着请求 ID,取消时要用。表达式非法(比如正则写错)会在提交时立刻拿到 400,不会拖到执行期才暴露问题。

跟踪:查询删除请求状态

GET /loki/api/v1/delete按创建时间排序返回该租户的全部删除请求,支持两个可选过滤参数:

  • for_querytime_filtering=true:只返回与查询时过滤相关的那部分
  • start+end:只返回与给定时间范围有交集的请求

这条命令列出指定时间范围内的所有删除请求:

curl -X GET \ 'http://loki-compactor:3100/loki/api/v1/delete?start=1704067200&end=1704153600' \ -H 'X-Scope-OrgID: tenant1'

被拆分过的同一请求会以一条记录合并展示,状态字段取Received、Processed或N% Complete三种之一,数字就是已完成子请求的占比。

取消:Loki 删除请求取消方法

DELETE /loki/api/v1/delete?request_id=<ID>用于撤回请求:

  • 取消期(cancellation period,即提交后到真正删除前的保护窗口,由delete_request_cancel_period控制,默认24h)内随时可撤
  • 请求已被处理或已完成时,默认返回 400 拒绝
  • force=true的适用场景:请求已经开始处理,或已超过取消期。注意强制撤回后,已删掉的那部分数据不会恢复,请求状态仍会显示为已处理

带强制参数的取消命令:

curl -X DELETE \ 'http://loki-compactor:3100/loki/api/v1/delete?request_id=<REQUEST_ID>&force=true' \ -H 'X-Scope-OrgID: tenant1'

成功同样返回204。撤掉之后,请求会从存储中移除,GET结果里不再出现。

缓存失效端点

删除之后,查询结果缓存可能还留着旧数据,Loki 用缓存代数(cache generation number,用来判断查询结果缓存是否过期)解决:

  • GET /loki/api/v1/cache/generation_numbers:查看租户当前代数
  • POST /loki/api/v1/cache/generation_numbers/increase:手动递增,让该租户的查询缓存全部失效,回放历史数据这类场景会用到;删除完成后代数会自动递增,无需手动干预

请求在背后经历了什么

提交只是记了一笔账,真正的执行是一条五步流水线:

  1. 周期扫描:compactor 在每个 retention 周期(apply_retention_interval,默认与压缩周期一致,并额外加上不超过 10 分钟的抖动,避免和压缩撞车)扫一遍所有未处理的删除请求
  2. 取消期过滤:只有创建时间已超过delete_request_cancel_period(默认 24h)的请求才进入删除阶段,保护窗口在这里兜底
  3. 批量执行:每个周期最多处理delete_batch_size(默认 70)个请求,防止一个大请求拖死整条队列
  4. chunk 重建写回:filter-and-delete模式下,把相关 chunk 读出来、剔掉匹配行、重建后再传回对象存储并更新索引;这一步之前还有一层retention_delete_delay(默认 2h)缓冲
  5. 缓存失效:处理完成后自动递增缓存代数,后续查询不会再命中已删数据的旧缓存

分片机制只作用于带行过滤器的请求:每个分片最多覆盖delete_max_interval(默认 24h),相邻子请求之间刻意保留少量时间重叠,避免毫秒级边界上的日志漏删;不带行过滤器的请求原样执行,不拆分。

存储层与迁移:删除请求存在哪里

删除请求本身也要持久化,它由两个不同维度的配置共同决定:

  • delete_request_store:对象存储位置,即请求数据文件所在的桶与路径前缀(默认index/)
  • delete_request_store_db_type:本地数据库引擎,默认boltdb,可换成sqlite

想把引擎从 boltdb 迁到 sqlite 时,先给备份库开双写:请求同时落进旧的 boltdb 存储,迁移期间一条都不丢;切换完成后把备份配置去掉。备份库目前只支持 boltdb。迁移期的三行配置:

compactor: delete_request_store_db_type: sqlite backup_delete_request_store_db_type: boltdb

两种引擎的实现分别放在 delete_requests_db_boltdb.go 和 delete_requests_db_sqlite.go,配套测试齐全,想深入细节可以直接读源码。

避坑清单

  • ⚠️对象存储先开版本控制。retention 或保留期一旦配错,版本历史是你唯一能回头的路。
  • ⚠️先 filter-only 试跑再物理删除。在查询层确认命中范围无误,再切filter-and-delete,避免一上来就删错。
  • ⚠️带行过滤器的删除非常吃 CPU 和 IO——读 chunk、剔行、重写、回传,一步不少。批量删大量数据时,按compactor 水平扩展文档把负载摊到多个 compactor 实例上。
  • ⚠️用max_interval控制单请求跨度。别把一个请求跨好几天,执行时间会拖到失控。
  • ⚠️盯住loki_compactor_deletion_*指标。请求积压、删除行数、失败数都在这组指标里,发现异常及时扩容或拆请求。

把retention_enabled、delete_request_store、deletion_mode三件套配齐之后,Grafana Loki 的日志删除就是一个完全可预期的流程:提交请求、享受保护窗口、由 compactor 在后台分片并批量执行、最后在查询层验证干净。真正不可逆的只有物理删除这一步——开版本控制、先 filter-only 试跑、盯紧指标,这三件事做到位,这项能力就可以放心用了。

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

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

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

从设计规范到AI生成:测试用例资产化的关键实践

1. 为什么多数测试用例写着写着就“废”了我见过太多项目组把测试用例当成一个“交付物”来凑&#xff1a;需求评审完了&#xff0c;测试经理排个deadline&#xff0c;测试工程师花两三天把用例铺满Excel&#xff0c;领导一看数量不少&#xff0c;归档。然后呢&#xff1f;开发…

作者头像 李华
网站建设 2026/9/29 7:38:36

Python应用容器化实战:从Dockerfile到Compose编排与排错

最近帮一个做量化策略的哥们儿把他的Python应用容器化&#xff0c;过程比想象中曲折得多。他的脚本在自己电脑上跑得好好的&#xff0c;一到另一台服务器就出问题&#xff1a;先是差点找不到OpenBLAS底层库&#xff0c;后来pandas版本又和服务器上预装的全局Python环境打架&…

作者头像 李华
网站建设 2026/9/29 7:37:13

【Codex智慧中医系统】统一前端模板继承与渲染方式

智慧中医系统接入现成 Web 前端模板时,最容易出问题的不是单个页面,而是静态资源、模板继承块、链接参数和后端数据字段之间没有统一口径,最终表现为样式丢失、跳转失败或页面空白。 读完本文后,可以独立检查 Django 模板体系中的 base 模板、继承页面、链接参数、数据遍历…

作者头像 李华
网站建设 2026/9/29 7:35:41

汽车旋变解码实战:原理、软硬方案与调试全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 7:33:45

从代码规范到设计理念:一份降低认知负担的思维图谱

做软件开发十几年&#xff0c;我越来越确认一件事&#xff1a;代码规范被太多人看小了。很多团队愿意花力气配置格式化工具、接入 lint 插件&#xff0c;但被问一句“这套规范到底在保护什么”的时候&#xff0c;回答多半停在“代码好看”“风格统一”“避免低级错误”。这个答…

作者头像 李华