move TaintToleration predicate to its plugin

This commit is contained in:
Abdullah Gharaibeh
2020-01-08 16:43:26 -05:00
parent 9db337be05
commit 50b697bacb
8 changed files with 30 additions and 260 deletions

View File

@@ -33,8 +33,6 @@ var (
// ErrNodeSelectorNotMatch is used for MatchNodeSelector predicate error.
ErrNodeSelectorNotMatch = NewPredicateFailureError("MatchNodeSelector", "node(s) didn't match node selector")
// ErrTaintsTolerationsNotMatch is used for PodToleratesNodeTaints predicate error.
ErrTaintsTolerationsNotMatch = NewPredicateFailureError("PodToleratesNodeTaints", "node(s) had taints that the pod didn't tolerate")
// ErrPodNotMatchHostName is used for HostName predicate error.
ErrPodNotMatchHostName = NewPredicateFailureError("HostName", "node(s) didn't match the requested hostname")
// ErrPodNotFitsHostPorts is used for PodFitsHostPorts predicate error.
@@ -63,9 +61,8 @@ var (
)
var unresolvablePredicateFailureErrors = map[PredicateFailureReason]struct{}{
ErrNodeSelectorNotMatch: {},
ErrPodNotMatchHostName: {},
ErrTaintsTolerationsNotMatch: {},
ErrNodeSelectorNotMatch: {},
ErrPodNotMatchHostName: {},
// Node conditions won't change when scheduler simulates removal of preemption victims.
// So, it is pointless to try nodes that have not been able to host the pod due to node
// conditions. These include ErrNodeNotReady, ErrNodeUnderPIDPressure, ErrNodeUnderMemoryPressure, ....

View File

@@ -52,8 +52,6 @@ const (
PodToleratesNodeTaintsPred = "PodToleratesNodeTaints"
// CheckNodeUnschedulablePred defines the name of predicate CheckNodeUnschedulablePredicate.
CheckNodeUnschedulablePred = "CheckNodeUnschedulable"
// PodToleratesNodeNoExecuteTaintsPred defines the name of predicate PodToleratesNodeNoExecuteTaints.
PodToleratesNodeNoExecuteTaintsPred = "PodToleratesNodeNoExecuteTaints"
// CheckNodeLabelPresencePred defines the name of predicate CheckNodeLabelPresence.
CheckNodeLabelPresencePred = "CheckNodeLabelPresence"
// CheckServiceAffinityPred defines the name of predicate checkServiceAffinity.
@@ -102,7 +100,7 @@ var (
predicatesOrdering = []string{CheckNodeUnschedulablePred,
GeneralPred, HostNamePred, PodFitsHostPortsPred,
MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred,
PodToleratesNodeTaintsPred, PodToleratesNodeNoExecuteTaintsPred, CheckNodeLabelPresencePred,
PodToleratesNodeTaintsPred, CheckNodeLabelPresencePred,
CheckServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred, MaxCSIVolumeCountPred,
MaxAzureDiskVolumeCountPred, MaxCinderVolumeCountPred, CheckVolumeBindingPred, NoVolumeZoneConflictPred,
EvenPodsSpreadPred, MatchInterPodAffinityPred}
@@ -306,34 +304,3 @@ func GeneralPredicates(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.N
return len(predicateFails) == 0, predicateFails, nil
}
// PodToleratesNodeTaints checks if a pod tolerations can tolerate the node taints.
func PodToleratesNodeTaints(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) {
if nodeInfo == nil || nodeInfo.Node() == nil {
return false, []PredicateFailureReason{ErrNodeUnknownCondition}, nil
}
return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool {
// PodToleratesNodeTaints is only interested in NoSchedule and NoExecute taints.
return t.Effect == v1.TaintEffectNoSchedule || t.Effect == v1.TaintEffectNoExecute
})
}
// PodToleratesNodeNoExecuteTaints checks if a pod tolerations can tolerate the node's NoExecute taints.
func PodToleratesNodeNoExecuteTaints(pod *v1.Pod, meta Metadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) {
return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool {
return t.Effect == v1.TaintEffectNoExecute
})
}
func podToleratesNodeTaints(pod *v1.Pod, nodeInfo *schedulernodeinfo.NodeInfo, filter func(t *v1.Taint) bool) (bool, []PredicateFailureReason, error) {
taints, err := nodeInfo.Taints()
if err != nil {
return false, nil, err
}
if v1helper.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, filter) {
return true, nil, nil
}
return false, []PredicateFailureReason{ErrTaintsTolerationsNotMatch}, nil
}

View File

@@ -1515,206 +1515,3 @@ func TestRunGeneralPredicates(t *testing.T) {
})
}
}
func TestPodToleratesTaints(t *testing.T) {
podTolerateTaintsTests := []struct {
pod *v1.Pod
node v1.Node
fits bool
name string
}{
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod0",
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}},
},
},
fits: false,
name: "A pod having no tolerations can't be scheduled onto a node with nonempty taints",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod1",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod1:V1"}},
Tolerations: []v1.Toleration{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}},
},
},
fits: true,
name: "A pod which can be scheduled on a dedicated node assigned to user1 with effect NoSchedule",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{{Key: "dedicated", Operator: "Equal", Value: "user2", Effect: "NoSchedule"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}},
},
},
fits: false,
name: "A pod which can't be scheduled on a dedicated node assigned to user2 with effect NoSchedule",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{{Key: "foo", Operator: "Exists", Effect: "NoSchedule"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}},
},
},
fits: true,
name: "A pod can be scheduled onto the node, with a toleration uses operator Exists that tolerates the taints on the node",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{
{Key: "dedicated", Operator: "Equal", Value: "user2", Effect: "NoSchedule"},
{Key: "foo", Operator: "Exists", Effect: "NoSchedule"},
},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{Key: "dedicated", Value: "user2", Effect: "NoSchedule"},
{Key: "foo", Value: "bar", Effect: "NoSchedule"},
},
},
},
fits: true,
name: "A pod has multiple tolerations, node has multiple taints, all the taints are tolerated, pod can be scheduled onto the node",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "PreferNoSchedule"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{Key: "foo", Value: "bar", Effect: "NoSchedule"},
},
},
},
fits: false,
name: "A pod has a toleration that keys and values match the taint on the node, but (non-empty) effect doesn't match, " +
"can't be scheduled onto the node",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{{Key: "foo", Operator: "Equal", Value: "bar"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{Key: "foo", Value: "bar", Effect: "NoSchedule"},
},
},
},
fits: true,
name: "The pod has a toleration that keys and values match the taint on the node, the effect of toleration is empty, " +
"and the effect of taint is NoSchedule. Pod can be scheduled onto the node",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
Tolerations: []v1.Toleration{{Key: "dedicated", Operator: "Equal", Value: "user2", Effect: "NoSchedule"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{Key: "dedicated", Value: "user1", Effect: "PreferNoSchedule"},
},
},
},
fits: true,
name: "The pod has a toleration that key and value don't match the taint on the node, " +
"but the effect of taint on node is PreferNochedule. Pod can be scheduled onto the node",
},
{
pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod2",
},
Spec: v1.PodSpec{
Containers: []v1.Container{{Image: "pod2:V1"}},
},
},
node: v1.Node{
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{Key: "dedicated", Value: "user1", Effect: "PreferNoSchedule"},
},
},
},
fits: true,
name: "The pod has no toleration, " +
"but the effect of taint on node is PreferNochedule. Pod can be scheduled onto the node",
},
}
expectedFailureReasons := []PredicateFailureReason{ErrTaintsTolerationsNotMatch}
for _, test := range podTolerateTaintsTests {
t.Run(test.name, func(t *testing.T) {
nodeInfo := schedulernodeinfo.NewNodeInfo()
nodeInfo.SetNode(&test.node)
fits, reasons, err := PodToleratesNodeTaints(test.pod, nil, nodeInfo)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) {
t.Errorf("unexpected failure reason: %v, want: %v", reasons, expectedFailureReasons)
}
if fits != test.fits {
t.Errorf("expected: %v got %v", test.fits, fits)
}
})
}
}