Skip to content

fix: isolate rule status cache per rule-reconcile workers - #332

Merged
kubernetes-prow[bot] merged 2 commits into
kubernetes-sigs:mainfrom
bhuvan-somisetty:fix-rule-cache-concurrency-data-race
Aug 1, 2026
Merged

fix: isolate rule status cache per rule-reconcile workers#332
kubernetes-prow[bot] merged 2 commits into
kubernetes-sigs:mainfrom
bhuvan-somisetty:fix-rule-cache-concurrency-data-race

Conversation

@bhuvan-somisetty

@bhuvan-somisetty bhuvan-somisetty commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Description

This PR resolves data races and memory leaks in the controller when --node-concurrent-reconciles is set to > 1:

  1. Rule Cache Data Race Fix: Updated RuleReadinessController.getApplicableRulesForNode to return rule.DeepCopy() pointers. Previously, returning pointers straight from r.ruleCache caused concurrent NodeReconciler worker threads to mutate rule.Status.NodeEvaluations and rule.Status.FailedNodes on the shared in-memory pointer without synchronization, resulting in Go data races and memory corruption under concurrent node reconciliation load.
    2. Prometheus Metric Leak Fix: Added metrics.EvaluationDuration.DeleteLabelValues(rule.Name) to reconcileDelete in nodereadinessrule_controller.go to ensure histogram metric series are unregistered when a rule CR is deleted.
  2. Unit Tests: Added TestGetApplicableRulesForNode_DeepCopy in helper_unit_test.go to verify that getApplicableRulesForNode returns isolated, deep-copied rule instances.

Related Issue

Fixes #331

Type of Change

/kind bug

Testing

  • Unit testing via go test -v ./internal/controller/...
  • Verified deep-copy isolation unit test passes without race conditions.

Checklist

  • make test passes
  • make lint passes

Does this PR introduce a user-facing change?

NONE

@netlify

netlify Bot commented Aug 1, 2026

Copy link
Copy Markdown

Deploy Preview for node-readiness-controller canceled.

Name Link
🔨 Latest commit d58c938
🔍 Latest deploy log https://app.netlify.com/projects/node-readiness-controller/deploys/6a6d9beb3bf01e0008f13dda

@kubernetes-prow kubernetes-prow Bot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Aug 1, 2026
@kubernetes-prow

Copy link
Copy Markdown

Welcome @bhuvan-somisetty!

It looks like this is your first PR to kubernetes-sigs/node-readiness-controller 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-sigs/node-readiness-controller has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@kubernetes-prow kubernetes-prow Bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Aug 1, 2026
@kubernetes-prow

Copy link
Copy Markdown

Hi @bhuvan-somisetty. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

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.

@kubernetes-prow kubernetes-prow Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Aug 1, 2026
@bhuvan-somisetty

Copy link
Copy Markdown
Contributor Author

/cc @ajaysundark @Priyankasaggu11929 @vitorfloriano @Karthik-K-N @AvineshTripathi

Hey folks! Whenever you get a chance, could you please take a look at this PR when convenient? It addresses the data race and metric memory leak under concurrent node reconciliations described in #331. Thanks a lot!

@ajaysundark

Copy link
Copy Markdown
Contributor

Thanks for your PR.

Note, this is duplicate to #330 and #209

@ajaysundark

Copy link
Copy Markdown
Contributor

#209 however lacks the unit-tests, so could obsolete the former to take this one.

Could you evaluate the fixes and also address the lint failures and update?

@ajaysundark

Copy link
Copy Markdown
Contributor

/uncc @Priyankasaggu11929 @vitorfloriano @Karthik-K-N @AvineshTripathi @dchen1107 @SergeyKanzhelev
/assign @bhuvan-somisetty

please reassign to me once you updated the PR.

…onDuration metric

Fix data races when running with --node-concurrent-reconciles > 1 by returning deep-copied rule objects from getApplicableRulesForNode. This isolates in-memory status evaluation mutations on rule pointers across concurrent worker goroutines.

Additionally, add missing EvaluationDuration unregistration in reconcileDelete to prevent Prometheus metric memory leaks when rules are deleted.

Signed-off-by: bhuvan-somisetty <somisettybhuvan5@gmail.com>
@bhuvan-somisetty
bhuvan-somisetty force-pushed the fix-rule-cache-concurrency-data-race branch from ee57367 to d58c938 Compare August 1, 2026 07:10
@bhuvan-somisetty

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @ajaysundark!

I rebased onto latest main and noticed #330 (the metric cleanup fix) had already been merged, so I dropped that hunk from this PR to avoid the duplicate — this PR now only carries the ruleCache deep-copy fix plus the unit test that #209 was missing.

Also fixed the lint failure: the test file had a gofmt formatting issue (extra blank line) and a usetesting nit (swapped context.Background() for t.Context()). Verified locally with go build ./..., go vet ./..., go test ./internal/controller/..., and golangci-lint run — all clean now.

Reassigning to you as requested. Let me know if you'd like anything else adjusted.

@bhuvan-somisetty

Copy link
Copy Markdown
Contributor Author

/assign @ajaysundark

@ajaysundark

Copy link
Copy Markdown
Contributor

/ok-to-test

@kubernetes-prow kubernetes-prow Bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 1, 2026
@ajaysundark

Copy link
Copy Markdown
Contributor

@bhuvan-somisetty Can you review #209 and evaluate the recordFailure patch you noted on your issue as well - this could be a separate followup PR.

@ajaysundark

Copy link
Copy Markdown
Contributor

/retitle fix: isolate rule status cache per rule-reconcile workers

@kubernetes-prow kubernetes-prow Bot changed the title fix: isolate ruleCache pointers per reconcile and unregister EvaluationDuration metric fix: isolate rule status cache per rule-reconcile workers Aug 1, 2026
@ajaysundark

Copy link
Copy Markdown
Contributor

/lgtm

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

@ajaysundark ajaysundark 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.

Thanks!

@kubernetes-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ajaysundark, bhuvan-somisetty

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 Aug 1, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit d9aae37 into kubernetes-sigs:main Aug 1, 2026
11 checks passed
@bhuvan-somisetty

Copy link
Copy Markdown
Contributor Author

Thanks @ajaysundark!

Took a look at #209 and dug into the recordFailure/stale FailedNodes behavior on top of what's now merged here. Turns out it's a real, still-open bug, but only on one of the two code paths:

  • nodereadinessrule_controller.go's processAllNodesForRule (the RuleReconciler path) already clears FailedNodes inline on success, so it's fine as-is.
  • node_controller.go's processNodeAgainstAllRules (the NodeReconciler path) does not — it only records a failure on error and never clears it on success. Since rule there is now a deep-copied snapshot from ruleCache, a stale failure entry from an earlier reconcile keeps getting carried forward on every subsequent successful evaluation, so a recovered node stays stuck in status.failedNodes indefinitely.

Opened #333 as the separate follow-up you suggested, scoped to just that fix (added a clearNodeFailure helper mirroring recordNodeFailure, plus unit tests). Verified locally with go build, go vet, go test ./internal/controller/..., and golangci-lint run — all clean.

@vitorfloriano vitorfloriano mentioned this pull request Aug 8, 2026
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. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. 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.

[BUG] Data race and memory corruption in shared ruleCache under concurrent node reconciliations

2 participants