我使用 operator-sdk 创建了一个自定义资源DatabaseService
。创建DatabaseService
CR 应触发Reconcile
从第三方获取机密后在 CR 命名空间中创建机密的函数。
我将 CR 设置为秘密的所有者,这样每当手动删除秘密时,协调功能就会再次触发并重新创建秘密。
这是代码:
func (r *DatabaseServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
requeueResult := ctrl.Result{Requeue: true, RequeueAfter: time.Minute}
emptyResult := ctrl.Result{Requeue: false, RequeueAfter: 0}
ds := &operatorsv1alpha1.DatabaseService{}
if err := r.Client.Get(context.Background(), req.NamespacedName, ds); err != nil {
if misc.IsNotFound(err) {
return emptyResult, nil
})
return requeueResult, err
}
secret, err := getSecretFromThirdParty(ds)
if err != nil {
return requeueResult, err
}
if err := controllerutil.SetControllerReference(ds, secret, r.Scheme); err != nil {
logger.Error("failed to set controller reference for the secret", zap.Error(err))
return requeueResult, err
}
if err := r.createOrUpdateSecret(secret, logger); err != nil {
return requeueResult, err
}
return emptyResult, nil
}
func (r *DatabaseServiceReconciler) createOrUpdateSecret(secret *corev1.Secret) error {
if err := r.createNamespaceIfNotExist(secret.Namespace, logger); err != nil {
return err
}
if err := r.Client.Create(context.TODO(), secret); err == nil {
return nil
}
if !apierrors.IsAlreadyExists(err) {
return err
}
if err := r.Client.Update(context.TODO(), secret); err != nil {
return err
}
return nil
}
我观察到,如果我在调用之前将 CR 设置为秘密的所有者createOrUpdateSecret
- 将再次触发协调功能,因为拥有的对象(秘密)中的某些内容发生了变化。
我的 Reconcile 逻辑是幂等的,所以这不是一个大问题。但是,在从内部对拥有的对象进行更改后,我无需Reconcile
再次运行Reconcile
。现在,每次 Reconcile 创建/更新秘密时,它都会再次运行。这种行为似乎有点笨拙,并导致操作员的额外工作以及对第三方的额外调用。
有没有办法绕过从内部重新激活 Reconcile 创建/更新拥有的对象Reconcile
?还是不建议这样做,我应该允许反复运行协调直到没有任何改变?