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

如何让GrandPa控制器的Reconcile()在GrandSon对象变更时触发?

实现GrandPa控制器监听GrandSon对象变更的方案

因为.Owns()只能监听控制器直接拥有的资源,而GrandSon属于Son的子资源,没法通过链式所有权自动触发GrandPa的Reconcile。但可以通过直接监听GrandSon资源事件+反向追溯所有权链的方式实现需求,具体步骤如下:

1. 给GrandPa控制器添加GrandSon资源监听

在控制器的SetupWithManager方法里,除了原本的For(&v1.GrandPa{}),额外用Watches()方法注册对GrandSon的监听,同时指定自定义的所有者解析器:

import (
    mygroupv1 "your-module/api/v1" // 替换成实际的GrandSon API包路径
    "sigs.k8s.io/controller-runtime/pkg/event"
    "sigs.k8s.io/controller-runtime/pkg/predicate"
)

func (r *GrandPaReconciler) SetupWithManager(mgr ctrl.Manager) error {
    return ctrl.NewControllerManagedBy(mgr).
        For(&mygroupv1.GrandPa{}).
        // 注册GrandSon监听,用自定义解析器找对应的GrandPa
        Watches(
            &source.Kind{Type: &mygroupv1.GrandSon{}},
            &handler.EnqueueRequestForOwner{
                IsController: false, // GrandSon的直接所有者是Son,不是GrandPa
                OwnerType:    &mygroupv1.GrandPa{},
                OwnerResolver: &grandSonToGrandPaResolver{Client: r.Client},
            },
            // 可选:过滤事件类型,只处理需要的变更
            predicate.Funcs{
                CreateFunc: func(e event.CreateEvent) bool { return true },
                UpdateFunc: func(e event.UpdateEvent) bool { return true },
                DeleteFunc: func(e event.DeleteEvent) bool { return true },
                GenericFunc: func(e event.GenericEvent) bool { return false },
            },
        ).
        Complete(r)
}

2. 实现自定义所有者解析器

这个解析器的作用是从GrandSon对象出发,先找到它的父资源Son,再从Son找到对应的GrandPa,最后生成GrandPa的Reconcile请求:

import (
    "context"
    "k8s.io/apimachinery/pkg/types"
    "sigs.k8s.io/controller-runtime/pkg/client"
    "sigs.k8s.io/controller-runtime/pkg/reconcile"
)

type grandSonToGrandPaResolver struct {
    client.Client // 注入客户端,用来查询Son对象
}

func (r *grandSonToGrandPaResolver) GetOwner(obj client.Object) []reconcile.Request {
    grandSon := obj.(*mygroupv1.GrandSon)
    var requests []reconcile.Request

    // 第一步:从GrandSon的OwnerReferences里找到对应的Son
    var sonRef metav1.OwnerReference
    for _, ref := range grandSon.OwnerReferences {
        if ref.Kind == "Son" && ref.Controller != nil && *ref.Controller {
            sonRef = ref
            break
        }
    }
    if sonRef.Name == "" {
        return requests // 找不到Son,直接返回空请求
    }

    // 第二步:查询Son对象
    son := &mygroupv1.Son{}
    err := r.Client.Get(context.TODO(), types.NamespacedName{
        Namespace: grandSon.Namespace,
        Name:      sonRef.Name,
    }, son)
    if err != nil {
        log.Error(err, "查询Son对象失败", "grandson", grandSon.Name)
        return requests
    }

    // 第三步:从Son的OwnerReferences里找到对应的GrandPa
    var grandpaRef metav1.OwnerReference
    for _, ref := range son.OwnerReferences {
        if ref.Kind == "GrandPa" && ref.Controller != nil && *ref.Controller {
            grandpaRef = ref
            break
        }
    }
    if grandpaRef.Name == "" {
        return requests // 找不到GrandPa,返回空请求
    }

    // 生成GrandPa的Reconcile请求
    requests = append(requests, reconcile.Request{
        NamespacedName: types.NamespacedName{
            Namespace: grandSon.Namespace,
            Name:      grandpaRef.Name,
        },
    })
    return requests
}

3. 补充控制器的RBAC权限

需要给GrandPa控制器的ClusterRole添加Son和GrandSon的访问权限,否则查询资源会失败:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: grandpa-controller-role
rules:
# 原有GrandPa权限保留
- apiGroups: ["mygroup.example.com"]
  resources: ["grandpas"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# 添加Son的查询权限
- apiGroups: ["mygroup.example.com"]
  resources: ["sons"]
  verbs: ["get", "list", "watch"]
# 添加GrandSon的监听和查询权限
- apiGroups: ["mygroup.example.com"]
  resources: ["grandsons"]
  verbs: ["get", "list", "watch"]

注意事项

  • 可以根据业务需求调整事件过滤规则,比如只在GrandSon的特定状态字段变更时触发Reconcile,减少无效执行。
  • 要处理资源查询失败的场景,避免因为Son/GrandPa已被删除导致的报错影响控制器运行。

内容的提问来源于stack exchange,提问作者guettli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:04:51