Skip to content

Commit dd48aad

Browse files
Allow filtering node resources on taint. (#1840)
* allow filtering node resources on taint
1 parent c5dc2a1 commit dd48aad

12 files changed

+368
-2
lines changed

config/crds/troubleshoot.sh_analyzers.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,34 @@ spec:
12821282
type: string
12831283
type: object
12841284
type: object
1285+
taint:
1286+
description: |-
1287+
The node this Taint is attached to has the "effect" on
1288+
any pod that does not tolerate the Taint.
1289+
properties:
1290+
effect:
1291+
description: |-
1292+
Required. The effect of the taint on pods
1293+
that do not tolerate the taint.
1294+
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
1295+
type: string
1296+
key:
1297+
description: Required. The taint key to be applied
1298+
to a node.
1299+
type: string
1300+
timeAdded:
1301+
description: TimeAdded represents the time at which
1302+
the taint was added.
1303+
format: date-time
1304+
type: string
1305+
value:
1306+
description: The taint value corresponding to the
1307+
taint key.
1308+
type: string
1309+
required:
1310+
- effect
1311+
- key
1312+
type: object
12851313
type: object
12861314
outcomes:
12871315
items:

config/crds/troubleshoot.sh_preflights.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,34 @@ spec:
12821282
type: string
12831283
type: object
12841284
type: object
1285+
taint:
1286+
description: |-
1287+
The node this Taint is attached to has the "effect" on
1288+
any pod that does not tolerate the Taint.
1289+
properties:
1290+
effect:
1291+
description: |-
1292+
Required. The effect of the taint on pods
1293+
that do not tolerate the taint.
1294+
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
1295+
type: string
1296+
key:
1297+
description: Required. The taint key to be applied
1298+
to a node.
1299+
type: string
1300+
timeAdded:
1301+
description: TimeAdded represents the time at which
1302+
the taint was added.
1303+
format: date-time
1304+
type: string
1305+
value:
1306+
description: The taint value corresponding to the
1307+
taint key.
1308+
type: string
1309+
required:
1310+
- effect
1311+
- key
1312+
type: object
12851313
type: object
12861314
outcomes:
12871315
items:

config/crds/troubleshoot.sh_supportbundles.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,34 @@ spec:
13131313
type: string
13141314
type: object
13151315
type: object
1316+
taint:
1317+
description: |-
1318+
The node this Taint is attached to has the "effect" on
1319+
any pod that does not tolerate the Taint.
1320+
properties:
1321+
effect:
1322+
description: |-
1323+
Required. The effect of the taint on pods
1324+
that do not tolerate the taint.
1325+
Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
1326+
type: string
1327+
key:
1328+
description: Required. The taint key to be applied
1329+
to a node.
1330+
type: string
1331+
timeAdded:
1332+
description: TimeAdded represents the time at which
1333+
the taint was added.
1334+
format: date-time
1335+
type: string
1336+
value:
1337+
description: The taint value corresponding to the
1338+
taint key.
1339+
type: string
1340+
required:
1341+
- effect
1342+
- key
1343+
type: object
13161344
type: object
13171345
outcomes:
13181346
items:

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ require (
5555
k8s.io/cli-runtime v0.34.0
5656
k8s.io/client-go v0.34.0
5757
k8s.io/klog/v2 v2.130.1
58+
k8s.io/kubernetes v1.33.4
5859
oras.land/oras-go v1.2.6
5960
sigs.k8s.io/controller-runtime v0.22.0
6061
sigs.k8s.io/e2e-framework v0.6.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,6 +2261,8 @@ k8s.io/kubectl v0.33.3 h1:r/phHvH1iU7gO/l7tTjQk2K01ER7/OAJi8uFHHyWSac=
22612261
k8s.io/kubectl v0.33.3/go.mod h1:euj2bG56L6kUGOE/ckZbCoudPwuj4Kud7BR0GzyNiT0=
22622262
k8s.io/kubelet v0.34.0 h1:1nZt1Q6Kfx7xCaTS9vnqR9sjZDxf3cRSQkAFCczULmc=
22632263
k8s.io/kubelet v0.34.0/go.mod h1:NqbF8ViVettlZbf9hw9DJhubaWn7rGvDDTcLMDm6tQ0=
2264+
k8s.io/kubernetes v1.33.4 h1:T1d5FLUYm3/KyUeV7YJhKTR980zHCHb7K2xhCSo3lE8=
2265+
k8s.io/kubernetes v1.33.4/go.mod h1:nrt8sldmckKz2fCZhgRX3SKfS2e+CzXATPv6ITNkU00=
22642266
k8s.io/metrics v0.34.0 h1:nYSfG2+tnL6/MRC2I+sGHjtNEGoEoM/KktgGOoQFwws=
22652267
k8s.io/metrics v0.34.0/go.mod h1:KCuXmotE0v4AvoARKUP8NC4lUnbK/Du1mluGdor5h4M=
22662268
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=

pkg/analyze/node_resources.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"k8s.io/apimachinery/pkg/api/resource"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414
"k8s.io/apimachinery/pkg/labels"
15+
"k8s.io/kubernetes/pkg/util/taints"
1516

1617
"github.com/replicatedhq/troubleshoot/internal/util"
1718
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
@@ -451,6 +452,10 @@ func nodeMatchesFilters(node corev1.Node, filters *troubleshootv1beta2.NodeResou
451452
}
452453
}
453454

455+
if filters.Taint != nil {
456+
return taints.TaintExists(node.Spec.Taints, filters.Taint), nil
457+
}
458+
454459
if filters.CPUArchitecture != "" {
455460
parsed := filters.CPUArchitecture
456461

pkg/analyze/node_resources_test.go

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,191 @@ func Test_nodeMatchesFilters(t *testing.T) {
702702
},
703703
expectResult: false,
704704
},
705+
{
706+
name: "true when taint exists",
707+
node: corev1.Node{
708+
Spec: corev1.NodeSpec{
709+
Taints: []corev1.Taint{
710+
{
711+
Key: "node.kubernetes.io/not-ready",
712+
Value: "",
713+
Effect: corev1.TaintEffectNoSchedule,
714+
},
715+
},
716+
},
717+
},
718+
filters: &troubleshootv1beta2.NodeResourceFilters{
719+
Taint: &corev1.Taint{
720+
Key: "node.kubernetes.io/not-ready",
721+
Effect: corev1.TaintEffectNoSchedule,
722+
},
723+
},
724+
expectResult: true,
725+
},
726+
{
727+
name: "true when taint exists with value match",
728+
node: corev1.Node{
729+
Spec: corev1.NodeSpec{
730+
Taints: []corev1.Taint{
731+
{
732+
Key: "dedicated",
733+
Value: "gpu",
734+
Effect: corev1.TaintEffectNoSchedule,
735+
},
736+
},
737+
},
738+
},
739+
filters: &troubleshootv1beta2.NodeResourceFilters{
740+
Taint: &corev1.Taint{
741+
Key: "dedicated",
742+
Value: "gpu",
743+
Effect: corev1.TaintEffectNoSchedule,
744+
},
745+
},
746+
expectResult: true,
747+
},
748+
{
749+
name: "false when taint key does not exist",
750+
node: corev1.Node{
751+
Spec: corev1.NodeSpec{
752+
Taints: []corev1.Taint{
753+
{
754+
Key: "node.kubernetes.io/not-ready",
755+
Value: "",
756+
Effect: corev1.TaintEffectNoSchedule,
757+
},
758+
},
759+
},
760+
},
761+
filters: &troubleshootv1beta2.NodeResourceFilters{
762+
Taint: &corev1.Taint{
763+
Key: "different-key",
764+
Effect: corev1.TaintEffectNoSchedule,
765+
},
766+
},
767+
expectResult: false,
768+
},
769+
{
770+
name: "false when taint effect does not match",
771+
node: corev1.Node{
772+
Spec: corev1.NodeSpec{
773+
Taints: []corev1.Taint{
774+
{
775+
Key: "node.kubernetes.io/not-ready",
776+
Value: "",
777+
Effect: corev1.TaintEffectNoSchedule,
778+
},
779+
},
780+
},
781+
},
782+
filters: &troubleshootv1beta2.NodeResourceFilters{
783+
Taint: &corev1.Taint{
784+
Key: "node.kubernetes.io/not-ready",
785+
Effect: corev1.TaintEffectNoExecute,
786+
},
787+
},
788+
expectResult: false,
789+
},
790+
{
791+
name: "true when taint value does not match but key and effect do (TaintExists only matches key and effect)",
792+
node: corev1.Node{
793+
Spec: corev1.NodeSpec{
794+
Taints: []corev1.Taint{
795+
{
796+
Key: "dedicated",
797+
Value: "gpu",
798+
Effect: corev1.TaintEffectNoSchedule,
799+
},
800+
},
801+
},
802+
},
803+
filters: &troubleshootv1beta2.NodeResourceFilters{
804+
Taint: &corev1.Taint{
805+
Key: "dedicated",
806+
Value: "cpu",
807+
Effect: corev1.TaintEffectNoSchedule,
808+
},
809+
},
810+
expectResult: true,
811+
},
812+
{
813+
name: "true when node has multiple taints and filter matches one",
814+
node: corev1.Node{
815+
Spec: corev1.NodeSpec{
816+
Taints: []corev1.Taint{
817+
{
818+
Key: "node.kubernetes.io/not-ready",
819+
Value: "",
820+
Effect: corev1.TaintEffectNoSchedule,
821+
},
822+
{
823+
Key: "dedicated",
824+
Value: "gpu",
825+
Effect: corev1.TaintEffectNoSchedule,
826+
},
827+
{
828+
Key: "example.com/special-hardware",
829+
Value: "true",
830+
Effect: corev1.TaintEffectNoExecute,
831+
},
832+
},
833+
},
834+
},
835+
filters: &troubleshootv1beta2.NodeResourceFilters{
836+
Taint: &corev1.Taint{
837+
Key: "dedicated",
838+
Value: "gpu",
839+
Effect: corev1.TaintEffectNoSchedule,
840+
},
841+
},
842+
expectResult: true,
843+
},
844+
{
845+
name: "true when node has no taints but no taint filter is specified",
846+
node: corev1.Node{
847+
Spec: corev1.NodeSpec{
848+
Taints: []corev1.Taint{},
849+
},
850+
},
851+
filters: &troubleshootv1beta2.NodeResourceFilters{},
852+
expectResult: true,
853+
},
854+
{
855+
name: "false when node has no taints but taint filter is specified",
856+
node: corev1.Node{
857+
Spec: corev1.NodeSpec{
858+
Taints: []corev1.Taint{},
859+
},
860+
},
861+
filters: &troubleshootv1beta2.NodeResourceFilters{
862+
Taint: &corev1.Taint{
863+
Key: "node.kubernetes.io/not-ready",
864+
Effect: corev1.TaintEffectNoSchedule,
865+
},
866+
},
867+
expectResult: false,
868+
},
869+
{
870+
name: "true when matching taint with PreferNoSchedule effect",
871+
node: corev1.Node{
872+
Spec: corev1.NodeSpec{
873+
Taints: []corev1.Taint{
874+
{
875+
Key: "node.kubernetes.io/memory-pressure",
876+
Value: "",
877+
Effect: corev1.TaintEffectPreferNoSchedule,
878+
},
879+
},
880+
},
881+
},
882+
filters: &troubleshootv1beta2.NodeResourceFilters{
883+
Taint: &corev1.Taint{
884+
Key: "node.kubernetes.io/memory-pressure",
885+
Effect: corev1.TaintEffectPreferNoSchedule,
886+
},
887+
},
888+
expectResult: true,
889+
},
705890
}
706891

707892
for _, test := range tests {

pkg/apis/troubleshoot/v1beta2/analyzer_shared.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package v1beta2
22

33
import (
4+
corev1 "k8s.io/api/core/v1"
45
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
56

67
"github.com/replicatedhq/troubleshoot/pkg/multitype"
@@ -142,6 +143,7 @@ type NodeResourceFilters struct {
142143
ResourceName string `json:"resourceName,omitempty" yaml:"resourceName,omitempty"`
143144
ResourceAllocatable string `json:"resourceAllocatable,omitempty" yaml:"resourceAllocatable,omitempty"`
144145
ResourceCapacity string `json:"resourceCapacity,omitempty" yaml:"resourceCapacity,omitempty"`
146+
Taint *corev1.Taint `json:"taint,omitempty" yaml:"taint,omitempty"`
145147
}
146148

147149
type NodeResourceSelectors struct {

pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go

Lines changed: 8 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)