使用谓词来优化手表
在使用控制器时,使用 谓词 来过滤事件和控制何时触发调整循环通常是有益的。
谓词 允许您基于事件(例如创建、更新或删除)和资源字段(例如标签、注释或状态字段)定义条件。通过使用 谓词,您可以细化控制器的行为,使其仅对所观察资源的特定变化做出响应。
这在你想要细化哪些资源的变化应该触发对账时尤其有用。通过使用谓词,你可以避免不必要的对账,并确保控制器仅对相关变化做出反应。
何时使用谓词
谓词在以下情况下很有用:
- 您想忽略某些更改,例如那些不影响控制器关注的字段的更新。
- 您只想对具有特定标签或注释的资源触发调整。
- 您希望监视外部资源,并仅对特定更改做出反应。
示例:使用谓词过滤更新事件
假设我们只希望我们的 BackupBusybox
控制器在 Busybox
资源的某些字段发生变化时进行调整,例如,当 spec.size
字段发生变化时,但我们希望忽略所有其他变化(如状态更新)。
定义谓词
在下面的示例中,我们定义了一个谓词,仅在对 Busybox
资源有重要更新时才允许对账:
import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/event"
)
// 仅在 Busybox 规格的大小变化时触发重新调整的谓词
updatePred := predicate.Funcs{
// 仅在 Busybox 资源的 spec.size 发生变化时允许更新
UpdateFunc: func(e event.UpdateEvent) bool {
oldObj := e.ObjectOld.(*examplecomv1alpha1.Busybox)
newObj := e.ObjectNew.(*examplecomv1alpha1.Busybox)
// 仅在 spec.size 字段发生变化时触发重新对账 return oldObj.Spec.Size != newObj.Spec.Size
},
// 允许创建事件
CreateFunc: func(e event.CreateEvent) bool {
return true
},
// 允许删除事件
DeleteFunc: func(e event.DeleteEvent) bool {
return true
},
// 允许通用事件(例如,外部触发)
GenericFunc: func(e event.GenericEvent) bool {
return true
},
}
Explanation
在这个例子中:
UpdateFunc
仅在spec.size
字段在旧对象和新对象之间发生变化时返回true
,这意味着在spec
中的其他所有更改(例如注释或其他字段)将被忽略。CreateFunc
、DeleteFunc
和GenericFunc
返回true
,意味着创建、删除和通用事件仍然被处理,从而允许这些事件类型的调整发生。
这确保了只有在特定字段 spec.size
被修改时,控制器才会进行调整,而忽略 spec
中与您的逻辑无关的其他修改。
示例:在Watches
中使用谓词
现在,我们将这个谓词应用在 BackupBusyboxReconciler
的 Watches()
方法中,以便仅针对相关事件触发重新对账:
// SetupWithManager 使用 Manager 设置控制器。
// 控制器将同时监视 BackupBusybox 主要资源和 Busybox 资源,并使用谓词。func (r *BackupBusyboxReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&examplecomv1alpha1.BackupBusybox{}). // 观察主要资源(BackupBusybox)
Watches(
&source.Kind{Type: &examplecomv1alpha1.Busybox{}}, // 观察 Busybox CR
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
return []reconcile.Request{
{
NamespacedName: types.NamespacedName{
Name: "backupbusybox", // 对关联的 BackupBusybox 资源进行调整
Namespace: obj.GetNamespace(), // 使用已更改的 Busybox 命名空间
},
},
}
}),
builder.WithPredicates(updatePred), // 应用谓词 ). // 当 Busybox 资源发生变化时触发调整(如果符合谓词条件)
Complete(r)
}
Explanation
builder.WithPredicates(updatePred)
:此方法应用谓词,确保只有在Busybox
中spec.size
字段发生变化时才会进行调解。- 其他事件:控制器仍将在
创建
、删除
和通用
事件上触发调整。