☰
Grafana Loki 日志删除实操:从提交请求到数据真正被删掉
2026/9/29 8:28:20 网站建设 项目流程

Grafana Loki 日志删除实操:从提交请求到数据真正被删掉

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

想象一下这样的场景:某租户把包含支付卡号的日志写进了 Loki,合规要求必须在 72 小时内把这些行从存储里清掉。Grafana Loki 的日志条目删除(Log Entry Deletion)就是为此设计的——你提交一个带流选择器、时间窗口、可选行过滤器的删除请求,等取消期过后,数据才真正从对象存储里消失。下面按"先跑通、再会查、最后敢删"的顺序讲清楚。

🧭 30 秒心智模型:删除是"先记账、再执行"的两段式操作

  • 删除是异步任务,不是同步动作。提交请求只产生一条持久化的"删除记录",真正的数据移除由 compactor 周期性执行,中间隔着两段缓冲时间(见后文)。
  • 取消期就是你提交后的"后悔窗口"。在delete_request_cancel_period(默认24h)内,请求随时可以撤销;超过窗口就基本不可逆了。
  • 删除记录本身会被持久化,所以即使是"只过滤不删"的模式,查询路径也会按它实时过滤结果——提交即对查询生效。
  • 三种模式决定最终行为:disabled(禁止删除,API 拒绝)、filter-only(只过滤不删)、filter-and-delete(过滤并从存储移除,默认值)。
  • 执行者只有一个角色:compactor。微服务模式里它是独立组件,负责 retention 与删除的整套工作:

一句话总结:API 负责登记,compactor 负责执行,取消期是你的反悔时间。

🚀 上手路径:三处配置 + 一次成功调用

这节解决"最小要改哪些东西才能跑起来"的问题。删除能力同时依赖三个开关,缺一不可:

  1. compactor 侧retention_enabled: true——删除 API 端点只在这个开关为true时才注册,否则所有请求直接返回400 Retention is not enabled;
  2. compactor 侧delete_request_store必填——否则启动校验直接失败,报错compactor.delete-request-store should be configured when retention is enabled(见 pkg/compactor/config.go 的Validate());
  3. 租户的deletion_mode不是disabled——它是limits_config中的全局加按租户设置,默认filter-and-delete,所以满足前两条后所有租户开箱可用,也可在运行时配置文件中按租户覆盖。

最小可用配置(注释说明每行"为什么"):

limits_config: retention_period: 0s # 只要删除能力、不强制按保留期清理,就设为 0s deletion_mode: filter-and-delete # 全局默认;想先观察命中范围可先改 filter-only compactor: working_directory: /var/loki/compactor retention_enabled: true # 不开这个,删除端点根本不存在 delete_request_store: gcs://bucket_for_delete_requests # 删除记录的存放位置,按你的对象存储类型改 delete_request_store_db_type: boltdb # 本地请求数据库引擎,默认 boltdb,可换 sqlite delete_request_cancel_period: 24h # 后悔窗口,源码注释建议至少 24h delete_max_interval: 24h # 带行过滤器的单个分片最大跨度

配置生效后,提交一条删除请求做冒烟验证:

curl -i -X POST -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?query=%7Bcluster%3D%22prod%22%7D&start=1704067200&end=1704153600"

