Commit a724a0fc authored by Gavin's avatar Gavin

Add specific errors for pod affinity predicates

parent 24ad0d21
...@@ -30,24 +30,27 @@ var ( ...@@ -30,24 +30,27 @@ var (
// be made to pass by removing pods, or you change an existing predicate so that // be made to pass by removing pods, or you change an existing predicate so that
// it can never be made to pass by removing pods, you need to add the predicate // it can never be made to pass by removing pods, you need to add the predicate
// failure error in nodesWherePreemptionMightHelp() in scheduler/core/generic_scheduler.go // failure error in nodesWherePreemptionMightHelp() in scheduler/core/generic_scheduler.go
ErrDiskConflict = newPredicateFailureError("NoDiskConflict") ErrDiskConflict = newPredicateFailureError("NoDiskConflict")
ErrVolumeZoneConflict = newPredicateFailureError("NoVolumeZoneConflict") ErrVolumeZoneConflict = newPredicateFailureError("NoVolumeZoneConflict")
ErrNodeSelectorNotMatch = newPredicateFailureError("MatchNodeSelector") ErrNodeSelectorNotMatch = newPredicateFailureError("MatchNodeSelector")
ErrPodAffinityNotMatch = newPredicateFailureError("MatchInterPodAffinity") ErrPodAffinityNotMatch = newPredicateFailureError("MatchInterPodAffinity")
ErrTaintsTolerationsNotMatch = newPredicateFailureError("PodToleratesNodeTaints") ErrPodAffinityRulesNotMatch = newPredicateFailureError("PodAffinityRulesNotMatch")
ErrPodNotMatchHostName = newPredicateFailureError("HostName") ErrPodAntiAffinityRulesNotMatch = newPredicateFailureError("PodAntiAffinityRulesNotMatch")
ErrPodNotFitsHostPorts = newPredicateFailureError("PodFitsHostPorts") ErrExistingPodsAntiAffinityRulesNotMatch = newPredicateFailureError("ExistingPodsAntiAffinityRulesNotMatch")
ErrNodeLabelPresenceViolated = newPredicateFailureError("CheckNodeLabelPresence") ErrTaintsTolerationsNotMatch = newPredicateFailureError("PodToleratesNodeTaints")
ErrServiceAffinityViolated = newPredicateFailureError("CheckServiceAffinity") ErrPodNotMatchHostName = newPredicateFailureError("HostName")
ErrMaxVolumeCountExceeded = newPredicateFailureError("MaxVolumeCount") ErrPodNotFitsHostPorts = newPredicateFailureError("PodFitsHostPorts")
ErrNodeUnderMemoryPressure = newPredicateFailureError("NodeUnderMemoryPressure") ErrNodeLabelPresenceViolated = newPredicateFailureError("CheckNodeLabelPresence")
ErrNodeUnderDiskPressure = newPredicateFailureError("NodeUnderDiskPressure") ErrServiceAffinityViolated = newPredicateFailureError("CheckServiceAffinity")
ErrNodeOutOfDisk = newPredicateFailureError("NodeOutOfDisk") ErrMaxVolumeCountExceeded = newPredicateFailureError("MaxVolumeCount")
ErrNodeNotReady = newPredicateFailureError("NodeNotReady") ErrNodeUnderMemoryPressure = newPredicateFailureError("NodeUnderMemoryPressure")
ErrNodeNetworkUnavailable = newPredicateFailureError("NodeNetworkUnavailable") ErrNodeUnderDiskPressure = newPredicateFailureError("NodeUnderDiskPressure")
ErrNodeUnschedulable = newPredicateFailureError("NodeUnschedulable") ErrNodeOutOfDisk = newPredicateFailureError("NodeOutOfDisk")
ErrNodeUnknownCondition = newPredicateFailureError("NodeUnknownCondition") ErrNodeNotReady = newPredicateFailureError("NodeNotReady")
ErrVolumeNodeConflict = newPredicateFailureError("NoVolumeNodeConflict") ErrNodeNetworkUnavailable = newPredicateFailureError("NodeNetworkUnavailable")
ErrNodeUnschedulable = newPredicateFailureError("NodeUnschedulable")
ErrNodeUnknownCondition = newPredicateFailureError("NodeUnknownCondition")
ErrVolumeNodeConflict = newPredicateFailureError("NoVolumeNodeConflict")
// ErrFakePredicate is used for test only. The fake predicates returning false also returns error // ErrFakePredicate is used for test only. The fake predicates returning false also returns error
// as ErrFakePredicate. // as ErrFakePredicate.
ErrFakePredicate = newPredicateFailureError("FakePredicateError") ErrFakePredicate = newPredicateFailureError("FakePredicateError")
......
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package predicates package predicates
import ( import (
"errors"
"fmt" "fmt"
"math/rand" "math/rand"
"strconv" "strconv"
...@@ -963,8 +964,9 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm ...@@ -963,8 +964,9 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm
if node == nil { if node == nil {
return false, nil, fmt.Errorf("node not found") return false, nil, fmt.Errorf("node not found")
} }
if !c.satisfiesExistingPodsAntiAffinity(pod, meta, nodeInfo) { if failedPredicates, error := c.satisfiesExistingPodsAntiAffinity(pod, meta, nodeInfo); failedPredicates != nil {
return false, []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, nil failedPredicates := append([]algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates)
return false, failedPredicates, error
} }
// Now check if <pod> requirements will be satisfied on this node. // Now check if <pod> requirements will be satisfied on this node.
...@@ -972,8 +974,9 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm ...@@ -972,8 +974,9 @@ func (c *PodAffinityChecker) InterPodAffinityMatches(pod *v1.Pod, meta algorithm
if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) { if affinity == nil || (affinity.PodAffinity == nil && affinity.PodAntiAffinity == nil) {
return true, nil, nil return true, nil, nil
} }
if !c.satisfiesPodsAffinityAntiAffinity(pod, nodeInfo, affinity) { if failedPredicates, error := c.satisfiesPodsAffinityAntiAffinity(pod, nodeInfo, affinity); failedPredicates != nil {
return false, []algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, nil failedPredicates := append([]algorithm.PredicateFailureReason{ErrPodAffinityNotMatch}, failedPredicates)
return false, failedPredicates, error
} }
if glog.V(10) { if glog.V(10) {
...@@ -1143,10 +1146,10 @@ func (c *PodAffinityChecker) getMatchingAntiAffinityTerms(pod *v1.Pod, allPods [ ...@@ -1143,10 +1146,10 @@ func (c *PodAffinityChecker) getMatchingAntiAffinityTerms(pod *v1.Pod, allPods [
// Checks if scheduling the pod onto this node would break any anti-affinity // Checks if scheduling the pod onto this node would break any anti-affinity
// rules indicated by the existing pods. // rules indicated by the existing pods.
func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) bool { func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (algorithm.PredicateFailureReason, error) {
node := nodeInfo.Node() node := nodeInfo.Node()
if node == nil { if node == nil {
return false return ErrExistingPodsAntiAffinityRulesNotMatch, fmt.Errorf("Node is nil")
} }
var matchingTerms map[string][]matchingPodAntiAffinityTerm var matchingTerms map[string][]matchingPodAntiAffinityTerm
if predicateMeta, ok := meta.(*predicateMetadata); ok { if predicateMeta, ok := meta.(*predicateMetadata); ok {
...@@ -1156,25 +1159,28 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta ...@@ -1156,25 +1159,28 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta
// present in nodeInfo. Pods on other nodes pass the filter. // present in nodeInfo. Pods on other nodes pass the filter.
filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything()) filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything())
if err != nil { if err != nil {
glog.Errorf("Failed to get all pods, %+v", err) errMessage := fmt.Sprintf("Failed to get all pods, %+v", err)
return false glog.Error(errMessage)
return ErrExistingPodsAntiAffinityRulesNotMatch, errors.New(errMessage)
} }
if matchingTerms, err = c.getMatchingAntiAffinityTerms(pod, filteredPods); err != nil { if matchingTerms, err = c.getMatchingAntiAffinityTerms(pod, filteredPods); err != nil {
glog.Errorf("Failed to get all terms that pod %+v matches, err: %+v", podName(pod), err) errMessage := fmt.Sprintf("Failed to get all terms that pod %+v matches, err: %+v", podName(pod), err)
return false glog.Error(errMessage)
return ErrExistingPodsAntiAffinityRulesNotMatch, errors.New(errMessage)
} }
} }
for _, terms := range matchingTerms { for _, terms := range matchingTerms {
for i := range terms { for i := range terms {
term := &terms[i] term := &terms[i]
if len(term.term.TopologyKey) == 0 { if len(term.term.TopologyKey) == 0 {
glog.Error("Empty topologyKey is not allowed except for PreferredDuringScheduling pod anti-affinity") errMessage := fmt.Sprintf("Empty topologyKey is not allowed except for PreferredDuringScheduling pod anti-affinity")
return false glog.Error(errMessage)
return ErrExistingPodsAntiAffinityRulesNotMatch, errors.New(errMessage)
} }
if priorityutil.NodesHaveSameTopologyKey(node, term.node, term.term.TopologyKey) { if priorityutil.NodesHaveSameTopologyKey(node, term.node, term.term.TopologyKey) {
glog.V(10).Infof("Cannot schedule pod %+v onto node %v,because of PodAntiAffinityTerm %v", glog.V(10).Infof("Cannot schedule pod %+v onto node %v,because of PodAntiAffinityTerm %v",
podName(pod), node.Name, term.term) podName(pod), node.Name, term.term)
return false return ErrExistingPodsAntiAffinityRulesNotMatch, nil
} }
} }
} }
...@@ -1184,27 +1190,27 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta ...@@ -1184,27 +1190,27 @@ func (c *PodAffinityChecker) satisfiesExistingPodsAntiAffinity(pod *v1.Pod, meta
glog.Infof("Schedule Pod %+v on Node %+v is allowed, existing pods anti-affinity rules satisfied.", glog.Infof("Schedule Pod %+v on Node %+v is allowed, existing pods anti-affinity rules satisfied.",
podName(pod), node.Name) podName(pod), node.Name)
} }
return true return nil, nil
} }
// Checks if scheduling the pod onto this node would break any rules of this pod. // Checks if scheduling the pod onto this node would break any rules of this pod.
func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, affinity *v1.Affinity) bool { func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, affinity *v1.Affinity) (algorithm.PredicateFailureReason, error) {
node := nodeInfo.Node() node := nodeInfo.Node()
if node == nil { if node == nil {
return false return ErrPodAffinityRulesNotMatch, fmt.Errorf("Node is nil")
} }
filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything()) filteredPods, err := c.podLister.FilteredList(nodeInfo.Filter, labels.Everything())
if err != nil { if err != nil {
return false return ErrPodAffinityRulesNotMatch, err
} }
// Check all affinity terms. // Check all affinity terms.
for _, term := range getPodAffinityTerms(affinity.PodAffinity) { for _, term := range getPodAffinityTerms(affinity.PodAffinity) {
termMatches, matchingPodExists, err := c.anyPodMatchesPodAffinityTerm(pod, filteredPods, node, &term) termMatches, matchingPodExists, err := c.anyPodMatchesPodAffinityTerm(pod, filteredPods, node, &term)
if err != nil { if err != nil {
glog.Errorf("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v, err: %v", errMessage := fmt.Sprintf("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v, err: %v", podName(pod), node.Name, term, err)
podName(pod), node.Name, term, err) glog.Error(errMessage)
return false return ErrPodAffinityRulesNotMatch, errors.New(errMessage)
} }
if !termMatches { if !termMatches {
// If the requirement matches a pod's own labels are namespace, and there are // If the requirement matches a pod's own labels are namespace, and there are
...@@ -1213,20 +1219,20 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node ...@@ -1213,20 +1219,20 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node
if matchingPodExists { if matchingPodExists {
glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v", glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v",
podName(pod), node.Name, term) podName(pod), node.Name, term)
return false return ErrPodAffinityRulesNotMatch, nil
} }
namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term) namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(pod, &term)
selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector) selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector)
if err != nil { if err != nil {
glog.Errorf("Cannot parse selector on term %v for pod %v. Details %v", errMessage := fmt.Sprintf("Cannot parse selector on term %v for pod %v. Details %v", term, podName(pod), err)
term, podName(pod), err) glog.Error(errMessage)
return false return ErrPodAffinityRulesNotMatch, errors.New(errMessage)
} }
match := priorityutil.PodMatchesTermsNamespaceAndSelector(pod, namespaces, selector) match := priorityutil.PodMatchesTermsNamespaceAndSelector(pod, namespaces, selector)
if !match { if !match {
glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v", glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAffinityTerm %v",
podName(pod), node.Name, term) podName(pod), node.Name, term)
return false return ErrPodAffinityRulesNotMatch, nil
} }
} }
} }
...@@ -1237,7 +1243,7 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node ...@@ -1237,7 +1243,7 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node
if err != nil || termMatches { if err != nil || termMatches {
glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAntiAffinityTerm %v, err: %v", glog.V(10).Infof("Cannot schedule pod %+v onto node %v, because of PodAntiAffinityTerm %v, err: %v",
podName(pod), node.Name, term, err) podName(pod), node.Name, term, err)
return false return ErrPodAntiAffinityRulesNotMatch, nil
} }
} }
...@@ -1247,7 +1253,7 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node ...@@ -1247,7 +1253,7 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node
glog.Infof("Schedule Pod %+v on Node %+v is allowed, pod affinity/anti-affinity constraints satisfied.", glog.Infof("Schedule Pod %+v on Node %+v is allowed, pod affinity/anti-affinity constraints satisfied.",
podName(pod), node.Name) podName(pod), node.Name)
} }
return true return nil, nil
} }
// PodToleratesNodeTaints checks if a pod tolerations can tolerate the node taints // PodToleratesNodeTaints checks if a pod tolerations can tolerate the node taints
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment