kube-scheduler: Use default predicates/prioritizers if policy config does not specify them

This commit is contained in:
Yang Guo 2018-02-05 10:00:17 -08:00
parent 1105751cc7
commit f69eaa3b18
6 changed files with 259 additions and 181 deletions

View File

@ -37,9 +37,14 @@ const (
type Policy struct { type Policy struct {
metav1.TypeMeta metav1.TypeMeta
// Holds the information to configure the fit predicate functions // Holds the information to configure the fit predicate functions.
// If unspecified, the default predicate functions will be applied.
// If empty list, all predicates (except the mandatory ones) will be
// bypassed.
Predicates []PredicatePolicy Predicates []PredicatePolicy
// Holds the information to configure the priority functions // Holds the information to configure the priority functions.
// If unspecified, the default priority functions will be applied.
// If empty list, all priority functions will be bypassed.
Priorities []PriorityPolicy Priorities []PriorityPolicy
// Holds the information to communicate with the extender(s) // Holds the information to communicate with the extender(s)
ExtenderConfigs []ExtenderConfig ExtenderConfigs []ExtenderConfig

View File

@ -67,6 +67,7 @@ go_test(
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/api/testing:go_default_library", "//pkg/api/testing:go_default_library",
"//pkg/scheduler:go_default_library",
"//pkg/scheduler/algorithm:go_default_library", "//pkg/scheduler/algorithm:go_default_library",
"//pkg/scheduler/api:go_default_library", "//pkg/scheduler/api:go_default_library",
"//pkg/scheduler/api/latest:go_default_library", "//pkg/scheduler/api/latest:go_default_library",
@ -77,6 +78,7 @@ go_test(
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",

View File

@ -892,15 +892,33 @@ func (f *configFactory) CreateFromConfig(policy schedulerapi.Policy) (*scheduler
} }
predicateKeys := sets.NewString() predicateKeys := sets.NewString()
for _, predicate := range policy.Predicates { if policy.Predicates == nil {
glog.V(2).Infof("Registering predicate: %s", predicate.Name) glog.V(2).Infof("Using predicates from algorithm provider '%v'", DefaultProvider)
predicateKeys.Insert(RegisterCustomFitPredicate(predicate)) provider, err := GetAlgorithmProvider(DefaultProvider)
if err != nil {
return nil, err
}
predicateKeys = provider.FitPredicateKeys
} else {
for _, predicate := range policy.Predicates {
glog.V(2).Infof("Registering predicate: %s", predicate.Name)
predicateKeys.Insert(RegisterCustomFitPredicate(predicate))
}
} }
priorityKeys := sets.NewString() priorityKeys := sets.NewString()
for _, priority := range policy.Priorities { if policy.Priorities == nil {
glog.V(2).Infof("Registering priority: %s", priority.Name) glog.V(2).Infof("Using priorities from algorithm provider '%v'", DefaultProvider)
priorityKeys.Insert(RegisterCustomPriorityFunction(priority)) provider, err := GetAlgorithmProvider(DefaultProvider)
if err != nil {
return nil, err
}
priorityKeys = provider.PriorityFunctionKeys
} else {
for _, priority := range policy.Priorities {
glog.V(2).Infof("Registering priority: %s", priority.Name)
priorityKeys.Insert(RegisterCustomPriorityFunction(priority))
}
} }
extenders := make([]algorithm.SchedulerExtender, 0) extenders := make([]algorithm.SchedulerExtender, 0)

View File

@ -26,6 +26,7 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
@ -33,6 +34,7 @@ import (
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/scheduler"
"k8s.io/kubernetes/pkg/scheduler/algorithm" "k8s.io/kubernetes/pkg/scheduler/algorithm"
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api" schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest" latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest"
@ -53,23 +55,7 @@ func TestCreate(t *testing.T) {
server := httptest.NewServer(&handler) server := httptest.NewServer(&handler)
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
v1.DefaultHardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
factory.Create() factory.Create()
} }
@ -87,23 +73,7 @@ func TestCreateFromConfig(t *testing.T) {
server := httptest.NewServer(&handler) server := httptest.NewServer(&handler)
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
v1.DefaultHardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
// Pre-register some predicate and priority functions // Pre-register some predicate and priority functions
RegisterFitPredicate("PredicateOne", PredicateOne) RegisterFitPredicate("PredicateOne", PredicateOne)
@ -148,23 +118,7 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) {
server := httptest.NewServer(&handler) server := httptest.NewServer(&handler)
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
v1.DefaultHardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
// Pre-register some predicate and priority functions // Pre-register some predicate and priority functions
RegisterFitPredicate("PredicateOne", PredicateOne) RegisterFitPredicate("PredicateOne", PredicateOne)
@ -210,23 +164,7 @@ func TestCreateFromEmptyConfig(t *testing.T) {
server := httptest.NewServer(&handler) server := httptest.NewServer(&handler)
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
v1.DefaultHardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
configData = []byte(`{}`) configData = []byte(`{}`)
if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil { if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
@ -236,6 +174,88 @@ func TestCreateFromEmptyConfig(t *testing.T) {
factory.CreateFromConfig(policy) factory.CreateFromConfig(policy)
} }
// Test configures a scheduler from a policy that does not specify any
// predicate/priority.
// The predicate/priority from DefaultProvider will be used.
func TestCreateFromConfigWithUnspecifiedPredicatesOrPriorities(t *testing.T) {
handler := utiltesting.FakeHandler{
StatusCode: 500,
ResponseBody: "",
T: t,
}
server := httptest.NewServer(&handler)
defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
RegisterFitPredicate("PredicateOne", PredicateOne)
RegisterPriorityFunction("PriorityOne", PriorityOne, 1)
RegisterAlgorithmProvider(DefaultProvider, sets.NewString("PredicateOne"), sets.NewString("PriorityOne"))
configData := []byte(`{
"kind" : "Policy",
"apiVersion" : "v1"
}`)
var policy schedulerapi.Policy
if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
t.Fatalf("Invalid configuration: %v", err)
}
config, err := factory.CreateFromConfig(policy)
if err != nil {
t.Fatalf("Failed to create scheduler from configuration: %v", err)
}
if _, found := config.Algorithm.Predicates()["PredicateOne"]; !found {
t.Errorf("Expected predicate PredicateOne from %q", DefaultProvider)
}
if len(config.Algorithm.Prioritizers()) != 1 || config.Algorithm.Prioritizers()[0].Name != "PriorityOne" {
t.Errorf("Expected priority PriorityOne from %q", DefaultProvider)
}
}
// Test configures a scheduler from a policy that contains empty
// predicate/priority.
// Empty predicate/priority sets will be used.
func TestCreateFromConfigWithEmptyPredicatesOrPriorities(t *testing.T) {
handler := utiltesting.FakeHandler{
StatusCode: 500,
ResponseBody: "",
T: t,
}
server := httptest.NewServer(&handler)
defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
RegisterFitPredicate("PredicateOne", PredicateOne)
RegisterPriorityFunction("PriorityOne", PriorityOne, 1)
RegisterAlgorithmProvider(DefaultProvider, sets.NewString("PredicateOne"), sets.NewString("PriorityOne"))
configData := []byte(`{
"kind" : "Policy",
"apiVersion" : "v1",
"predicates" : [],
"priorities" : []
}`)
var policy schedulerapi.Policy
if err := runtime.DecodeInto(latestschedulerapi.Codec, configData, &policy); err != nil {
t.Fatalf("Invalid configuration: %v", err)
}
config, err := factory.CreateFromConfig(policy)
if err != nil {
t.Fatalf("Failed to create scheduler from configuration: %v", err)
}
if len(config.Algorithm.Predicates()) != 0 {
t.Error("Expected empty predicate sets")
}
if len(config.Algorithm.Prioritizers()) != 0 {
t.Error("Expected empty priority sets")
}
}
func PredicateOne(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { func PredicateOne(pod *v1.Pod, meta algorithm.PredicateMetadata, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
return true, nil, nil return true, nil, nil
} }
@ -269,23 +289,7 @@ func TestDefaultErrorFunc(t *testing.T) {
server := httptest.NewServer(mux) server := httptest.NewServer(mux)
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, v1.DefaultHardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
v1.DefaultHardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
queue := &core.FIFO{FIFO: cache.NewFIFO(cache.MetaNamespaceKeyFunc)} queue := &core.FIFO{FIFO: cache.NewFIFO(cache.MetaNamespaceKeyFunc)}
podBackoff := util.CreatePodBackoff(1*time.Millisecond, 1*time.Second) podBackoff := util.CreatePodBackoff(1*time.Millisecond, 1*time.Second)
errFunc := factory.MakeDefaultErrorFunc(podBackoff, queue) errFunc := factory.MakeDefaultErrorFunc(podBackoff, queue)
@ -379,23 +383,7 @@ func TestInvalidHardPodAffinitySymmetricWeight(t *testing.T) {
defer server.Close() defer server.Close()
client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}}) client := clientset.NewForConfigOrDie(&restclient.Config{Host: server.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion}})
// factory of "default-scheduler" // factory of "default-scheduler"
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, -1)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
-1,
enableEquivalenceCache,
)
_, err := factory.Create() _, err := factory.Create()
if err == nil { if err == nil {
t.Errorf("expected err: invalid hardPodAffinitySymmetricWeight, got nothing") t.Errorf("expected err: invalid hardPodAffinitySymmetricWeight, got nothing")
@ -427,23 +415,7 @@ func TestInvalidFactoryArgs(t *testing.T) {
} }
for _, test := range testCases { for _, test := range testCases {
informerFactory := informers.NewSharedInformerFactory(client, 0) factory := newConfigFactory(client, test.hardPodAffinitySymmetricWeight)
factory := NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
test.hardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
_, err := factory.Create() _, err := factory.Create()
if err == nil { if err == nil {
t.Errorf("expected err: %s, got nothing", test.expectErr) t.Errorf("expected err: %s, got nothing", test.expectErr)
@ -541,3 +513,23 @@ func TestSkipPodUpdate(t *testing.T) {
} }
} }
} }
func newConfigFactory(client *clientset.Clientset, hardPodAffinitySymmetricWeight int32) scheduler.Configurator {
informerFactory := informers.NewSharedInformerFactory(client, 0)
return NewConfigFactory(
v1.DefaultSchedulerName,
client,
informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().PersistentVolumes(),
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Core().V1().ReplicationControllers(),
informerFactory.Extensions().V1beta1().ReplicaSets(),
informerFactory.Apps().V1beta1().StatefulSets(),
informerFactory.Core().V1().Services(),
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
informerFactory.Storage().V1().StorageClasses(),
hardPodAffinitySymmetricWeight,
enableEquivalenceCache,
)
}

View File

@ -57,6 +57,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/informers:go_default_library",

View File

@ -31,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
@ -97,69 +98,128 @@ func TestSchedulerCreationFromConfigMap(t *testing.T) {
factory.RegisterPriorityFunction("PriorityOne", PriorityOne, 1) factory.RegisterPriorityFunction("PriorityOne", PriorityOne, 1)
factory.RegisterPriorityFunction("PriorityTwo", PriorityTwo, 1) factory.RegisterPriorityFunction("PriorityTwo", PriorityTwo, 1)
// Add a ConfigMap object. for i, test := range []struct {
configPolicyName := "scheduler-custom-policy-config" policy string
policyConfigMap := v1.ConfigMap{ expectedPredicates sets.String
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: configPolicyName}, expectedPrioritizers sets.String
Data: map[string]string{ }{
componentconfig.SchedulerPolicyConfigMapKey: `{ {
"kind" : "Policy", policy: `{
"apiVersion" : "v1", "kind" : "Policy",
"predicates" : [ "apiVersion" : "v1",
{"name" : "PredicateOne"}, "predicates" : [
{"name" : "PredicateTwo"} {"name" : "PredicateOne"},
], {"name" : "PredicateTwo"}
"priorities" : [ ],
{"name" : "PriorityOne", "weight" : 1}, "priorities" : [
{"name" : "PriorityTwo", "weight" : 5} {"name" : "PriorityOne", "weight" : 1},
] {"name" : "PriorityTwo", "weight" : 5}
]
}`, }`,
expectedPredicates: sets.NewString(
"CheckNodeCondition", // mandatory predicate
"PredicateOne",
"PredicateTwo",
),
expectedPrioritizers: sets.NewString(
"PriorityOne",
"PriorityTwo",
),
}, },
} {
policy: `{
"kind" : "Policy",
"apiVersion" : "v1"
}`,
expectedPredicates: sets.NewString(
"CheckNodeCondition", // mandatory predicate
"CheckNodeDiskPressure",
"CheckNodeMemoryPressure",
"CheckVolumeBinding",
"GeneralPredicates",
"MatchInterPodAffinity",
"MaxAzureDiskVolumeCount",
"MaxEBSVolumeCount",
"MaxGCEPDVolumeCount",
"NoDiskConflict",
"NoVolumeZoneConflict",
"PodToleratesNodeTaints",
),
expectedPrioritizers: sets.NewString(
"BalancedResourceAllocation",
"InterPodAffinityPriority",
"LeastRequestedPriority",
"NodeAffinityPriority",
"NodePreferAvoidPodsPriority",
"SelectorSpreadPriority",
"TaintTolerationPriority",
),
},
{
policy: `{
"kind" : "Policy",
"apiVersion" : "v1",
"predicates" : [],
"priorities" : []
}`,
expectedPredicates: sets.NewString(
"CheckNodeCondition", // mandatory predicate
),
expectedPrioritizers: sets.NewString(),
},
} {
// Add a ConfigMap object.
configPolicyName := fmt.Sprintf("scheduler-custom-policy-config-%d", i)
policyConfigMap := v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: configPolicyName},
Data: map[string]string{componentconfig.SchedulerPolicyConfigMapKey: test.policy},
}
policyConfigMap.APIVersion = testapi.Groups[v1.GroupName].GroupVersion().String() policyConfigMap.APIVersion = testapi.Groups[v1.GroupName].GroupVersion().String()
clientSet.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(&policyConfigMap) clientSet.CoreV1().ConfigMaps(metav1.NamespaceSystem).Create(&policyConfigMap)
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(clientSet.CoreV1().RESTClient()).Events("")}) eventBroadcaster.StartRecordingToSink(&clientv1core.EventSinkImpl{Interface: clientv1core.New(clientSet.CoreV1().RESTClient()).Events("")})
ss := &schedulerapp.SchedulerServer{ ss := &schedulerapp.SchedulerServer{
SchedulerName: v1.DefaultSchedulerName, SchedulerName: v1.DefaultSchedulerName,
AlgorithmSource: componentconfig.SchedulerAlgorithmSource{ AlgorithmSource: componentconfig.SchedulerAlgorithmSource{
Policy: &componentconfig.SchedulerPolicySource{ Policy: &componentconfig.SchedulerPolicySource{
ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{ ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{
Namespace: policyConfigMap.Namespace, Namespace: policyConfigMap.Namespace,
Name: policyConfigMap.Name, Name: policyConfigMap.Name,
},
}, },
}, },
}, HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight,
HardPodAffinitySymmetricWeight: v1.DefaultHardPodAffinitySymmetricWeight, Client: clientSet,
Client: clientSet, InformerFactory: informerFactory,
InformerFactory: informerFactory, PodInformer: factory.NewPodInformer(clientSet, 0, v1.DefaultSchedulerName),
PodInformer: factory.NewPodInformer(clientSet, 0, v1.DefaultSchedulerName), EventClient: clientSet.CoreV1(),
EventClient: clientSet.CoreV1(), Recorder: eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}),
Recorder: eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: v1.DefaultSchedulerName}), Broadcaster: eventBroadcaster,
Broadcaster: eventBroadcaster, }
}
config, err := ss.SchedulerConfig() config, err := ss.SchedulerConfig()
if err != nil { if err != nil {
t.Fatalf("couldn't make scheduler config: %v", err) t.Fatalf("couldn't make scheduler config: %v", err)
} }
// Verify that the config is applied correctly. // Verify that the config is applied correctly.
schedPredicates := config.Algorithm.Predicates() schedPredicates := sets.NewString()
schedPrioritizers := config.Algorithm.Prioritizers() for k := range config.Algorithm.Predicates() {
// Includes one mandatory predicates. schedPredicates.Insert(k)
if len(schedPredicates) != 3 || len(schedPrioritizers) != 2 { }
t.Errorf("Unexpected number of predicates or priority functions. Number of predicates: %v, number of prioritizers: %v", len(schedPredicates), len(schedPrioritizers)) schedPrioritizers := sets.NewString()
} for _, p := range config.Algorithm.Prioritizers() {
// Check a predicate and a priority function. schedPrioritizers.Insert(p.Name)
if schedPredicates["PredicateTwo"] == nil { }
t.Errorf("Expected to have a PodFitsHostPorts predicate.") if !schedPredicates.Equal(test.expectedPredicates) {
} t.Errorf("Expected predicates %v, got %v", test.expectedPredicates, schedPredicates)
if schedPrioritizers[1].Function == nil || schedPrioritizers[1].Weight != 5 { }
t.Errorf("Unexpected prioritizer: func: %v, weight: %v", schedPrioritizers[1].Function, schedPrioritizers[1].Weight) if !schedPrioritizers.Equal(test.expectedPrioritizers) {
t.Errorf("Expected priority functions %v, got %v", test.expectedPrioritizers, schedPrioritizers)
}
} }
} }