🐛 fix(eks): add ObservedGeneration to AWSManagedControlPlane to prevent missed spec changes#6084
Conversation
… 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>
|
/hold |
|
/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>
|
/test pull-cluster-api-provider-aws-e2e-eks |
1 similar comment
|
/test pull-cluster-api-provider-aws-e2e-eks |
|
/unhold |
|
/assign @richardcase @dlipovetsky @AndiDog @nrb @clebs |
|
/lgtm |
|
LGTM label has been added. DetailsGit tree hash: 9a68fac4816216184332d1fe19ae5244971bd97a |
|
[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 DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
@nrb how do we feel about backporting this? |
|
/cherry-pick release-2.11 release-2.10 |
|
@damdo: new pull request created: #6090 DetailsIn response to this:
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. |
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
reconcileNormalreturnsctrl.Result{}(noRequeueAfter), 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:
status.observedGenerationtoAWSManagedControlPlaneStatus(both v1beta2 and v1beta1) and wiresWithStatusObservedGenerationinto the controller's defer block on successful reconciliation. This is the idiomatic CAPI pattern already used byEKSConfigReconcilerandNodeadmConfigReconcilerin this repo.RequeueAfterat the end ofreconcileNormal: whenobservedGeneration < generation, the controller requeues to catch any coalesced spec changes. Once caught up, it returnsniland goes quiescent — no unnecessary periodic reconciling.PrincipalUsageAllowedConditionandPrincipalCredentialRetrievedConditionto theManagedControlPlaneScope's owned conditions list — they were set during scope creation but not declared as owned, which caused patch conflicts whenWithStatusObservedGenerationwas added.[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:scope.Close()setsstatus.observedGeneration = metadata.generationvia the CAPI patch helper'sWithStatusObservedGenerationoption.reconcileNormal, ifobservedGeneration < generation(values read at reconcile start), the controller requeues afterWaitInfraPeriod(default 1 minute). This catches spec changes that were coalesced during a long reconcile.observedGeneration == generation(set by the previousscope.Close()) and returnsnil— the controller goes quiescent.The v1beta1 conversion is auto-generated —
ObservedGenerationis a simpleint64field present in both versions, soconversion-genhandles it automatically.AI Usage:
Claude Code was used to investigate the root cause via Prow CI artifacts, research the CAPI
WithStatusObservedGenerationpattern, implement the fix, and create this PR.Checklist:
Release note: