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
@@ -4,6 +4,7 @@ package services
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -384,6 +385,54 @@ func reachableEndpoint(d *models.LokiDeployment) string {
|
||||
return endpoint
|
||||
}
|
||||
|
||||
// CleanupManagedLogSource 删除某部署名对应的**平台托管**数据源。
|
||||
//
|
||||
// 为什么必须有:部署删除后它自动注册的数据源若不清掉,「日志查询」下拉里会
|
||||
// 留一个指向已删实例的源,选中必然连接失败(线上残留过 host-verify-loki)。
|
||||
//
|
||||
// 连带处理:
|
||||
// - 该源上的查询授权策略组:DeleteLogSource 内部会一并删除
|
||||
// - 绑定了该源的告警规则:置为禁用(保留配置便于审计,但不再触发,
|
||||
// 否则引擎每次评估都会因为连不上而写失败记录)
|
||||
// - 手填的数据源(Managed=false)不动:那是用户自己建的,可能指向别的实例
|
||||
func CleanupManagedLogSource(name string) {
|
||||
db := repository.GetDB()
|
||||
if db == nil || name == "" {
|
||||
return
|
||||
}
|
||||
db.RLock()
|
||||
var sourceID uint
|
||||
for _, src := range db.LogSources {
|
||||
if src.Managed && src.Name == name {
|
||||
sourceID = src.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
db.RUnlock()
|
||||
if sourceID == 0 {
|
||||
// 部署本来就没注册数据源(如部署失败),无需处理
|
||||
return
|
||||
}
|
||||
|
||||
if err := DeleteLogSource(sourceID); err != nil {
|
||||
log.Printf("[deploy-delete] 清理数据源 %q(id=%d) 失败: %v", name, sourceID, err)
|
||||
}
|
||||
|
||||
db.Lock()
|
||||
defer db.Unlock()
|
||||
disabled := 0
|
||||
for i := range db.AlertRules {
|
||||
if db.AlertRules[i].SourceID == sourceID && db.AlertRules[i].Enabled {
|
||||
db.AlertRules[i].Enabled = false
|
||||
disabled++
|
||||
}
|
||||
}
|
||||
if disabled > 0 {
|
||||
db.RequestSave()
|
||||
log.Printf("[deploy-delete] %d 条告警规则因数据源被删而禁用", disabled)
|
||||
}
|
||||
}
|
||||
|
||||
// EnsureLogSourceForDeployment 部署成功后自动注册查询数据源(host→url;k8s→cluster-svc)。
|
||||
// 已存在同名数据源时:平台托管的自动刷新连接信息,用户手填的不覆盖。
|
||||
func EnsureLogSourceForDeployment(d *models.LokiDeployment) {
|
||||
|
||||
Reference in new issue
Block a user