What happened?
When the validation webhook is enabled, it blocks creation of a dryRun: true rule whenever an existing enforcement rule already manages the same taint key on overlapping nodes — even though a dry-run rule never writes any taint to any node and therefore presents no actual conflict.
The inverse is also blocked: promoting an existing dry-run rule to enforcement by creating a new enforcement rule with the same taint key is rejected if a dry-run rule for that key already exists.
Root cause
validateTaintConflicts in nodereadinessgaterule_webhook.go iterates all existing rules and flags any pair sharing the same taint.key + taint.effect on overlapping node selectors. It does not check spec.dryRun on either side:
// existing code — no dryRun guard
if existingRule.Spec.Taint.Key == rule.Spec.Taint.Key &&
existingRule.Spec.Taint.Effect == rule.Spec.Taint.Effect {
if w.nodeSelectorsOverlap(...) {
allErrs = append(allErrs, field.Invalid(...))
}
}
Steps to reproduce
- Create an enforcement rule:
apiVersion: readiness.node.x-k8s.io/v1alpha1
kind: NodeReadinessRule
metadata:
name: enforcement-rule
spec:
enforcementMode: continuous
nodeSelector:
matchLabels:
node-role.kubernetes.io/worker: ""
conditions:
- type: Ready
requiredStatus: "True"
taint:
key: readiness.k8s.io/node-ready
effect: NoSchedule
- Attempt to create a dry-run preview rule for the same taint key (e.g. to evaluate a condition change):
apiVersion: readiness.node.x-k8s.io/v1alpha1
kind: NodeReadinessRule
metadata:
name: preview-rule
spec:
dryRun: true
enforcementMode: continuous
nodeSelector:
matchLabels:
node-role.kubernetes.io/worker: ""
conditions:
- type: DiskPressure
requiredStatus: "False"
taint:
key: readiness.k8s.io/node-ready
effect: NoSchedule
- The webhook rejects the request:
Error: admission webhook "vnodereadinessrule.readiness.node.x-k8s.io" denied the request:
validation failed: [spec.taint.key: Invalid value: "readiness.k8s.io/node-ready":
conflicts with existing rule 'enforcement-rule' ...]
Expected behavior
A dryRun: true rule must never be rejected for a taint key conflict because it does not apply, remove, or modify any taint. The conflict guard exists to prevent two enforcement rules from fighting over the same taint; that concern does not apply to dry-run rules.
Impact
This makes the primary dryRun use case — previewing the impact of a rule against a taint key already in use — impossible when the webhook is enabled.
Controller version / image tag
Reproduced on main at e259c3f.
Kubernetes version
Not version-specific; this is webhook validation logic.
What happened?
When the validation webhook is enabled, it blocks creation of a
dryRun: truerule whenever an existing enforcement rule already manages the same taint key on overlapping nodes — even though a dry-run rule never writes any taint to any node and therefore presents no actual conflict.The inverse is also blocked: promoting an existing dry-run rule to enforcement by creating a new enforcement rule with the same taint key is rejected if a dry-run rule for that key already exists.
Root cause
validateTaintConflictsinnodereadinessgaterule_webhook.goiterates all existing rules and flags any pair sharing the sametaint.key+taint.effecton overlapping node selectors. It does not checkspec.dryRunon either side:Steps to reproduce
Expected behavior
A
dryRun: truerule must never be rejected for a taint key conflict because it does not apply, remove, or modify any taint. The conflict guard exists to prevent two enforcement rules from fighting over the same taint; that concern does not apply to dry-run rules.Impact
This makes the primary
dryRunuse case — previewing the impact of a rule against a taint key already in use — impossible when the webhook is enabled.Controller version / image tag
Reproduced on
mainate259c3f.Kubernetes version
Not version-specific; this is webhook validation logic.