K8s Operator通过事件过滤器监听密钥变化。

huangapple go评论89阅读模式
英文:

K8s Operator listen to secret change with event filter

问题

我们几个月前创建了一个使用kubebuilder运行良好的控制器。

几周前,我们向一个密钥添加了一个“监听器”,当密钥发生更改(密钥属性)时,应该调用reconcile函数。问题是它有时候工作有时候不工作(你更改密钥应用它,但reconcile函数没有被调用),我们对于完全相同的密钥文件进行操作。

我们尝试了几天来找到根本原因,但没有成功(我们将k8s.io/client-go v0.23.4更改为v0.22.3,现在使用的是v0.22.1,它才能正常工作)。有没有什么想法是什么问题?任何提示都会有帮助。或者有没有其他我们可以尝试的方法。

func (r *vtsReconciler) SetupWithManager(mgr ctrl.Manager) error {
    manager := ctrl.NewControllerManagedBy(mgr).
        For(&vts.str).
        WithEventFilter(predicate.Or(predicate.AnnotationChangedPredicate{}))
    manager = manager.Watches(&source.Kind{Type: &v1.Secret{}}, handler.EnqueueRequestsFromMapFunc(func(a client.Object) []reconcile.Request {
        return r.SecretRequests.SecretFinder(a.GetName())
    }))
    return manager.Complete(r)
}

func (secm *SecretMapper) SecretFinder(name string) []reconcile.Request {
    v := cli.ObjectKey{Name: name}
    return secm.SecMap[v.String()]
}
英文:

We have created a few month ago controller which runs great using kubebuilder.

Few weeks ago we added a “listener” to a secret which when the secret is changing (secret properties)
The reconcile should be invoked, the problem is that it is sometimes working and sometimes not, (you change the secret apply it and the reconcile doesn’t happens) , we are doing it for the exact same secret file.

We tried few days to find the root cause without success, (we change the k8s.io/client-go v0.23.4 and also to v0.22.3 and now v0.22.1 that is only working.
Any idea what the issue could be? any hint will be helpful. or Any other way to do it that we can try out.

func (r *vtsReconciler) SetupWithManager(mgr ctrl.Manager) error {
	manager := ctrl.NewControllerManagedBy(mgr).
		For(&vts.str).
		WithEventFilter(predicate.Or(predicate.AnnotationChangedPredicate{}))
	manager = manager.Watches(&source.Kind{Type: &v1.Secret{}}, handler.EnqueueRequestsFromMapFunc(func(a client.Object) []reconcile.Request {
		return r.SecretRequests.SecretFinder(a.GetName())
	}))
	return manager.Complete(r)
}



func (secm *SecretMapper) SecretFinder(name string) []reconcile.Request {
	v := cli.ObjectKey{Name: name}
	return secm.SecMap[v.String()]
}

答案1

得分: 4

最可能的问题是WithEventFilter适用于控制器监视的所有对象。对于CRD,生成是自动递增的,但并不适用于所有资源类型。

从GenerationChangedPredicate文档中可以看到:

// 注意事项:
//
// * 假设生成仅在写入spec时递增,并不适用于所有API。
// 例如,对于Deployment对象,生成也会在写入metadata.annotations字段时递增。
// 对于除自定义资源之外的对象类型,请确保在写入时会触发生成递增的字段。

您可以通过创建或更新一个secret来检查这一点,您会发现没有设置生成(至少在我的本地k3d集群上没有)。

最可能的情况是在创建时它可以工作,因为最初控制器将会将现有资源与集群同步。

要解决这个问题,您可以使用以下代码:

func (r *vtsReconciler) SetupWithManager(mgr ctrl.Manager) error {
    manager := ctrl.NewControllerManagedBy(mgr).
        For(&vts.str, WithPredicates(predicate.Or(predicate.GenerationChangedPredicate{}, predicate.AnnotationChangedPredicate{}))).
    manager = manager.Watches(&source.Kind{Type: &v1.Secret{}}, handler.EnqueueRequestsFromMapFunc(func(a client.Object) []reconcile.Request {
        return r.SecretRequests.FindForSecret(a.GetNamespace(), a.GetName())
    }))
    return manager.Complete(r)
}

这样可以将谓词应用于您的自定义资源。

英文:

Most likely the issue is that the WithEventFIlter applies to all watched objects by the controller. The generation is auto-incremented for CRDs, but this doesn't hold for all resource types.

From the GenerationChangedPredicate docs:

// Caveats:
//
// * The assumption that the Generation is incremented only on writing to the spec does not hold for all APIs.
// E.g For Deployment objects the Generation is also incremented on writes to the metadata.annotations field.
// For object types other than CustomResources be sure to verify which fields will trigger a Generation increment when they are written to.

You can check this by creating a secret / updating a secret you will see that there is no generation set (at least not on my local k3d cluster).

Most likely it works for the creation as initially the controller will sync existing resources with the cluster.

To solve it you can use:

func (r *vtsReconciler) SetupWithManager(mgr ctrl.Manager) error {
    manager := ctrl.NewControllerManagedBy(mgr).
        For(&vts.str, WithPredicates(predicate.Or(predicate.GenerationChangedPredicate{}, predicate.AnnotationChangedPredicate{}))).
    manager = manager.Watches(&source.Kind{Type: &v1.Secret{}}, handler.EnqueueRequestsFromMapFunc(func(a client.Object) []reconcile.Request {
        return r.SecretRequests.FindForSecret(a.GetNamespace(), a.GetName())
    }))
    return manager.Complete(r)
}

which should apply the predicates only to your custom resource.

huangapple
  • 本文由 发表于 2022年3月26日 17:48:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/71626957.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定