From d326cb10871c15481ade975eff8ec8aa8fe464b9 Mon Sep 17 00:00:00 2001 From: Ziyang LIN Date: Fri, 16 Jan 2026 16:37:33 +0100 Subject: [PATCH] fix: reduce excessive reconciliation and disable dev mode logging - Remove hardcoded `Development: true` from zap.Options to use production logging configuration by default (JSON format, info level) - Add status change detection to avoid unnecessary API calls when status conditions haven't changed - Add GenerationChangedPredicate for ScalityUI watch to prevent reconcile triggers from ScalityUI status changes To enable debug logging when needed: - Use `--zap-devel` flag for development mode - Use `--zap-log-level=debug` for debug level only --- cmd/main.go | 4 +--- .../scalityuicomponentexposer/controller.go | 10 +++++++++- .../reconcile_context.go | 17 +++++++++++++++++ .../scalityuicomponentexposer/status.go | 13 ++++++++++++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index dd98c2c..57740b5 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -77,9 +77,7 @@ func main() { "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.") flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") - opts := zap.Options{ - Development: true, - } + opts := zap.Options{} opts.BindFlags(flag.CommandLine) flag.Parse() diff --git a/internal/controller/scalityuicomponentexposer/controller.go b/internal/controller/scalityuicomponentexposer/controller.go index c925741..c1a4686 100644 --- a/internal/controller/scalityuicomponentexposer/controller.go +++ b/internal/controller/scalityuicomponentexposer/controller.go @@ -11,9 +11,11 @@ import ( "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -72,6 +74,8 @@ func (r *ScalityUIComponentExposerReconciler) Reconcile(ctx context.Context, req return reconcile.Result{}, err } + currentState.SetOldStatus(cr.Status.DeepCopy()) + resourceReconcilers := buildReducerList(r, cr, currentState) for _, rr := range resourceReconcilers { res, err := rr.F(cr, currentState, log) @@ -104,7 +108,11 @@ func (r *ScalityUIComponentExposerReconciler) SetupWithManager(mgr ctrl.Manager) For(&uiv1alpha1.ScalityUIComponentExposer{}). Owns(&networkingv1.Ingress{}). Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.findExposersForConfigMap)). - Watches(&uiv1alpha1.ScalityUI{}, handler.EnqueueRequestsFromMapFunc(r.findExposersForScalityUI)). + Watches( + &uiv1alpha1.ScalityUI{}, + handler.EnqueueRequestsFromMapFunc(r.findExposersForScalityUI), + builder.WithPredicates(predicate.GenerationChangedPredicate{}), + ). Watches(&uiv1alpha1.ScalityUIComponent{}, handler.EnqueueRequestsFromMapFunc(r.findExposersForScalityUIComponent)). Complete(r) } diff --git a/internal/controller/scalityuicomponentexposer/reconcile_context.go b/internal/controller/scalityuicomponentexposer/reconcile_context.go index 2887b0d..c57c416 100644 --- a/internal/controller/scalityuicomponentexposer/reconcile_context.go +++ b/internal/controller/scalityuicomponentexposer/reconcile_context.go @@ -12,6 +12,7 @@ import ( type reconcileContext struct { reconciler.BaseReconcileState + oldStatus *uiv1alpha1.ScalityUIComponentExposerStatus } var _ reconciler.State = &reconcileContext{} @@ -22,10 +23,26 @@ func newReconcileContextWithCtx(ctx context.Context) *reconcileContext { } } +// SetOldStatus stores the original status for comparison +func (r *reconcileContext) SetOldStatus(status *uiv1alpha1.ScalityUIComponentExposerStatus) { + r.oldStatus = status +} + +// GetOldStatus returns the original status +func (r *reconcileContext) GetOldStatus() *uiv1alpha1.ScalityUIComponentExposerStatus { + return r.oldStatus +} + // Type aliases for better readability type ScalityUIComponentExposer = *uiv1alpha1.ScalityUIComponentExposer type State = reconciler.State +// ExtendedState provides access to additional state beyond the base reconciler.State +type ExtendedState interface { + reconciler.State + GetOldStatus() *uiv1alpha1.ScalityUIComponentExposerStatus +} + // StateReducer represents a step in the reconciliation process type StateReducer struct { N string // Name of the reducer diff --git a/internal/controller/scalityuicomponentexposer/status.go b/internal/controller/scalityuicomponentexposer/status.go index 1f9455e..569d97e 100644 --- a/internal/controller/scalityuicomponentexposer/status.go +++ b/internal/controller/scalityuicomponentexposer/status.go @@ -5,6 +5,7 @@ import ( "github.com/go-logr/logr" uiv1alpha1 "github.com/scality/ui-operator/api/v1alpha1" + "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -41,8 +42,18 @@ func setStatusCondition(cr *uiv1alpha1.ScalityUIComponentExposer, conditionType meta.SetStatusCondition(&cr.Status.Conditions, condition) } -// updateStatus updates the ScalityUIComponentExposer status +// updateStatus updates the ScalityUIComponentExposer status only if it has changed func updateStatus(ctx context.Context, cr *uiv1alpha1.ScalityUIComponentExposer, currentState State, log logr.Logger) error { + // Check if status actually changed + extState, ok := currentState.(ExtendedState) + if ok { + oldStatus := extState.GetOldStatus() + if oldStatus != nil && equality.Semantic.DeepEqual(oldStatus, &cr.Status) { + log.V(1).Info("Status unchanged, skipping update", "exposer", cr.Name) + return nil + } + } + client := currentState.GetKubeClient() // Update the status subresource