Skip to content

🐛 fix(eks): add ObservedGeneration to AWSManagedControlPlane to prevent missed spec changes#6084

Merged
kubernetes-prow[bot] merged 2 commits into
kubernetes-sigs:mainfrom
damdo:fix/eks-upgrade-policy-race
Jun 30, 2026
Merged

🐛 fix(eks): add ObservedGeneration to AWSManagedControlPlane to prevent missed spec changes#6084
kubernetes-prow[bot] merged 2 commits into
kubernetes-sigs:mainfrom
damdo:fix/eks-upgrade-policy-race

Conversation

@damdo

@damdo damdo commented Jun 29, 2026

Copy link
Copy Markdown
Member

What type of PR is this?

/kind bug

What this PR does / why we need it:

The AWSManagedControlPlane controller could miss spec changes due to controller-runtime event coalescing. When multiple EKS clusters are reconciling concurrently, all 5 worker slots can be occupied for 12+ minutes. If a spec change arrives during this window, its watch event gets coalesced with an earlier status-patch event in the work queue. Since reconcileNormal returns ctrl.Result{} (no RequeueAfter), the controller never re-examines the object and the spec change is never reconciled.

Root cause confirmed from CI logs: the spec change watch event was not lost — it was deduplicated in the work queue because all workers were busy with long-running EKS cluster creation reconciles. By the time a worker picked up the item, the test had already issued a delete.

This PR:

  • Adds status.observedGeneration to AWSManagedControlPlaneStatus (both v1beta2 and v1beta1) and wires WithStatusObservedGeneration into the controller's defer block on successful reconciliation. This is the idiomatic CAPI pattern already used by EKSConfigReconciler and NodeadmConfigReconciler in this repo.
  • Adds a conditional RequeueAfter at the end of reconcileNormal: when observedGeneration < generation, the controller requeues to catch any coalesced spec changes. Once caught up, it returns nil and goes quiescent — no unnecessary periodic reconciling.
  • Adds PrincipalUsageAllowedCondition and PrincipalCredentialRetrievedCondition to the ManagedControlPlaneScope's owned conditions list — they were set during scope creation but not declared as owned, which caused patch conflicts when WithStatusObservedGeneration was added.
  • Hardens the [upgrade-policy] e2e test by verifying the spec patch is persisted before polling EKS, and increases the EKS API polling timeout from 5 to 10 minutes.

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #6085

Special notes for your reviewer:

The ObservedGeneration + conditional requeue mechanism works as follows:

  1. On successful reconciliation, the deferred scope.Close() sets status.observedGeneration = metadata.generation via the CAPI patch helper's WithStatusObservedGeneration option.
  2. At the end of reconcileNormal, if observedGeneration < generation (values read at reconcile start), the controller requeues after WaitInfraPeriod (default 1 minute). This catches spec changes that were coalesced during a long reconcile.
  3. The follow-up reconcile sees observedGeneration == generation (set by the previous scope.Close()) and returns nil — the controller goes quiescent.

The v1beta1 conversion is auto-generated — ObservedGeneration is a simple int64 field present in both versions, so conversion-gen handles it automatically.

AI Usage:

Claude Code was used to investigate the root cause via Prow CI artifacts, research the CAPI WithStatusObservedGeneration pattern, implement the fix, and create this PR.

Checklist:

  • squashed commits
  • includes documentation
  • includes AI generated content
  • includes emoji in title
  • adds unit tests
  • adds or updates e2e tests

Release note:

fix(eks): race condition where AWSManagedControlPlane controller could miss spec changes due to controller-runtime event coalescing by adding status.observedGeneration tracking and conditional requeue.

… missed spec changes

The AWSManagedControlPlane controller could miss spec changes due to
controller-runtime event coalescing. When a long reconcile completes,
the deferred scope.Close() status patch and an external spec patch
(e.g. UpgradePolicy change) can arrive within the same work queue
window and get coalesced into a single reconcile that may read stale
state.

Add status.observedGeneration to AWSManagedControlPlane and wire
WithStatusObservedGeneration into the controller's defer block on
successful reconciliation, matching the pattern already used by
EKSConfigReconciler and NodeadmConfigReconciler.

Also add PrincipalUsageAllowedCondition and
PrincipalCredentialRetrievedCondition to the ManagedControlPlaneScope's
owned conditions list — they were set during scope creation but not
declared as owned, causing patch conflicts.

Harden the upgrade-policy e2e test by verifying the spec patch is
persisted before polling EKS, and increase the EKS API polling timeout
from 5 to 10 minutes.

Signed-off-by: Damiano Donati <damiano.donati@gmail.com>
@kubernetes-prow kubernetes-prow Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/bug Categorizes issue or PR as related to a bug. labels Jun 29, 2026
@kubernetes-prow kubernetes-prow Bot requested review from fiunchinho and nrb June 29, 2026 13:53
@kubernetes-prow kubernetes-prow Bot added needs-priority cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jun 29, 2026
@damdo

damdo commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

/hold

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 29, 2026
@damdo

damdo commented Jun 29, 2026

Copy link
Copy Markdown
Member Author

/test pull-cluster-api-provider-aws-e2e-eks

…d events

When multiple EKS clusters reconcile concurrently, all worker slots can
be occupied for 12+ minutes. Watch events that arrive during this window
get coalesced in the work queue, causing spec changes to be silently
dropped. Add a conditional RequeueAfter when observedGeneration is behind
the current generation, ensuring one follow-up reconcile to process any
spec change that was coalesced. The controller goes quiescent once
observedGeneration catches up.

Signed-off-by: Damiano Donati <damiano.donati@gmail.com>
@damdo

damdo commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

/test pull-cluster-api-provider-aws-e2e-eks

1 similar comment
@damdo

damdo commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

/test pull-cluster-api-provider-aws-e2e-eks

@damdo

damdo commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

/unhold

@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 30, 2026
@damdo

damdo commented Jun 30, 2026

Copy link
Copy Markdown
Member Author

/assign @richardcase @dlipovetsky @AndiDog @nrb @clebs

@clebs

clebs commented Jun 30, 2026

Copy link
Copy Markdown
Member

/lgtm

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 30, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

LGTM label has been added.

DetailsGit tree hash: 9a68fac4816216184332d1fe19ae5244971bd97a

@nrb nrb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/approve

@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: nrb

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 30, 2026
@kubernetes-prow kubernetes-prow Bot merged commit daad8ec into kubernetes-sigs:main Jun 30, 2026
22 checks passed
@damdo

damdo commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

@nrb how do we feel about backporting this?

@damdo

damdo commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

/cherry-pick release-2.11 release-2.10

@k8s-infra-cherrypick-robot

Copy link
Copy Markdown

@damdo: new pull request created: #6090

Details

In response to this:

/cherry-pick release-2.11 release-2.10

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. needs-priority release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flake] AWSManagedControlPlane spec changes can be silently dropped due to event coalescing

7 participants