implementing predicates ordering

This commit is contained in:
Yassine TIJANI
2017-12-14 00:57:23 +00:00
parent 17117051c4
commit ecba504974
4 changed files with 83 additions and 29 deletions

View File

@@ -51,7 +51,23 @@ import (
const ( const (
MatchInterPodAffinity = "MatchInterPodAffinity" MatchInterPodAffinity = "MatchInterPodAffinity"
CheckVolumeBinding = "CheckVolumeBinding" CheckVolumeBinding = "CheckVolumeBinding"
CheckNodeConditionPred = "CheckNodeCondition"
GeneralPred = "GeneralPredicates"
HostNamePred = "HostName"
PodFitsHostPortsPred = "PodFitsHostPorts"
MatchNodeSelectorPred = "MatchNodeSelector"
PodFitsResourcesPred = "PodFitsResources"
NoDiskConflictPred = "NoDiskConflict"
PodToleratesNodeTaintsPred = "PodToleratesNodeTaints"
PodToleratesNodeNoExecuteTaintsPred = "PodToleratesNodeNoExecuteTaints"
CheckNodeLabelPresencePred = "CheckNodeLabelPresence"
checkServiceAffinityPred = "checkServiceAffinity"
MaxEBSVolumeCountPred = "MaxEBSVolumeCount"
MaxGCEPDVolumeCountPred = "MaxGCEPDVolumeCount"
MaxAzureDiskVolumeCountPred = "MaxAzureDiskVolumeCount"
NoVolumeZoneConflictPred = "NoVolumeZoneConflict"
CheckNodeMemoryPressurePred = "CheckNodeMemoryPressure"
CheckNodeDiskPressure = "CheckNodeDiskPressure"
// DefaultMaxGCEPDVolumes defines the maximum number of PD Volumes for GCE // DefaultMaxGCEPDVolumes defines the maximum number of PD Volumes for GCE
// GCE instances can have up to 16 PD volumes attached. // GCE instances can have up to 16 PD volumes attached.
DefaultMaxGCEPDVolumes = 16 DefaultMaxGCEPDVolumes = 16
@@ -79,6 +95,21 @@ const (
// For example: // For example:
// https://github.com/kubernetes/kubernetes/blob/36a218e/plugin/pkg/scheduler/factory/factory.go#L422 // https://github.com/kubernetes/kubernetes/blob/36a218e/plugin/pkg/scheduler/factory/factory.go#L422
// IMPORTANT: this list contains the ordering of the predicates, if you develop a new predicates
// it is mandatory to add its name on this list.
// otherwise it won't be processed, see generic_scheduler#podFitsOnNode()
// the order is based on the restrictiveness & complexity of predicates
// design doc: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/predicates-ordering.md
var (
predicatesOrdering = []string{CheckNodeConditionPred,
GeneralPred, HostNamePred, PodFitsHostPortsPred,
MatchNodeSelectorPred, PodFitsResourcesPred, NoDiskConflictPred,
PodToleratesNodeTaintsPred, PodToleratesNodeNoExecuteTaintsPred, CheckNodeLabelPresencePred,
checkServiceAffinityPred, MaxEBSVolumeCountPred, MaxGCEPDVolumeCountPred,
MaxAzureDiskVolumeCountPred, CheckVolumeBinding, NoVolumeZoneConflictPred,
CheckNodeMemoryPressurePred, CheckNodeDiskPressure, MatchInterPodAffinity}
)
// NodeInfo: Other types for predicate functions... // NodeInfo: Other types for predicate functions...
type NodeInfo interface { type NodeInfo interface {
GetNodeInfo(nodeID string) (*v1.Node, error) GetNodeInfo(nodeID string) (*v1.Node, error)
@@ -93,6 +124,14 @@ type CachedPersistentVolumeInfo struct {
corelisters.PersistentVolumeLister corelisters.PersistentVolumeLister
} }
func GetPredicatesOrdering() []string {
return predicatesOrdering
}
func SetPredicatesOrdering(names []string) {
predicatesOrdering = names
}
func (c *CachedPersistentVolumeInfo) GetPersistentVolumeInfo(pvID string) (*v1.PersistentVolume, error) { func (c *CachedPersistentVolumeInfo) GetPersistentVolumeInfo(pvID string) (*v1.PersistentVolume, error) {
return c.Get(pvID) return c.Get(pvID)
} }

View File

@@ -444,7 +444,9 @@ func podFitsOnNode(
// TODO(bsalamat): consider using eCache and adding proper eCache invalidations // TODO(bsalamat): consider using eCache and adding proper eCache invalidations
// when pods are nominated or their nominations change. // when pods are nominated or their nominations change.
eCacheAvailable = eCacheAvailable && !podsAdded eCacheAvailable = eCacheAvailable && !podsAdded
for predicateKey, predicate := range predicateFuncs { for _, predicateKey := range predicates.GetPredicatesOrdering() {
//TODO (yastij) : compute average predicate restrictiveness to export it as promethus metric
if predicate, exist := predicateFuncs[predicateKey]; exist {
if eCacheAvailable { if eCacheAvailable {
// PredicateWithECache will return its cached predicate results. // PredicateWithECache will return its cached predicate results.
fit, reasons, invalid = ecache.PredicateWithECache(pod.GetName(), info.Node().GetName(), predicateKey, equivalenceHash) fit, reasons, invalid = ecache.PredicateWithECache(pod.GetName(), info.Node().GetName(), predicateKey, equivalenceHash)
@@ -475,6 +477,7 @@ func podFitsOnNode(
} }
} }
} }
}
// TODO(bsalamat): This way of updating equiv. cache has a race condition against // TODO(bsalamat): This way of updating equiv. cache has a race condition against
// cache invalidations invoked in event handlers. This race has existed despite locks // cache invalidations invoked in event handlers. This race has existed despite locks

View File

@@ -42,6 +42,10 @@ import (
schedulertesting "k8s.io/kubernetes/plugin/pkg/scheduler/testing" schedulertesting "k8s.io/kubernetes/plugin/pkg/scheduler/testing"
) )
var (
order = []string{"false", "true", "matches", "nopods", predicates.MatchInterPodAffinity}
)
func falsePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { func falsePredicate(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil return false, []algorithm.PredicateFailureReason{algorithmpredicates.ErrFakePredicate}, nil
} }
@@ -181,6 +185,7 @@ func TestSelectHost(t *testing.T) {
} }
func TestGenericScheduler(t *testing.T) { func TestGenericScheduler(t *testing.T) {
predicates.SetPredicatesOrdering(order)
tests := []struct { tests := []struct {
name string name string
predicates map[string]algorithm.FitPredicate predicates map[string]algorithm.FitPredicate
@@ -401,6 +406,7 @@ func TestGenericScheduler(t *testing.T) {
} }
func TestFindFitAllError(t *testing.T) { func TestFindFitAllError(t *testing.T) {
predicates.SetPredicatesOrdering(order)
nodes := []string{"3", "2", "1"} nodes := []string{"3", "2", "1"}
predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "false": falsePredicate} predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "false": falsePredicate}
nodeNameToInfo := map[string]*schedulercache.NodeInfo{ nodeNameToInfo := map[string]*schedulercache.NodeInfo{
@@ -430,8 +436,9 @@ func TestFindFitAllError(t *testing.T) {
} }
func TestFindFitSomeError(t *testing.T) { func TestFindFitSomeError(t *testing.T) {
predicates.SetPredicatesOrdering(order)
nodes := []string{"3", "2", "1"} nodes := []string{"3", "2", "1"}
predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "match": matchesPredicate} predicates := map[string]algorithm.FitPredicate{"true": truePredicate, "matches": matchesPredicate}
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "1"}} pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "1"}}
nodeNameToInfo := map[string]*schedulercache.NodeInfo{ nodeNameToInfo := map[string]*schedulercache.NodeInfo{
"3": schedulercache.NewNodeInfo(), "3": schedulercache.NewNodeInfo(),
@@ -741,6 +748,7 @@ var negPriority, lowPriority, midPriority, highPriority, veryHighPriority = int3
// TestSelectNodesForPreemption tests selectNodesForPreemption. This test assumes // TestSelectNodesForPreemption tests selectNodesForPreemption. This test assumes
// that podsFitsOnNode works correctly and is tested separately. // that podsFitsOnNode works correctly and is tested separately.
func TestSelectNodesForPreemption(t *testing.T) { func TestSelectNodesForPreemption(t *testing.T) {
predicates.SetPredicatesOrdering(order)
tests := []struct { tests := []struct {
name string name string
predicates map[string]algorithm.FitPredicate predicates map[string]algorithm.FitPredicate
@@ -879,6 +887,7 @@ func TestSelectNodesForPreemption(t *testing.T) {
// TestPickOneNodeForPreemption tests pickOneNodeForPreemption. // TestPickOneNodeForPreemption tests pickOneNodeForPreemption.
func TestPickOneNodeForPreemption(t *testing.T) { func TestPickOneNodeForPreemption(t *testing.T) {
predicates.SetPredicatesOrdering(order)
tests := []struct { tests := []struct {
name string name string
predicates map[string]algorithm.FitPredicate predicates map[string]algorithm.FitPredicate

View File

@@ -43,6 +43,8 @@ import (
"k8s.io/kubernetes/plugin/pkg/scheduler/volumebinder" "k8s.io/kubernetes/plugin/pkg/scheduler/volumebinder"
) )
var order = []string{"VolumeBindingChecker"}
type fakeBinder struct { type fakeBinder struct {
b func(binding *v1.Binding) error b func(binding *v1.Binding) error
} }
@@ -637,6 +639,7 @@ func makePredicateError(failReason string) error {
} }
func TestSchedulerWithVolumeBinding(t *testing.T) { func TestSchedulerWithVolumeBinding(t *testing.T) {
predicates.SetPredicatesOrdering(order)
findErr := fmt.Errorf("find err") findErr := fmt.Errorf("find err")
assumeErr := fmt.Errorf("assume err") assumeErr := fmt.Errorf("assume err")
bindErr := fmt.Errorf("bind err") bindErr := fmt.Errorf("bind err")