Skip to content

Commit ba6a4d6

Browse files
committed
Fix
1 parent b5bb6e8 commit ba6a4d6

File tree

8 files changed

+95
-24
lines changed

8 files changed

+95
-24
lines changed

README.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ spec:
5151
- type: "example.com/CNIReady"
5252
requiredStatus: "True"
5353
taint:
54-
key: "readiness.k8s.io/network/not-ready"
54+
key: "readiness.k8s.io/example.com/network-not-ready"
5555
effect: "NoSchedule"
5656
value: "pending"
5757
enforcementMode: "bootstrap-only"
@@ -64,16 +64,18 @@ Find a more detailed walkthrough of setting up Node Readiness Controller in your
6464
6565
### Taint Key Conventions
6666
67-
- Reserved core prefixes are not allowed for user rules (except the controller-owned `readiness.k8s.io/network/not-ready` and `readiness.k8s.io/storage/not-ready`):
68-
- readiness.k8s.io/system/*
69-
- readiness.k8s.io/core/*
70-
- readiness.k8s.io/node/*
71-
- readiness.k8s.io/device/*
72-
- readiness.k8s.io/network/* (except readiness.k8s.io/network/not-ready)
73-
- readiness.k8s.io/storage/* (except readiness.k8s.io/storage/not-ready)
74-
- Use user-space keys under readiness.k8s.io/* with a DNS-style component, for example:
75-
- readiness.k8s.io/network/not-ready
76-
- readiness.k8s.io/storage/not-ready
67+
All taint keys must use the `readiness.k8s.io/` prefix. The following core prefixes are reserved and not allowed for user rules:
68+
- `readiness.k8s.io/system/*`
69+
- `readiness.k8s.io/core/*`
70+
- `readiness.k8s.io/node/*`
71+
- `readiness.k8s.io/device/*`
72+
- `readiness.k8s.io/network/*`
73+
- `readiness.k8s.io/storage/*`
74+
75+
Use user-space keys under `readiness.k8s.io/*` with a DNS-style component to avoid conflicts, for example:
76+
- `readiness.k8s.io/example.com/network-not-ready`
77+
- `readiness.k8s.io/projectcalico.org/cni-ready`
78+
- `readiness.k8s.io/vendor.io/storage-driver-ready`
7779

7880
## High-level Roadmap
7981

api/v1alpha1/nodereadinessrule_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ type NodeReadinessRuleSpec struct {
7979
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/core/')",message="reserved taint prefix 'readiness.k8s.io/core/*' is not allowed"
8080
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/node/')",message="reserved taint prefix 'readiness.k8s.io/node/*' is not allowed"
8181
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/device/')",message="reserved taint prefix 'readiness.k8s.io/device/*' is not allowed"
82-
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/network/') || self.key == 'readiness.k8s.io/network/not-ready'",message="reserved taint prefix 'readiness.k8s.io/network/*' is not allowed except 'readiness.k8s.io/network/not-ready'"
83-
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/storage/') || self.key == 'readiness.k8s.io/storage/not-ready'",message="reserved taint prefix 'readiness.k8s.io/storage/*' is not allowed except 'readiness.k8s.io/storage/not-ready'"
82+
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/network/')",message="reserved taint prefix 'readiness.k8s.io/network/*' is not allowed"
83+
// +kubebuilder:validation:XValidation:rule="!self.key.startsWith('readiness.k8s.io/storage/')",message="reserved taint prefix 'readiness.k8s.io/storage/*' is not allowed"
8484
// +kubebuilder:validation:XValidation:rule="self.key.size() <= 253",message="taint key length must be at most 253 characters"
8585
// +kubebuilder:validation:XValidation:rule="!has(self.value) || self.value.size() <= 63",message="taint value length must be at most 63 characters"
8686
// +kubebuilder:validation:XValidation:rule="self.effect in ['NoSchedule', 'PreferNoSchedule', 'NoExecute']",message="taint effect must be one of 'NoSchedule', 'PreferNoSchedule', 'NoExecute'"

config/samples/v1alpha1_nodereadinessrule.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ spec:
1010
- type: "network.kubernetes.io/CNIReady"
1111
requiredStatus: "True"
1212
taint:
13-
key: "readiness.k8s.io/network/not-ready"
13+
key: "readiness.k8s.io/example.com/network-not-ready"
1414
effect: "NoSchedule"
1515
value: "pending"
1616
enforcementMode: "bootstrap-only"

docs/book/src/user-guide/concepts.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ Reserved core prefixes (not allowed for user rules):
2727
- `readiness.k8s.io/core/*`
2828
- `readiness.k8s.io/node/*`
2929
- `readiness.k8s.io/device/*`
30-
- `readiness.k8s.io/network/*` (except `readiness.k8s.io/network/not-ready`)
31-
- `readiness.k8s.io/storage/*` (except `readiness.k8s.io/storage/not-ready`)
30+
- `readiness.k8s.io/network/*`
31+
- `readiness.k8s.io/storage/*`
3232

33-
Use vendor/user-space paths under `readiness.k8s.io/*` that include a DNS-style component to avoid conflicts.
33+
Use vendor/user-space paths under `readiness.k8s.io/*` that include a DNS-style component to avoid conflicts, for example:
34+
- `readiness.k8s.io/example.com/my-component`
35+
- `readiness.k8s.io/projectcalico.org/network-not-ready`
36+
- `readiness.k8s.io/vendor.io/storage-driver-ready`
3437

3538
The segment after `readiness.k8s.io/` should describe the dependency or subsystem whose readiness is being guarded (for example, a CNI plugin, storage backend, or security agent). Treat this domain as reserved for the controller and closely related components, and avoid reusing it for unrelated taints.
3639

examples/cni-readiness/network-readiness-dryrun-rule.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ spec:
88
- type: "projectcalico.org/CalicoReady"
99
requiredStatus: "True"
1010
taint:
11-
key: "readiness.k8s.io/network/not-ready"
11+
key: "readiness.k8s.io/projectcalico.org/network-not-ready"
1212
effect: "NoSchedule"
1313
value: "pending"
1414
enforcementMode: "bootstrap-only"

examples/cni-readiness/network-readiness-rule.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ spec:
77
- type: "projectcalico.org/CalicoReady"
88
requiredStatus: "True"
99
taint:
10-
key: "readiness.k8s.io/network/not-ready"
10+
key: "readiness.k8s.io/projectcalico.org/network-not-ready"
1111
effect: "NoSchedule"
1212
value: "pending"
1313
enforcementMode: "continuous"

internal/webhook/nodereadinessgaterule_webhook.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ func (w *NodeReadinessRuleWebhook) validateSpec(spec readinessv1alpha1.NodeReadi
111111
}
112112
for _, p := range reserved {
113113
if strings.HasPrefix(spec.Taint.Key, p) {
114-
if (p == "readiness.k8s.io/network/" && spec.Taint.Key == "readiness.k8s.io/network/not-ready") ||
115-
(p == "readiness.k8s.io/storage/" && spec.Taint.Key == "readiness.k8s.io/storage/not-ready") {
116-
continue
117-
}
118114
allErrs = append(allErrs, field.Invalid(taintField.Child("key"), spec.Taint.Key, fmt.Sprintf("reserved taint prefix '%s*' is not allowed", p)))
119115
break
120116
}

internal/webhook/nodereadinessgaterule_webhook_test.go

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ var _ = Describe("NodeReadinessRule Validation Webhook", func() {
636636
})
637637

638638
Context("Reserved Prefix Validation", func() {
639-
It("should reject reserved readiness.k8s.io core prefixes", func() {
639+
It("should reject all reserved readiness.k8s.io core prefixes", func() {
640640
reservedKeys := []string{
641641
"readiness.k8s.io/system/foo",
642642
"readiness.k8s.io/core/bar",
@@ -668,6 +668,76 @@ var _ = Describe("NodeReadinessRule Validation Webhook", func() {
668668
Expect(allErrs[0].Field).To(Equal("spec.taint.key"))
669669
}
670670
})
671+
672+
It("should reject readiness.k8s.io/network/not-ready", func() {
673+
rule := &readinessv1alpha1.NodeReadinessRule{
674+
Spec: readinessv1alpha1.NodeReadinessRuleSpec{
675+
Conditions: []readinessv1alpha1.ConditionRequirement{
676+
{Type: "Ready", RequiredStatus: corev1.ConditionTrue},
677+
},
678+
NodeSelector: metav1.LabelSelector{
679+
MatchLabels: map[string]string{
680+
"node-role.kubernetes.io/worker": "",
681+
},
682+
},
683+
Taint: corev1.Taint{
684+
Key: "readiness.k8s.io/network/not-ready",
685+
Effect: corev1.TaintEffectNoSchedule,
686+
},
687+
EnforcementMode: readinessv1alpha1.EnforcementModeBootstrapOnly,
688+
},
689+
}
690+
allErrs := webhook.validateSpec(rule.Spec)
691+
Expect(allErrs).NotTo(BeEmpty())
692+
Expect(allErrs[0].Field).To(Equal("spec.taint.key"))
693+
Expect(allErrs[0].Detail).To(ContainSubstring("reserved taint prefix 'readiness.k8s.io/network/*' is not allowed"))
694+
})
695+
696+
It("should reject readiness.k8s.io/storage/not-ready", func() {
697+
rule := &readinessv1alpha1.NodeReadinessRule{
698+
Spec: readinessv1alpha1.NodeReadinessRuleSpec{
699+
Conditions: []readinessv1alpha1.ConditionRequirement{
700+
{Type: "Ready", RequiredStatus: corev1.ConditionTrue},
701+
},
702+
NodeSelector: metav1.LabelSelector{
703+
MatchLabels: map[string]string{
704+
"node-role.kubernetes.io/worker": "",
705+
},
706+
},
707+
Taint: corev1.Taint{
708+
Key: "readiness.k8s.io/storage/not-ready",
709+
Effect: corev1.TaintEffectNoSchedule,
710+
},
711+
EnforcementMode: readinessv1alpha1.EnforcementModeBootstrapOnly,
712+
},
713+
}
714+
allErrs := webhook.validateSpec(rule.Spec)
715+
Expect(allErrs).NotTo(BeEmpty())
716+
Expect(allErrs[0].Field).To(Equal("spec.taint.key"))
717+
Expect(allErrs[0].Detail).To(ContainSubstring("reserved taint prefix 'readiness.k8s.io/storage/*' is not allowed"))
718+
})
719+
720+
It("should allow user-space keys under readiness.k8s.io", func() {
721+
rule := &readinessv1alpha1.NodeReadinessRule{
722+
Spec: readinessv1alpha1.NodeReadinessRuleSpec{
723+
Conditions: []readinessv1alpha1.ConditionRequirement{
724+
{Type: "Ready", RequiredStatus: corev1.ConditionTrue},
725+
},
726+
NodeSelector: metav1.LabelSelector{
727+
MatchLabels: map[string]string{
728+
"node-role.kubernetes.io/worker": "",
729+
},
730+
},
731+
Taint: corev1.Taint{
732+
Key: "readiness.k8s.io/example.com/my-component",
733+
Effect: corev1.TaintEffectNoSchedule,
734+
},
735+
EnforcementMode: readinessv1alpha1.EnforcementModeBootstrapOnly,
736+
},
737+
}
738+
allErrs := webhook.validateSpec(rule.Spec)
739+
Expect(allErrs).To(BeEmpty())
740+
})
671741
})
672742

673743
Context("Full Validation Integration", func() {

0 commit comments

Comments
 (0)