You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kubernetes Operator控制器自定义指标删除功能失效求助

Kubernetes Operator自定义指标删除失效的排查与解决

排查方向与解决方案

1. 验证标签匹配的一致性

删除指标时必须完全匹配注册时使用的所有标签键和值,任何拼写、大小写或维度缺失都会导致删除失败:

  • 检查注册指标时的标签定义,比如如果注册是:
    custom_metric_name.With(prometheus.Labels{
        "cr_name":   cr.Name,
        "namespace": cr.Namespace,
        "cluster":   "default",
    })
    
    那删除时必须包含所有3个标签,不能只传name和namespace。
  • 直接查询Prometheus确认指标的实际标签:执行curl http://<prometheus-addr>:9090/api/v1/query?query=custom_metric_name,对比返回的标签键值对和删除代码中的参数。

2. 确认指标实例的全局唯一性

如果custom_metric_name不是全局单例(比如在函数内局部初始化),删除操作会针对错误的指标实例生效,导致实际暴露的指标不受影响:

  • 确保custom_metric_name是全局变量,且只初始化一次:
    var custom_metric_name = prometheus.NewGaugeVec(
        prometheus.GaugeOpts{Name: "custom_metric_name"},
        []string{"name", "namespace"},
    )
    
  • 初始化后立即注册到Prometheus:prometheus.MustRegister(custom_metric_name)

3. 改用Finalizer处理删除逻辑

仅在errors.IsNotFound(err)分支处理删除不可靠——CR被删除时,Kubernetes会先标记DeletionTimestamp,此时CR还存在,直到所有Finalizer被移除。用Finalizer确保指标删除逻辑必执行:

func (r *cr) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    cr := &CR{}
    err := r.Get(ctx, req.NamespacedName, cr)
    if err != nil {
        if errors.IsNotFound(err) {
            return ctrl.Result{}, nil
        }
        return ctrl.Result{}, err
    }

    // 处理CR删除流程
    if !cr.DeletionTimestamp.IsZero() {
        // 执行指标删除
        DeleteMetric(cr, true)
        // 移除自定义Finalizer
        cr.Finalizers = slices.DeleteFunc(cr.Finalizers, func(f string) bool {
            return f == "cr.example.com/metric-cleanup"
        })
        if err := r.Update(ctx, cr); err != nil {
            return ctrl.Result{}, err
        }
        return ctrl.Result{}, nil
    }

    // 为CR添加Finalizer(首次创建时)
    if !slices.Contains(cr.Finalizers, "cr.example.com/metric-cleanup") {
        cr.Finalizers = append(cr.Finalizers, "cr.example.com/metric-cleanup")
        if err := r.Update(ctx, cr); err != nil {
            return ctrl.Result{}, err
        }
        return ctrl.Result{Requeue: true}, nil
    }

    // 正常业务逻辑...
    return ctrl.Result{}, nil
}

4. 修复Predicate的Delete事件过滤

如果使用Predicate,确保它不会拦截Delete事件:

// 配置Predicate,允许接收Delete事件
pred := predicates.NewPredicateFuncs(func(obj client.Object) bool {
    // 始终允许Delete事件
    if obj.GetDeletionTimestamp() != nil {
        return true
    }
    // 其他事件的过滤逻辑
    return true
})

// 在SetupWithManager中使用
err = r.SetupWithManager(mgr, ctrl.NewControllerManagedBy(mgr).
    For(&CR{}).
    WithEventFilter(pred).
    // 其他子资源...
)

5. 增加日志排查细节

在DeleteMetric中添加更详细的日志,验证删除操作的执行状态:

func DeleteMetric(cr *CR, condition bool) {
    l := logf.Log.WithName("CR Metric deletion")
    l.Info("Deleting metric for CR", "instance", cr.Name, "namespace", cr.Namespace)
    if condition {
        // 删除前检查指标是否存在
        gauge := custom_metric_name.With(prometheus.Labels{
            "name":      cr.Name,
            "namespace": cr.Namespace,
        })
        l.Info("Current metric value before deletion", "value", gauge.Get())
        
        // 执行删除
        custom_metric_name.Delete(prometheus.Labels{
            "name":      cr.Name,
            "namespace": cr.Namespace,
        })
        
        // 删除后再次检查
        l.Info("Metric exists after deletion?", "exists", gauge.Get() != 0)
    }
}

内容的提问来源于stack exchange,提问作者unbox-us

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:10:35