mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Scheduler volume cache plumbing and predicate invalidation
This commit is contained in:
parent
fa6b62fa63
commit
01a8772111
@ -40,6 +40,7 @@ import (
|
|||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
|
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
@ -625,6 +626,11 @@ func (s *SchedulerServer) Run(stop chan struct{}) error {
|
|||||||
// SchedulerConfig creates the scheduler configuration. This is exposed for use
|
// SchedulerConfig creates the scheduler configuration. This is exposed for use
|
||||||
// by tests.
|
// by tests.
|
||||||
func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) {
|
func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) {
|
||||||
|
var storageClassInformer storageinformers.StorageClassInformer
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
storageClassInformer = s.InformerFactory.Storage().V1().StorageClasses()
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the configurator which can create schedulers from configs.
|
// Set up the configurator which can create schedulers from configs.
|
||||||
configurator := factory.NewConfigFactory(
|
configurator := factory.NewConfigFactory(
|
||||||
s.SchedulerName,
|
s.SchedulerName,
|
||||||
@ -638,6 +644,7 @@ func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) {
|
|||||||
s.InformerFactory.Apps().V1beta1().StatefulSets(),
|
s.InformerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
s.InformerFactory.Core().V1().Services(),
|
s.InformerFactory.Core().V1().Services(),
|
||||||
s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
storageClassInformer,
|
||||||
s.HardPodAffinitySymmetricWeight,
|
s.HardPodAffinitySymmetricWeight,
|
||||||
utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache),
|
utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache),
|
||||||
)
|
)
|
||||||
|
@ -439,6 +439,18 @@ func ClusterRoles() []rbac.ClusterRole {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
// Find the scheduler role
|
||||||
|
for i, role := range roles {
|
||||||
|
if role.Name == "system:kube-scheduler" {
|
||||||
|
pvRule := rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie()
|
||||||
|
scRule := rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie()
|
||||||
|
roles[i].Rules = append(role.Rules, pvRule, scRule)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addClusterRoleLabel(roles)
|
addClusterRoleLabel(roles)
|
||||||
return roles
|
return roles
|
||||||
}
|
}
|
||||||
|
@ -506,6 +506,7 @@ func TestCompatibility_v1_Scheduler(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
).CreateFromConfig(policy); err != nil {
|
).CreateFromConfig(policy); err != nil {
|
||||||
|
@ -317,7 +317,7 @@ func TestGenericSchedulerWithExtenders(t *testing.T) {
|
|||||||
}
|
}
|
||||||
queue := NewSchedulingQueue()
|
queue := NewSchedulingQueue()
|
||||||
scheduler := NewGenericScheduler(
|
scheduler := NewGenericScheduler(
|
||||||
cache, nil, queue, test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyMetadataProducer, extenders)
|
cache, nil, queue, test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyMetadataProducer, extenders, nil)
|
||||||
podIgnored := &v1.Pod{}
|
podIgnored := &v1.Pod{}
|
||||||
machine, err := scheduler.Schedule(podIgnored, schedulertesting.FakeNodeLister(makeNodeList(test.nodes)))
|
machine, err := scheduler.Schedule(podIgnored, schedulertesting.FakeNodeLister(makeNodeList(test.nodes)))
|
||||||
if test.expectsErr {
|
if test.expectsErr {
|
||||||
|
@ -36,6 +36,7 @@ import (
|
|||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/util"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/util"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/volumebinder"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FailedPredicateMap map[string][]algorithm.PredicateFailureReason
|
type FailedPredicateMap map[string][]algorithm.PredicateFailureReason
|
||||||
@ -91,6 +92,7 @@ type genericScheduler struct {
|
|||||||
lastNodeIndex uint64
|
lastNodeIndex uint64
|
||||||
|
|
||||||
cachedNodeInfoMap map[string]*schedulercache.NodeInfo
|
cachedNodeInfoMap map[string]*schedulercache.NodeInfo
|
||||||
|
volumeBinder *volumebinder.VolumeBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule tries to schedule the given pod to one of node in the node list.
|
// Schedule tries to schedule the given pod to one of node in the node list.
|
||||||
@ -867,7 +869,10 @@ func nodesWherePreemptionMightHelp(pod *v1.Pod, nodes []*v1.Node, failedPredicat
|
|||||||
predicates.ErrNodeNotReady,
|
predicates.ErrNodeNotReady,
|
||||||
predicates.ErrNodeNetworkUnavailable,
|
predicates.ErrNodeNetworkUnavailable,
|
||||||
predicates.ErrNodeUnschedulable,
|
predicates.ErrNodeUnschedulable,
|
||||||
predicates.ErrNodeUnknownCondition:
|
predicates.ErrNodeUnknownCondition,
|
||||||
|
predicates.ErrVolumeZoneConflict,
|
||||||
|
predicates.ErrVolumeNodeConflict,
|
||||||
|
predicates.ErrVolumeBindConflict:
|
||||||
unresolvableReasonExist = true
|
unresolvableReasonExist = true
|
||||||
break
|
break
|
||||||
// TODO(bsalamat): Please add affinity failure cases once we have specific affinity failure errors.
|
// TODO(bsalamat): Please add affinity failure cases once we have specific affinity failure errors.
|
||||||
@ -909,7 +914,8 @@ func NewGenericScheduler(
|
|||||||
predicateMetaProducer algorithm.PredicateMetadataProducer,
|
predicateMetaProducer algorithm.PredicateMetadataProducer,
|
||||||
prioritizers []algorithm.PriorityConfig,
|
prioritizers []algorithm.PriorityConfig,
|
||||||
priorityMetaProducer algorithm.MetadataProducer,
|
priorityMetaProducer algorithm.MetadataProducer,
|
||||||
extenders []algorithm.SchedulerExtender) algorithm.ScheduleAlgorithm {
|
extenders []algorithm.SchedulerExtender,
|
||||||
|
volumeBinder *volumebinder.VolumeBinder) algorithm.ScheduleAlgorithm {
|
||||||
return &genericScheduler{
|
return &genericScheduler{
|
||||||
cache: cache,
|
cache: cache,
|
||||||
equivalenceCache: eCache,
|
equivalenceCache: eCache,
|
||||||
@ -920,5 +926,6 @@ func NewGenericScheduler(
|
|||||||
priorityMetaProducer: priorityMetaProducer,
|
priorityMetaProducer: priorityMetaProducer,
|
||||||
extenders: extenders,
|
extenders: extenders,
|
||||||
cachedNodeInfoMap: make(map[string]*schedulercache.NodeInfo),
|
cachedNodeInfoMap: make(map[string]*schedulercache.NodeInfo),
|
||||||
|
volumeBinder: volumeBinder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ func TestGenericScheduler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scheduler := NewGenericScheduler(
|
scheduler := NewGenericScheduler(
|
||||||
cache, nil, NewSchedulingQueue(), test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyMetadataProducer, []algorithm.SchedulerExtender{})
|
cache, nil, NewSchedulingQueue(), test.predicates, algorithm.EmptyPredicateMetadataProducer, test.prioritizers, algorithm.EmptyMetadataProducer, []algorithm.SchedulerExtender{}, nil)
|
||||||
machine, err := scheduler.Schedule(test.pod, schedulertesting.FakeNodeLister(makeNodeList(test.nodes)))
|
machine, err := scheduler.Schedule(test.pod, schedulertesting.FakeNodeLister(makeNodeList(test.nodes)))
|
||||||
|
|
||||||
if !reflect.DeepEqual(err, test.wErr) {
|
if !reflect.DeepEqual(err, test.wErr) {
|
||||||
@ -1190,7 +1190,7 @@ func TestPreempt(t *testing.T) {
|
|||||||
extenders = append(extenders, extender)
|
extenders = append(extenders, extender)
|
||||||
}
|
}
|
||||||
scheduler := NewGenericScheduler(
|
scheduler := NewGenericScheduler(
|
||||||
cache, nil, NewSchedulingQueue(), map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, algorithm.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, algorithm.EmptyMetadataProducer, extenders)
|
cache, nil, NewSchedulingQueue(), map[string]algorithm.FitPredicate{"matches": algorithmpredicates.PodFitsResources}, algorithm.EmptyPredicateMetadataProducer, []algorithm.PriorityConfig{{Function: numericPriority, Weight: 1}}, algorithm.EmptyMetadataProducer, extenders, nil)
|
||||||
// Call Preempt and check the expected results.
|
// Call Preempt and check the expected results.
|
||||||
node, victims, _, err := scheduler.Preempt(test.pod, schedulertesting.FakeNodeLister(makeNodeList(nodeNames)), error(&FitError{Pod: test.pod, FailedPredicates: failedPredMap}))
|
node, victims, _, err := scheduler.Preempt(test.pod, schedulertesting.FakeNodeLister(makeNodeList(nodeNames)), error(&FitError{Pod: test.pod, FailedPredicates: failedPredMap}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,18 +37,22 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
appsinformers "k8s.io/client-go/informers/apps/v1beta1"
|
appsinformers "k8s.io/client-go/informers/apps/v1beta1"
|
||||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1"
|
extensionsinformers "k8s.io/client-go/informers/extensions/v1beta1"
|
||||||
policyinformers "k8s.io/client-go/informers/policy/v1beta1"
|
policyinformers "k8s.io/client-go/informers/policy/v1beta1"
|
||||||
|
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
appslisters "k8s.io/client-go/listers/apps/v1beta1"
|
appslisters "k8s.io/client-go/listers/apps/v1beta1"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
extensionslisters "k8s.io/client-go/listers/extensions/v1beta1"
|
extensionslisters "k8s.io/client-go/listers/extensions/v1beta1"
|
||||||
policylisters "k8s.io/client-go/listers/policy/v1beta1"
|
policylisters "k8s.io/client-go/listers/policy/v1beta1"
|
||||||
|
storagelisters "k8s.io/client-go/listers/storage/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
|
"k8s.io/kubernetes/pkg/features"
|
||||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler"
|
"k8s.io/kubernetes/plugin/pkg/scheduler"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||||
@ -58,6 +62,7 @@ import (
|
|||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/core"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/core"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/util"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/util"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/volumebinder"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -98,6 +103,8 @@ type configFactory struct {
|
|||||||
statefulSetLister appslisters.StatefulSetLister
|
statefulSetLister appslisters.StatefulSetLister
|
||||||
// a means to list all PodDisruptionBudgets
|
// a means to list all PodDisruptionBudgets
|
||||||
pdbLister policylisters.PodDisruptionBudgetLister
|
pdbLister policylisters.PodDisruptionBudgetLister
|
||||||
|
// a means to list all StorageClasses
|
||||||
|
storageClassLister storagelisters.StorageClassLister
|
||||||
|
|
||||||
// Close this to stop all reflectors
|
// Close this to stop all reflectors
|
||||||
StopEverything chan struct{}
|
StopEverything chan struct{}
|
||||||
@ -120,6 +127,9 @@ type configFactory struct {
|
|||||||
|
|
||||||
// Enable equivalence class cache
|
// Enable equivalence class cache
|
||||||
enableEquivalenceClassCache bool
|
enableEquivalenceClassCache bool
|
||||||
|
|
||||||
|
// Handles volume binding decisions
|
||||||
|
volumeBinder *volumebinder.VolumeBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfigFactory initializes the default implementation of a Configurator To encourage eventual privatization of the struct type, we only
|
// NewConfigFactory initializes the default implementation of a Configurator To encourage eventual privatization of the struct type, we only
|
||||||
@ -136,12 +146,19 @@ func NewConfigFactory(
|
|||||||
statefulSetInformer appsinformers.StatefulSetInformer,
|
statefulSetInformer appsinformers.StatefulSetInformer,
|
||||||
serviceInformer coreinformers.ServiceInformer,
|
serviceInformer coreinformers.ServiceInformer,
|
||||||
pdbInformer policyinformers.PodDisruptionBudgetInformer,
|
pdbInformer policyinformers.PodDisruptionBudgetInformer,
|
||||||
|
storageClassInformer storageinformers.StorageClassInformer,
|
||||||
hardPodAffinitySymmetricWeight int32,
|
hardPodAffinitySymmetricWeight int32,
|
||||||
enableEquivalenceClassCache bool,
|
enableEquivalenceClassCache bool,
|
||||||
) scheduler.Configurator {
|
) scheduler.Configurator {
|
||||||
stopEverything := make(chan struct{})
|
stopEverything := make(chan struct{})
|
||||||
schedulerCache := schedulercache.New(30*time.Second, stopEverything)
|
schedulerCache := schedulercache.New(30*time.Second, stopEverything)
|
||||||
|
|
||||||
|
// storageClassInformer is only enabled through VolumeScheduling feature gate
|
||||||
|
var storageClassLister storagelisters.StorageClassLister
|
||||||
|
if storageClassInformer != nil {
|
||||||
|
storageClassLister = storageClassInformer.Lister()
|
||||||
|
}
|
||||||
|
|
||||||
c := &configFactory{
|
c := &configFactory{
|
||||||
client: client,
|
client: client,
|
||||||
podLister: schedulerCache,
|
podLister: schedulerCache,
|
||||||
@ -153,6 +170,7 @@ func NewConfigFactory(
|
|||||||
replicaSetLister: replicaSetInformer.Lister(),
|
replicaSetLister: replicaSetInformer.Lister(),
|
||||||
statefulSetLister: statefulSetInformer.Lister(),
|
statefulSetLister: statefulSetInformer.Lister(),
|
||||||
pdbLister: pdbInformer.Lister(),
|
pdbLister: pdbInformer.Lister(),
|
||||||
|
storageClassLister: storageClassLister,
|
||||||
schedulerCache: schedulerCache,
|
schedulerCache: schedulerCache,
|
||||||
StopEverything: stopEverything,
|
StopEverything: stopEverything,
|
||||||
schedulerName: schedulerName,
|
schedulerName: schedulerName,
|
||||||
@ -208,9 +226,14 @@ func NewConfigFactory(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
if err := c.podQueue.Delete(obj.(*v1.Pod)); err != nil {
|
pod := obj.(*v1.Pod)
|
||||||
|
if err := c.podQueue.Delete(pod); err != nil {
|
||||||
runtime.HandleError(fmt.Errorf("unable to dequeue %T: %v", obj, err))
|
runtime.HandleError(fmt.Errorf("unable to dequeue %T: %v", obj, err))
|
||||||
}
|
}
|
||||||
|
if c.volumeBinder != nil {
|
||||||
|
// Volume binder only wants to keep unassigned pods
|
||||||
|
c.volumeBinder.DeletePodBindings(pod)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -252,6 +275,7 @@ func NewConfigFactory(
|
|||||||
pvcInformer.Informer().AddEventHandler(
|
pvcInformer.Informer().AddEventHandler(
|
||||||
cache.ResourceEventHandlerFuncs{
|
cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: c.onPvcAdd,
|
AddFunc: c.onPvcAdd,
|
||||||
|
UpdateFunc: c.onPvcUpdate,
|
||||||
DeleteFunc: c.onPvcDelete,
|
DeleteFunc: c.onPvcDelete,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -272,6 +296,11 @@ func NewConfigFactory(
|
|||||||
// Existing equivalence cache should not be affected by add/delete RC/Deployment etc,
|
// Existing equivalence cache should not be affected by add/delete RC/Deployment etc,
|
||||||
// it only make sense when pod is scheduled or deleted
|
// it only make sense when pod is scheduled or deleted
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
// Setup volume binder
|
||||||
|
c.volumeBinder = volumebinder.NewVolumeBinder(client, pvcInformer, pvInformer, nodeInformer, storageClassInformer)
|
||||||
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +394,12 @@ func (c *configFactory) invalidatePredicatesForPv(pv *v1.PersistentVolume) {
|
|||||||
if pv.Spec.AzureDisk != nil {
|
if pv.Spec.AzureDisk != nil {
|
||||||
invalidPredicates.Insert("MaxAzureDiskVolumeCount")
|
invalidPredicates.Insert("MaxAzureDiskVolumeCount")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
// Add/delete impacts the available PVs to choose from
|
||||||
|
invalidPredicates.Insert(predicates.CheckVolumeBinding)
|
||||||
|
}
|
||||||
|
|
||||||
c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates)
|
c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,6 +415,27 @@ func (c *configFactory) onPvcAdd(obj interface{}) {
|
|||||||
c.podQueue.MoveAllToActiveQueue()
|
c.podQueue.MoveAllToActiveQueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configFactory) onPvcUpdate(old, new interface{}) {
|
||||||
|
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.enableEquivalenceClassCache {
|
||||||
|
newPVC, ok := new.(*v1.PersistentVolumeClaim)
|
||||||
|
if !ok {
|
||||||
|
glog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", new)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldPVC, ok := old.(*v1.PersistentVolumeClaim)
|
||||||
|
if !ok {
|
||||||
|
glog.Errorf("cannot convert to *v1.PersistentVolumeClaim: %v", old)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.invalidatePredicatesForPvcUpdate(oldPVC, newPVC)
|
||||||
|
}
|
||||||
|
c.podQueue.MoveAllToActiveQueue()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configFactory) onPvcDelete(obj interface{}) {
|
func (c *configFactory) onPvcDelete(obj interface{}) {
|
||||||
if c.enableEquivalenceClassCache {
|
if c.enableEquivalenceClassCache {
|
||||||
var pvc *v1.PersistentVolumeClaim
|
var pvc *v1.PersistentVolumeClaim
|
||||||
@ -407,6 +463,21 @@ func (c *configFactory) invalidatePredicatesForPvc(pvc *v1.PersistentVolumeClaim
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configFactory) invalidatePredicatesForPvcUpdate(old, new *v1.PersistentVolumeClaim) {
|
||||||
|
invalidPredicates := sets.NewString()
|
||||||
|
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
|
if old.Spec.VolumeName != new.Spec.VolumeName {
|
||||||
|
// PVC volume binding has changed
|
||||||
|
invalidPredicates.Insert(predicates.CheckVolumeBinding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if invalidPredicates.Len() > 0 {
|
||||||
|
c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(invalidPredicates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *configFactory) onServiceAdd(obj interface{}) {
|
func (c *configFactory) onServiceAdd(obj interface{}) {
|
||||||
if c.enableEquivalenceClassCache {
|
if c.enableEquivalenceClassCache {
|
||||||
c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(serviceAffinitySet)
|
c.equivalencePodCache.InvalidateCachedPredicateItemOfAllNodes(serviceAffinitySet)
|
||||||
@ -468,6 +539,7 @@ func (c *configFactory) addPodToCache(obj interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.podQueue.AssignedPodAdded(pod)
|
c.podQueue.AssignedPodAdded(pod)
|
||||||
|
|
||||||
// NOTE: Updating equivalence cache of addPodToCache has been
|
// NOTE: Updating equivalence cache of addPodToCache has been
|
||||||
// handled optimistically in InvalidateCachedPredicateItemForPodAdd.
|
// handled optimistically in InvalidateCachedPredicateItemForPodAdd.
|
||||||
}
|
}
|
||||||
@ -830,7 +902,8 @@ func (f *configFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String,
|
|||||||
f.equivalencePodCache = core.NewEquivalenceCache(getEquivalencePodFunc)
|
f.equivalencePodCache = core.NewEquivalenceCache(getEquivalencePodFunc)
|
||||||
glog.Info("Created equivalence class cache")
|
glog.Info("Created equivalence class cache")
|
||||||
}
|
}
|
||||||
algo := core.NewGenericScheduler(f.schedulerCache, f.equivalencePodCache, f.podQueue, predicateFuncs, predicateMetaProducer, priorityConfigs, priorityMetaProducer, extenders)
|
|
||||||
|
algo := core.NewGenericScheduler(f.schedulerCache, f.equivalencePodCache, f.podQueue, predicateFuncs, predicateMetaProducer, priorityConfigs, priorityMetaProducer, extenders, f.volumeBinder)
|
||||||
|
|
||||||
podBackoff := util.CreateDefaultPodBackoff()
|
podBackoff := util.CreateDefaultPodBackoff()
|
||||||
return &scheduler.Config{
|
return &scheduler.Config{
|
||||||
@ -850,6 +923,7 @@ func (f *configFactory) CreateFromKeys(predicateKeys, priorityKeys sets.String,
|
|||||||
},
|
},
|
||||||
Error: f.MakeDefaultErrorFunc(podBackoff, f.podQueue),
|
Error: f.MakeDefaultErrorFunc(podBackoff, f.podQueue),
|
||||||
StopEverything: f.StopEverything,
|
StopEverything: f.StopEverything,
|
||||||
|
VolumeBinder: f.volumeBinder,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,6 +981,8 @@ func (f *configFactory) getPluginArgs() (*PluginFactoryArgs, error) {
|
|||||||
NodeInfo: &predicates.CachedNodeInfo{NodeLister: f.nodeLister},
|
NodeInfo: &predicates.CachedNodeInfo{NodeLister: f.nodeLister},
|
||||||
PVInfo: &predicates.CachedPersistentVolumeInfo{PersistentVolumeLister: f.pVLister},
|
PVInfo: &predicates.CachedPersistentVolumeInfo{PersistentVolumeLister: f.pVLister},
|
||||||
PVCInfo: &predicates.CachedPersistentVolumeClaimInfo{PersistentVolumeClaimLister: f.pVCLister},
|
PVCInfo: &predicates.CachedPersistentVolumeClaimInfo{PersistentVolumeClaimLister: f.pVCLister},
|
||||||
|
StorageClassInfo: &predicates.CachedStorageClassInfo{StorageClassLister: f.storageClassLister},
|
||||||
|
VolumeBinder: f.volumeBinder,
|
||||||
HardPodAffinitySymmetricWeight: f.hardPodAffinitySymmetricWeight,
|
HardPodAffinitySymmetricWeight: f.hardPodAffinitySymmetricWeight,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -1047,6 +1123,7 @@ func (factory *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, pod
|
|||||||
Namespace: pod.Namespace,
|
Namespace: pod.Namespace,
|
||||||
Name: pod.Name,
|
Name: pod.Name,
|
||||||
}
|
}
|
||||||
|
origPod := pod
|
||||||
|
|
||||||
// When pod priority is enabled, we would like to place an unschedulable
|
// When pod priority is enabled, we would like to place an unschedulable
|
||||||
// pod in the unschedulable queue. This ensures that if the pod is nominated
|
// pod in the unschedulable queue. This ensures that if the pod is nominated
|
||||||
@ -1066,11 +1143,21 @@ func (factory *configFactory) MakeDefaultErrorFunc(backoff *util.PodBackoff, pod
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
if len(pod.Spec.NodeName) == 0 {
|
if len(pod.Spec.NodeName) == 0 {
|
||||||
podQueue.AddUnschedulableIfNotPresent(pod)
|
podQueue.AddUnschedulableIfNotPresent(pod)
|
||||||
|
} else {
|
||||||
|
if factory.volumeBinder != nil {
|
||||||
|
// Volume binder only wants to keep unassigned pods
|
||||||
|
factory.volumeBinder.DeletePodBindings(pod)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
glog.Warningf("A pod %v no longer exists", podID)
|
glog.Warningf("A pod %v no longer exists", podID)
|
||||||
|
|
||||||
|
if factory.volumeBinder != nil {
|
||||||
|
// Volume binder only wants to keep unassigned pods
|
||||||
|
factory.volumeBinder.DeletePodBindings(origPod)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
glog.Errorf("Error getting pod %v for retry: %v; retrying...", podID, err)
|
glog.Errorf("Error getting pod %v for retry: %v; retrying...", podID, err)
|
||||||
|
@ -66,6 +66,7 @@ func TestCreate(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -99,6 +100,7 @@ func TestCreateFromConfig(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -159,6 +161,7 @@ func TestCreateFromConfigWithHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -220,6 +223,7 @@ func TestCreateFromEmptyConfig(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -278,6 +282,7 @@ func TestDefaultErrorFunc(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -388,6 +393,7 @@ func TestInvalidHardPodAffinitySymmetricWeight(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
-1,
|
-1,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
@ -435,6 +441,7 @@ func TestInvalidFactoryArgs(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
test.hardPodAffinitySymmetricWeight,
|
test.hardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
|
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/kubernetes/plugin/pkg/scheduler/volumebinder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PluginFactoryArgs are passed to all plugin factory functions.
|
// PluginFactoryArgs are passed to all plugin factory functions.
|
||||||
@ -43,6 +44,8 @@ type PluginFactoryArgs struct {
|
|||||||
NodeInfo predicates.NodeInfo
|
NodeInfo predicates.NodeInfo
|
||||||
PVInfo predicates.PersistentVolumeInfo
|
PVInfo predicates.PersistentVolumeInfo
|
||||||
PVCInfo predicates.PersistentVolumeClaimInfo
|
PVCInfo predicates.PersistentVolumeClaimInfo
|
||||||
|
StorageClassInfo predicates.StorageClassInfo
|
||||||
|
VolumeBinder *volumebinder.VolumeBinder
|
||||||
HardPodAffinitySymmetricWeight int32
|
HardPodAffinitySymmetricWeight int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
|
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||||
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
|
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
|
||||||
"k8s.io/kubernetes/plugin/pkg/scheduler/core"
|
"k8s.io/kubernetes/plugin/pkg/scheduler/core"
|
||||||
@ -129,6 +130,8 @@ type Config struct {
|
|||||||
|
|
||||||
// Close this to shut down the scheduler.
|
// Close this to shut down the scheduler.
|
||||||
StopEverything chan struct{}
|
StopEverything chan struct{}
|
||||||
|
|
||||||
|
VolumeBinder persistentvolume.SchedulerVolumeBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromConfigurator returns a new scheduler that is created entirely by the Configurator. Assumes Create() is implemented.
|
// NewFromConfigurator returns a new scheduler that is created entirely by the Configurator. Assumes Create() is implemented.
|
||||||
|
@ -528,7 +528,8 @@ func setupTestScheduler(queuedPodStore *clientcache.FIFO, scache schedulercache.
|
|||||||
algorithm.EmptyPredicateMetadataProducer,
|
algorithm.EmptyPredicateMetadataProducer,
|
||||||
[]algorithm.PriorityConfig{},
|
[]algorithm.PriorityConfig{},
|
||||||
algorithm.EmptyMetadataProducer,
|
algorithm.EmptyMetadataProducer,
|
||||||
[]algorithm.SchedulerExtender{})
|
[]algorithm.SchedulerExtender{},
|
||||||
|
nil)
|
||||||
bindingChan := make(chan *v1.Binding, 1)
|
bindingChan := make(chan *v1.Binding, 1)
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
configurator := &FakeConfigurator{
|
configurator := &FakeConfigurator{
|
||||||
@ -566,7 +567,8 @@ func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, sc
|
|||||||
algorithm.EmptyPredicateMetadataProducer,
|
algorithm.EmptyPredicateMetadataProducer,
|
||||||
[]algorithm.PriorityConfig{},
|
[]algorithm.PriorityConfig{},
|
||||||
algorithm.EmptyMetadataProducer,
|
algorithm.EmptyMetadataProducer,
|
||||||
[]algorithm.SchedulerExtender{})
|
[]algorithm.SchedulerExtender{},
|
||||||
|
nil)
|
||||||
bindingChan := make(chan *v1.Binding, 2)
|
bindingChan := make(chan *v1.Binding, 2)
|
||||||
configurator := &FakeConfigurator{
|
configurator := &FakeConfigurator{
|
||||||
Config: &Config{
|
Config: &Config{
|
||||||
|
74
plugin/pkg/scheduler/volumebinder/volume_binder.go
Normal file
74
plugin/pkg/scheduler/volumebinder/volume_binder.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package volumebinder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
|
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||||
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VolumeBinder sets up the volume binding library and manages
|
||||||
|
// the volume binding operations with a queue.
|
||||||
|
type VolumeBinder struct {
|
||||||
|
Binder persistentvolume.SchedulerVolumeBinder
|
||||||
|
BindQueue *workqueue.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVolumeBinder sets up the volume binding library and binding queue
|
||||||
|
func NewVolumeBinder(
|
||||||
|
client clientset.Interface,
|
||||||
|
pvcInformer coreinformers.PersistentVolumeClaimInformer,
|
||||||
|
pvInformer coreinformers.PersistentVolumeInformer,
|
||||||
|
nodeInformer coreinformers.NodeInformer,
|
||||||
|
storageClassInformer storageinformers.StorageClassInformer) *VolumeBinder {
|
||||||
|
|
||||||
|
return &VolumeBinder{
|
||||||
|
Binder: persistentvolume.NewVolumeBinder(client, pvcInformer, pvInformer, nodeInformer, storageClassInformer),
|
||||||
|
BindQueue: workqueue.NewNamed("podsToBind"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFakeVolumeBinder sets up a fake volume binder and binding queue
|
||||||
|
func NewFakeVolumeBinder(config *persistentvolume.FakeVolumeBinderConfig) *VolumeBinder {
|
||||||
|
return &VolumeBinder{
|
||||||
|
Binder: persistentvolume.NewFakeVolumeBinder(config),
|
||||||
|
BindQueue: workqueue.NewNamed("podsToBind"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run starts a goroutine to handle the binding queue with the given function.
|
||||||
|
func (b *VolumeBinder) Run(bindWorkFunc func(), stopCh <-chan struct{}) {
|
||||||
|
go wait.Until(bindWorkFunc, time.Second, stopCh)
|
||||||
|
|
||||||
|
<-stopCh
|
||||||
|
b.BindQueue.ShutDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePodBindings will delete the cached volume bindings for the given pod.
|
||||||
|
func (b *VolumeBinder) DeletePodBindings(pod *v1.Pod) {
|
||||||
|
cache := b.Binder.GetBindingsCache()
|
||||||
|
if cache != nil && pod != nil {
|
||||||
|
cache.DeleteBindings(pod)
|
||||||
|
}
|
||||||
|
}
|
@ -369,6 +369,7 @@ func TestSchedulerExtender(t *testing.T) {
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
|
@ -469,6 +469,7 @@ func TestMultiScheduler(t *testing.T) {
|
|||||||
informerFactory2.Apps().V1beta1().StatefulSets(),
|
informerFactory2.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory2.Core().V1().Services(),
|
informerFactory2.Core().V1().Services(),
|
||||||
informerFactory2.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory2.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory2.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
|
@ -131,6 +131,7 @@ func TestTaintNodeByCondition(t *testing.T) {
|
|||||||
informers.Apps().V1beta1().StatefulSets(),
|
informers.Apps().V1beta1().StatefulSets(),
|
||||||
informers.Core().V1().Services(),
|
informers.Core().V1().Services(),
|
||||||
informers.Policy().V1beta1().PodDisruptionBudgets(),
|
informers.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informers.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
true, // Enable EqualCache by default.
|
true, // Enable EqualCache by default.
|
||||||
)
|
)
|
||||||
|
@ -78,6 +78,7 @@ func initTest(t *testing.T, nsPrefix string) *TestContext {
|
|||||||
context.informerFactory.Apps().V1beta1().StatefulSets(),
|
context.informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
context.informerFactory.Core().V1().Services(),
|
context.informerFactory.Core().V1().Services(),
|
||||||
context.informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
context.informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
context.informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
@ -75,6 +75,7 @@ func mustSetupScheduler() (schedulerConfigurator scheduler.Configurator, destroy
|
|||||||
informerFactory.Apps().V1beta1().StatefulSets(),
|
informerFactory.Apps().V1beta1().StatefulSets(),
|
||||||
informerFactory.Core().V1().Services(),
|
informerFactory.Core().V1().Services(),
|
||||||
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
informerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||||
|
informerFactory.Storage().V1().StorageClasses(),
|
||||||
v1.DefaultHardPodAffinitySymmetricWeight,
|
v1.DefaultHardPodAffinitySymmetricWeight,
|
||||||
enableEquivalenceCache,
|
enableEquivalenceCache,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user