使用谓词来优化手表

在使用控制器时,使用 谓词 来过滤事件和控制何时触发调整循环通常是有益的。

谓词 允许您基于事件(例如创建、更新或删除)和资源字段(例如标签、注释或状态字段)定义条件。通过使用 谓词,您可以细化控制器的行为,使其仅对所观察资源的特定变化做出响应。

这在你想要细化哪些资源的变化应该触发对账时尤其有用。通过使用谓词,你可以避免不必要的对账,并确保控制器仅对相关变化做出反应。

何时使用谓词

谓词在以下情况下很有用:

  • 您想忽略某些更改,例如那些不影响控制器关注的字段的更新。
  • 您只想对具有特定标签或注释的资源触发调整。
  • 您希望监视外部资源,并仅对特定更改做出反应。

示例:使用谓词过滤更新事件

假设我们只希望我们的 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 中的其他所有更改(例如注释或其他字段)将被忽略。
  • CreateFuncDeleteFuncGenericFunc 返回 true,意味着创建、删除和通用事件仍然被处理,从而允许这些事件类型的调整发生。

这确保了只有在特定字段 spec.size 被修改时,控制器才会进行调整,而忽略 spec 中与您的逻辑无关的其他修改。

示例:在Watches中使用谓词

现在,我们将这个谓词应用在 BackupBusyboxReconcilerWatches() 方法中,以便仅针对相关事件触发重新对账:

// 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):此方法应用谓词,确保只有在 Busyboxspec.size 字段发生变化时才会进行调解。
  • 其他事件:控制器仍将在 创建删除通用 事件上触发调整。