fix(deploy): 删除部署时同步清理自动注册的查询数据源(孤儿数据源)
=== 现象(用户实测)=== 在 /deployments 页面删掉两个主机模式部署后,本机(172.19.16.8)容器确实清干净了: docker ps -a 无任何 lokistack-* 容器 /etc/promtail、/var/lib/promtail 等目录均不存在 无 promtail systemd 单元 但**平台里残留一个数据源** host-verify-loki(url=http://172.19.16.8:3100), 「日志查询」下拉里还能选到它,选中必然连接失败。 === 根因 === DeploymentService.Delete 只做了两件事:删容器、删部署记录。 部署创建时由 EnsureLogSourceForDeployment 自动注册的托管数据源(Managed=true) 没有任何清理逻辑 —— 删除动作只完成了一半。 === 修法 === 1) DeploymentService.Delete 删完记录后调用 CleanupManagedLogSource(部署名) - 删掉同名且 Managed=true 的数据源(手填的 Managed=false 不动) - DeleteLogSource 内部会连带删除指向它的查询授权策略组 - 绑定该源的告警规则置为禁用(保留配置便于审计,但不让它每次评估都失败) - 注意锁顺序:必须先 db.Unlock() 再调用,CleanupManagedLogSource 内部会自己加锁, 持有锁再调用会死锁 2) schemaVersion v6→v7 迁移 removeOrphanManagedLogSources() 清理历史遗留:Managed=true 但没有任何同名部署的数据源 → 删除, 连带删策略组、禁用告警规则 === 实测(d9487694ece6)=== v7 迁移日志:移除孤儿数据源 "host-verify-loki"(id=2):对应部署已删除 数据源:1 个(只剩 loki-pre,managed=true) 部署:1 / 采集器:1 / 策略组:1 本机:docker ps -a 无 lokistack-* 容器,/etc/promtail 等目录不存在,无 systemd 单元
This commit is contained in:
1 parent
6d6e17745c
commit
bad61e5027
3 files changed
+114
-6
No files matched your search
@@ -113,6 +113,48 @@ func (d *JsonDB) raiseLegacyAlertThresholds() {
|
||||
}
|
||||
}
|
||||
|
||||
// removeOrphanManagedLogSources 清掉"部署已不存在、但数据源还在"的孤儿记录。
|
||||
//
|
||||
// 判据:Managed=true(平台托管)且没有任何同名部署。
|
||||
// 连带:删掉指向它的查询授权策略组,并禁用绑定它的告警规则。
|
||||
func (d *JsonDB) removeOrphanManagedLogSources() {
|
||||
alive := map[string]bool{}
|
||||
for _, dep := range d.Deployments {
|
||||
alive[dep.Name] = true
|
||||
}
|
||||
orphans := map[uint]bool{}
|
||||
kept := make([]models.LogSource, 0, len(d.LogSources))
|
||||
for _, src := range d.LogSources {
|
||||
if src.Managed && !alive[src.Name] {
|
||||
orphans[src.ID] = true
|
||||
log.Printf("[schema] 移除孤儿数据源 %q(id=%d):对应部署已删除", src.Name, src.ID)
|
||||
continue
|
||||
}
|
||||
kept = append(kept, src)
|
||||
}
|
||||
if len(orphans) == 0 {
|
||||
return
|
||||
}
|
||||
d.LogSources = kept
|
||||
|
||||
groups := make([]models.LogPolicyGroup, 0, len(d.LogPolicyGroups))
|
||||
for _, group := range d.LogPolicyGroups {
|
||||
if orphans[group.SourceID] {
|
||||
log.Printf("[schema] 移除指向孤儿数据源的策略组 %q", group.Name)
|
||||
continue
|
||||
}
|
||||
groups = append(groups, group)
|
||||
}
|
||||
d.LogPolicyGroups = groups
|
||||
|
||||
for i := range d.AlertRules {
|
||||
if orphans[d.AlertRules[i].SourceID] {
|
||||
d.AlertRules[i].Enabled = false
|
||||
log.Printf("[schema] 告警规则 %q 的数据源已删除,规则已禁用", d.AlertRules[i].Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// linkRulesToDefaultChannel 给未关联通道的规则挂上默认通道。
|
||||
//
|
||||
// 没有通道时不凭空造(那是 seed 首次部署的职责);这里只在已有通道时补齐关联。
|
||||
@@ -366,7 +408,7 @@ func (d *JsonDB) dedupeLogSourceIDs() {
|
||||
//
|
||||
// v0/v1(无字段)→ 1:新增 auditLogs / schemaVersion(老库走零值兜底即可,无需处理)
|
||||
// v1 → 2:预留示例(如把 ScrapeJobs 从 logPath 拆分时,需按旧结构生成默认 job)
|
||||
const CurrentSchemaVersion = 6
|
||||
const CurrentSchemaVersion = 7
|
||||
|
||||
// migrateSchema 按版本号顺序迁移老库。返回是否发生了迁移(需要回写)。
|
||||
func (d *JsonDB) migrateSchema() bool {
|
||||
@@ -426,6 +468,12 @@ func (d *JsonDB) migrateSchema() bool {
|
||||
// notify-config;那个早就不用了,结果就是"规则在响但哪里都没发出去"。
|
||||
d.linkRulesToDefaultChannel()
|
||||
d.SchemaVersion = 6
|
||||
case 6:
|
||||
// v6 → v7:清理"孤儿数据源"。
|
||||
// 删除部署时曾漏掉对自动注册数据源的清理,导致查询页残留指向
|
||||
// 已删实例的数据源(线上残留过 host-verify-loki)。
|
||||
d.removeOrphanManagedLogSources()
|
||||
d.SchemaVersion = 7
|
||||
default:
|
||||
// 防御:出现未知版本(比当前代码还新)时不乱动,避免降级把数据写坏
|
||||
log.Printf("[schema] 数据库版本 %d 高于当前代码支持版本 %d,跳过迁移", d.SchemaVersion, CurrentSchemaVersion)
|
||||
|
||||
Reference in new issue
Block a user