参数逐个说:

  • query:LogQL 流选择器,如{cluster="prod"},可追加行过滤器(|= "ERROR")。表达式会在提交时就解析校验,regex 写错、ip()模式非法等直接400,不会拖到执行期才炸。
  • start/end:起始与结束时间,Unix 秒(必须是 10 位)或 RFC3339 格式。两个硬校验:end不能指向未来(deletes in the future are not allowed),start必须严格小于end(start time can't be greater than or equal to end time)。
  • 多租户用X-Scope-OrgID头标识,请求按租户隔离。

成功的样子:204 No Content,响应头X-Delete-Request-ID里就是删除请求 ID,请收好,后续查询和取消都靠它。失败的样子:各种400加上明确的错误文案(query not set、start time not set、invalid start time: require unix seconds or RFC3339 format等),全部在提交阶段拦截,不会产生半成品请求。

📋 操作手册:提交 → 查询 → 取消

这节把日常会用到的端点按动作流串起来,每条都给出命令、关键参数和成败判据。

提交:带行过滤器时记得控制分片大小

curl -i -X POST -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?query=%7Bcluster%3D%22prod%22%7D%20%7C%3D%20%22ERROR%22&start=1704067200&end=1704681600&max_interval=12h"

max_interval是唯一的可选参数,语义是"单个子请求最多覆盖多长":

约束触发的错误
最小1s,单位仅s、m、hinvalid max_interval: valid time units are 's', 'm', 'h'
不能超过delete_max_intervalmax_interval can't be greater than 24h0m0s
不能超过本次要删的窗口本身max_interval can't be greater than the interval to be deleted (...)

查询:看状态、看进度

curl -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete"

返回该租户的删除请求 JSON 数组,按创建时间升序。两个可选参数:

  • for_querytime_filtering=true:只返回与查询时过滤相关的请求;
  • start+end:时间重叠过滤,只返回与给定区间有交集的请求。

被拆分过的同一请求的多个子请求会被合并成一条展示,状态按完成比例呈现:Received(未开始)、N% Complete(部分完成)、Processed(全部完成)。验证生效最直接的方式就是轮询这个接口,等状态从Received走到Processed;若是filter-only模式,还可以直接对查询做回归,确认匹配行已不可见。

取消:窗口内随便撤,窗口外要 force

curl -i -X PUT -H "X-Scope-OrgID: tenant1" \ "http://loki-compactor:3100/loki/api/v1/delete?request_id=<REQUEST_ID>"

成败判据一览:

场景响应
取消成功204 No Content
ID 不存在404 could not find delete request with given id
请求已在处理中或已完成(Processed)400 deletion of request which is in process or already processed is not allowed
已超过取消期400 Cancellation of partially completed delete request or delete request past the deadline of 24h0m0s since its creation is not allowed. To force, use the ?force query parameter

最后这种想强行撤销,追加&force=true即可:

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

辅助:手动使查询缓存失效

删除完成后缓存代数会自动更新,保证查询不会命中已删数据的缓存。但如果是回放历史数据等其他场景导致查询结果不一致,可以手动递增某租户的缓存代数:GET /loki/api/v1/cache_generation_number查看,POST同一端点递增(成功返回204),该租户的查询结果缓存随即失效。

⚙️ 原理与边界:只讲影响你决策的部分

这节不展开源码,只回答"什么情况下这些机制会咬到你"。

什么时候数据才真正消失

提交请求 ≠ 删除发生。时序是:取消期(delete_request_cancel_period,默认24h)→ compactor 在每个 retention 周期扫描未处理且已过取消期的请求 → 每周期最多处理delete_batch_size(默认70)个 → chunk 重建并写回对象存储。apply_retention_interval设为0时与 compaction 周期(默认10m)一致,并自动加上最多10m(不超过其一半)的抖动避免撞车。filter-and-delete模式下,涉及删除的 chunk 需要读出来、剔除匹配行、重写再写回,这是 CPU 与 IO 最重的操作;需要大批量、多租户删带过滤器的数据时,考虑横向扩展 compactor,把删除工作分到多个实例。

什么时候分片机制会影响你

只有带行过滤器的请求会被拆分:超过delete_max_interval(默认24h)的窗口会被切成多个不超过该跨度的子请求;不带行过滤器的请求永远不拆。分片之间刻意保留少量时间重叠而非精确衔接,避免边界 1ms 的缝隙漏删。你要关心的只是:删除窗口很长且带行过滤器时,用max_interval把单片压小,避免单个请求执行时间过长。

什么时候会碰到请求存储迁移

删除记录存两份维度:delete_request_store是对象存储位置(放数据文件),delete_request_store_db_type是本地数据库引擎(boltdb默认,或sqlite)。从一种引擎迁到另一种时,设backup_delete_request_store_db_type: boltdb让请求双写备份库,迁移期间不丢请求——当前备份库仅支持 boltdb。索引存储侧的约束:TSDB 索引完整支持删除;BoltDB Shipper 索引虽也支持,但将在 Loki 4.0 移除,新部署直接用 TSDB。

🚧 避坑清单

⚠️启用 retention 前,先在对象存储上开启版本控制。retention 配错会连带删数据,没有版本控制就没有回滚。对策:开启 versioning 是启用retention_enabled: true的前置动作,不是可选项;只想用删除能力、不想强制保留期,把retention_period设0s。

⚠️filter-only是免费的试错通道。先切到filter-only提交同样的请求,用查询验证实际命中范围,确认无误再改回filter-and-delete落地物理删除。对策:同一请求在两种模式下都会持久化,观察期不丢数据。

⚠️取消窗口过后就没有第二次机会了。默认24h,且已进入处理中的请求默认不可取消(force=true也只能用于部分完成的请求)。对策:把delete_request_cancel_period按合规节奏调长;提交后立刻用 GET 接口核对流、时间窗口、行过滤器三要素再等待。

⚠️deletion_mode拼错不会静默降级,而是直接报错。未知值返回unknown deletion mode: must be one of disabled|filter-only|filter-and-delete,请求校验阶段就失败。对策:上线前用一次400请求冒烟,或检查运行时配置里租户覆盖值的拼写。

⚠️带行过滤器的删除是 compactor 上最重的活之一。每个相关 chunk 都要读出、剔除、重写、回传,积压会拖慢整个 retention 周期。对策:监控loki_compactor_deletion_*指标(选中 chunk 数、已删行数、已处理请求数、失败数),观察积压与失败;需要时按官方横向扩展方案把 compactor 扩成多实例分摊删除负载。

🔍 快速参考

配置项 / 端点默认值作用
compactor.retention_enabledfalse总开关;true才注册删除端点
compactor.delete_request_store空(启用 retention 时必填)删除记录的对象存储位置
compactor.delete_request_store_key_prefixindex/记录在桶中的路径前缀
compactor.delete_request_store_db_typeboltdb本地请求数据库引擎(boltdb/sqlite)
compactor.delete_request_cancel_period24h后悔窗口,过后才执行删除
compactor.delete_max_interval24h带行过滤器请求的单分片最大跨度
compactor.delete_batch_size70每 retention 周期最多处理的请求数
compactor.retention_delete_delay2hchunk 真正被删除前的额外缓冲
compactor.retention_delete_worker_count150删除 chunk 的工作协程数
limits_config.deletion_modefilter-and-delete全局/按租户模式,disabled时端点返回403语义的拒绝
POST /loki/api/v1/delete—提交删除请求,204+X-Delete-Request-ID
GET /loki/api/v1/delete—列出请求,支持for_querytime_filtering、start/end
PUT /loki/api/v1/delete?request_id=...—取消请求,超期需force=true,204成功

删除能力 =retention_enabled+delete_request_store+ 非disabled的deletion_mode,三要素齐备即对租户生效。记住两段缓冲——取消期与retention_delete_delay——就是"提交"与"真删"之间的距离。把filter-only当演练、把取消期当刹车、把 compactor 指标当仪表盘,这套强操作能力就能安全地用在生产上。

<输出文章>

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

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询