Skip to content

[BUG] Handle node deletion, label selector unmatching, and status drift in NodeReconciler #338

Open

Description

@bhuvan-somisetty

What happened?

When a node is deleted from the cluster, NodeReconciler.Reconcile gets a NotFound error from r.Get and silently swallows it via client.IgnoreNotFound(err). The deleted node is never removed from rule.Status.NodeEvaluations, AppliedNodes, or FailedNodes on any rule, and the node_readiness_nodes_by_state metric keeps counting it forever.

Separately, RuleReconciler.cleanupDeletedNodes only filters NodeEvaluations — it misses AppliedNodes and FailedNodes, so those two fields also go stale.

Two related points originally filed here are split out per this review:

Expected behavior

  • Deleting a node removes it from NodeEvaluations, AppliedNodes, and FailedNodes on every rule, and updates the metric.
  • cleanupDeletedNodes cleans up all three fields, not just NodeEvaluations.

Repro

  1. Create a NodeReadinessRule matching worker nodes.
  2. Confirm a node shows up in rule.Status.NodeEvaluations/AppliedNodes.
  3. kubectl delete node worker-1.
  4. worker-1 is still in the rule status and in /metrics.

Affected components

  • internal/controller/node_controller.go (Reconcile)
  • internal/controller/nodereadinessrule_controller.go (cleanupDeletedNodes)

Controller version / K8s version

main (v0.4.1+) / v1.30.0–v1.31.0

Activity

  1. changed the title [-]fix(controller): handle node deletion, label selector unmatching, and status drift in NodeReconciler[/-] [+][BUG] Handle node deletion, label selector unmatching, and status drift in NodeReconciler[/+] on Aug 2, 2026
  2. bhuvan-somisetty commented on Aug 2, 2026

    @bhuvan-somisetty
    ContributorAuthor

    /assign

  3. added 3 commits that reference this issue on Aug 2, 2026
    1128043
    6c6a68e
    9e9a1d1
  4. ajaysundark commented on Aug 3, 2026

    @ajaysundark
    Contributor
    1. We are looking to drop the per-node fields in rule.status soon so improving rule.Status.*Nodes is lower priority.

    2. Selector Unmatch Cleanup: When a node no longer matches a rule's nodeSelector, any readiness taint previously managed by that rule is removed from the node, and the node is removed from the rule's status.

    This was as designed originally. Because after the label is deleted, NRC cannot find the 'applicable rules' for this node any more:

    applicableRules := r.getApplicableRulesForNode(ctx, node)

    To solve this case, what is needed is to detect when a node "used to match" a rule but no longer matches it.

    BUT the node is present in rule.Status.NodeEvaluations

    controller relying on its status (for pre-existing match) to decide on the action is fragile and cannot be a reliable signal for it to act on.

    or currently has rule.Spec.Taint

    The alternative is for NodeReconciler to evaluate 'all rules' for all node updates, instead of just the matching rules, so if a node is not matched by label, but it had a managed taint, it will send patch to remove. But it is expensive especially with the status updates.

    If a user has a manual action to delete a matching label (possibly via a script), it feels like the taint removal can also be patched in the same script. So in reality, this doesnt feel a high-impact bug, besides NRC supports a dry-run feature to capture misconfiguration scenarios to avoid this kind of manual errors.

    Can we create a separate issue for this instead of clubbing it all together in a single issue?

  5. bhuvan-somisetty commented on Aug 3, 2026

    @bhuvan-somisetty
    ContributorAuthor

    Makes sense on all counts. Split the selector-unmatch part into #342 for its own design discussion, and dropped the AppliedNodes real-time sync from here too since #89 is moving that away anyway. #338/#339 are now just node deletion cleanup + making cleanupDeletedNodes cover AppliedNodes/FailedNodes, not just NodeEvaluations. Updated the PR to match.

  6. ajaysundark commented on Aug 9, 2026

    @ajaysundark
    Contributor

    #338/ #339 are now just node deletion cleanup + making cleanupDeletedNodes cover AppliedNodes/FailedNodes, not just NodeEvaluations. Updated the PR to match.

    Hi @bhuvan-somisetty can you rather clean up the description to be concise on what this is about? The verbose descriptions for a rather straightforward issue is overwhelming for the readers.

    AI tooling could be reducing maintainer toil, not add to them. When working with such tools, consider taking effort to 'process' the information, understand the issue and work with the community manually. In open-source, we like to work with humans in slack and issues! :)

  7. ajaysundark commented on Aug 9, 2026

    @ajaysundark
    Contributor

    cc @Priyankasaggu11929 we should consider adding a note for AI assisted contribution guidelines in our project.

  8. Priyankasaggu11929 commented on Aug 10, 2026

    @Priyankasaggu11929
    Member

    cc @Priyankasaggu11929 we should consider adding a note for AI assisted contribution guidelines in our project.

    I'll send a PR adding some discreet instructions.

    I am seeing the pattern all over the project now - AI generated PR/issues with AI generated description, continuing with AI generated comments. 😓 (another example - #376 (comment))
    Not helpful at all, to maintainers reviewing these changes.

  9. bhuvan-somisetty commented on Aug 10, 2026

    @bhuvan-somisetty
    ContributorAuthor

    Fair point, and taken to heart — trimmed the description above down to just what's needed to reproduce and fix it. Will keep future issues/PRs shorter and lean on discussion in comments (or slack) instead of front-loading everything into the description.

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions