Skip to content

Fix reconcile loops caused by server-defaulted fields in CreateOrPatch#681

Open
lmiccini wants to merge 1 commit intoopenstack-k8s-operators:mainfrom
lmiccini:fix-service-reconcile-loop
Open

Fix reconcile loops caused by server-defaulted fields in CreateOrPatch#681
lmiccini wants to merge 1 commit intoopenstack-k8s-operators:mainfrom
lmiccini:fix-service-reconcile-loop

Conversation

@lmiccini
Copy link
Copy Markdown
Contributor

@lmiccini lmiccini commented Apr 4, 2026

Service, Deployment, DaemonSet, and StatefulSet CreateOrPatch functions were overwriting entire specs/templates, stripping Kubernetes server-defaulted fields (e.g. TargetPort, ImagePullPolicy, SessionAffinity). This caused controllerutil.CreateOrPatch to detect a diff on every reconcile, creating infinite reconcile loops.

  • Add shared pod.MergeContainersByName to preserve container-level server defaults (ImagePullPolicy, TerminationMessagePath, TerminationMessagePolicy) across Deployment, DaemonSet, StatefulSet
  • Add service.MergeServicePorts to preserve port-level server defaults (TargetPort, Protocol)
  • Change Service CreateOrPatch to copy only operator-controlled fields, keeping the existing spec as base so server-defaulted fields are preserved implicitly
  • Deprecate statefulset.MergeContainersByName in favor of the shared pod.MergeContainersByName

Service, Deployment, DaemonSet, and StatefulSet CreateOrPatch functions
were overwriting entire specs/templates, stripping Kubernetes
server-defaulted fields (e.g. TargetPort, ImagePullPolicy,
SessionAffinity). This caused controllerutil.CreateOrPatch to detect a
diff on every reconcile, creating infinite reconcile loops.

- Add shared pod.MergeContainersByName to preserve container-level
  server defaults (ImagePullPolicy, TerminationMessagePath,
  TerminationMessagePolicy) across Deployment, DaemonSet, StatefulSet
- Add service.MergeServicePorts to preserve port-level server defaults
  (TargetPort, Protocol)
- Change Service CreateOrPatch to copy only operator-controlled fields,
  keeping the existing spec as base so server-defaulted fields are
  preserved implicitly
- Deprecate statefulset.MergeContainersByName in favor of the shared
  pod.MergeContainersByName

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant