kubernetes-sigs / kubernetes-sigs/node-readiness-controller
[BUG] taintsEqual can report different taint sets as equal, dropping Node update events
@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:
-
Concatenation collides.
"a"+PreferNoScheduleand"aPrefer"+
NoScheduleboth produce"aPreferNoSchedule". Both are valid taints, so
two different taint sets compare equal. -
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.