kubernetes-sigs / kubernetes-sigs/node-readiness-controller

[BUG] taintsEqual can report different taint sets as equal, dropping Node update events

Open
#400 1 comment 0 reactions 1 assignee View on GitHub

@Ujjwal-Gowda is already working on this.

Since Aug 13, 2026.

Dominant language
Go
Stars
164
Forks
75
Avg merge
8d 23h
Merged PRs (30d)
13

Description

What happened:

taintsEqual in internal/controller/helper.go builds its lookup key by
concatenating Key and Effect:

aMap := make(map[string]corev1.Taint)
for _, taint := range a {
    key := taint.Key + string(taint.Effect)
    aMap[key] = taint
}

Two problems come out of that:

  1. Concatenation collides. "a" + PreferNoSchedule and "aPrefer" +
    NoSchedule both produce "aPreferNoSchedule". Both are valid taints, so
    two different taint sets compare equal.

  2. A map collapses repeats. Storing by key overwrites, so a slice holding
    the same key twice with different values compares equal to a slice holding
    that key twice with the same value.

Both cases pass the len(a) != len(b) guard, so they reach the map logic.

Why it matters:

taintsEqual is used by the Node UpdateFunc predicate in
internal/controller/node_controller.go:

taintsChanged := !taintsEqual(oldNode.Spec.Taints, newNode.Spec.Taints)
...
return conditionsChanged || taintsChanged || labelsChanged

A false "equal" means the predicate returns false and the update event is
dropped, so a node whose taints actually changed is never reconciled until
some unrelated event arrives.

How to reproduce it:

a := []corev1.Taint{{Key: "a", Value: "v", Effect: corev1.TaintEffectPreferNoSchedule}}
b := []corev1.Taint{{Key: "aPrefer", Value: "v", Effect: corev1.TaintEffectNoSchedule}}
taintsEqual(a, b) // true, want false

c := []corev1.Taint{
    {Key: "x", Value: "v1", Effect: corev1.TaintEffectNoSchedule},
    {Key: "x", Value: "v2", Effect: corev1.TaintEffectNoSchedule},
}
d := []corev1.Taint{
    {Key: "x", Value: "v2", Effect: corev1.TaintEffectNoSchedule},
    {Key: "x", Value: "v2", Effect: corev1.TaintEffectNoSchedule},
}
taintsEqual(c, d) // true, want false

What you expected to happen:

Taint slices that hold different taints compare as different, regardless of
how key and effect happen to concatenate.

Environment:

  • main (reproduced locally)

I have a fix and table-driven tests ready, keying the comparison on a struct
of key/value/effect and counting occurrences so repeats are compared as a
multiset. TimeAdded stays out of the comparison, as it is today. Happy to
open the PR, could I be assigned?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.