Enhancements to scheduler priority functions
- Modified the existing spreading priority to consider service pods explicitly - Added a new priority function to spread pods across zones
This commit is contained in:
@@ -31,11 +31,11 @@ func defaultPredicates() util.StringSet {
|
||||
return util.NewStringSet(
|
||||
// Fit is defined based on the absence of port conflicts.
|
||||
factory.RegisterFitPredicate("PodFitsPorts", algorithm.PodFitsPorts),
|
||||
// Fit is determined by resource availability
|
||||
// Fit is determined by resource availability.
|
||||
factory.RegisterFitPredicate("PodFitsResources", algorithm.NewResourceFitPredicate(factory.MinionLister)),
|
||||
// Fit is determined by non-conflicting disk volumes
|
||||
// Fit is determined by non-conflicting disk volumes.
|
||||
factory.RegisterFitPredicate("NoDiskConflict", algorithm.NoDiskConflict),
|
||||
// Fit is determined by node selector query
|
||||
// Fit is determined by node selector query.
|
||||
factory.RegisterFitPredicate("MatchNodeSelector", algorithm.NewSelectorMatchPredicate(factory.MinionLister)),
|
||||
// Fit is determined by the presence of the Host parameter and a string match
|
||||
factory.RegisterFitPredicate("HostName", algorithm.PodFitsHost),
|
||||
@@ -46,8 +46,11 @@ func defaultPriorities() util.StringSet {
|
||||
return util.NewStringSet(
|
||||
// Prioritize nodes by least requested utilization.
|
||||
factory.RegisterPriorityFunction("LeastRequestedPriority", algorithm.LeastRequestedPriority, 1),
|
||||
// spreads pods by minimizing the number of pods on the same minion with the same labels.
|
||||
factory.RegisterPriorityFunction("SpreadingPriority", algorithm.CalculateSpreadPriority, 1),
|
||||
// spreads pods by minimizing the number of pods (belonging to the same service) on the same minion.
|
||||
factory.RegisterPriorityFunction("ServiceSpreadingPriority", algorithm.NewServiceSpreadPriority(factory.ServiceLister), 1),
|
||||
// spreads pods belonging to the same service across minions in different zones
|
||||
// TODO: remove the hardcoding of the "zone" label and move it to a constant
|
||||
factory.RegisterPriorityFunction("ZoneSpreadingPriority", algorithm.NewZoneSpreadPriority(factory.ServiceLister, "zone"), 1),
|
||||
// EqualPriority is a prioritizer function that gives an equal weight of one to all minions
|
||||
factory.RegisterPriorityFunction("EqualPriority", algorithm.EqualPriority, 0),
|
||||
)
|
||||
|
@@ -35,8 +35,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
PodLister = &cache.StoreToPodLister{cache.NewStore()}
|
||||
MinionLister = &cache.StoreToNodeLister{cache.NewStore()}
|
||||
PodLister = &cache.StoreToPodLister{cache.NewStore()}
|
||||
MinionLister = &cache.StoreToNodeLister{cache.NewStore()}
|
||||
ServiceLister = &cache.StoreToServiceLister{cache.NewStore()}
|
||||
)
|
||||
|
||||
// ConfigFactory knows how to fill out a scheduler config with its support functions.
|
||||
@@ -48,15 +49,18 @@ type ConfigFactory struct {
|
||||
PodLister *cache.StoreToPodLister
|
||||
// a means to list all minions
|
||||
MinionLister *cache.StoreToNodeLister
|
||||
// a means to list all services
|
||||
ServiceLister *cache.StoreToServiceLister
|
||||
}
|
||||
|
||||
// NewConfigFactory initializes the factory.
|
||||
func NewConfigFactory(client *client.Client) *ConfigFactory {
|
||||
return &ConfigFactory{
|
||||
Client: client,
|
||||
PodQueue: cache.NewFIFO(),
|
||||
PodLister: PodLister,
|
||||
MinionLister: MinionLister,
|
||||
Client: client,
|
||||
PodQueue: cache.NewFIFO(),
|
||||
PodLister: PodLister,
|
||||
MinionLister: MinionLister,
|
||||
ServiceLister: ServiceLister,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +109,11 @@ func (f *ConfigFactory) CreateFromKeys(predicateKeys, priorityKeys util.StringSe
|
||||
cache.NewPoller(f.pollMinions, 10*time.Second, f.MinionLister.Store).Run()
|
||||
}
|
||||
|
||||
// Watch and cache all service objects. Scheduler needs to find all pods
|
||||
// created by the same service, so that it can spread them correctly.
|
||||
// Cache this locally.
|
||||
cache.NewReflector(f.createServiceLW(), &api.Service{}, f.ServiceLister.Store).Run()
|
||||
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
algo := algorithm.NewGenericScheduler(predicateFuncs, priorityConfigs, f.PodLister, r)
|
||||
@@ -178,6 +187,15 @@ func (factory *ConfigFactory) pollMinions() (cache.Enumerator, error) {
|
||||
return &nodeEnumerator{list}, nil
|
||||
}
|
||||
|
||||
// createServiceLW returns a listWatch that gets all changes to services.
|
||||
func (factory *ConfigFactory) createServiceLW() *listWatch {
|
||||
return &listWatch{
|
||||
client: factory.Client,
|
||||
fieldSelector: parseSelectorOrDie(""),
|
||||
resource: "services",
|
||||
}
|
||||
}
|
||||
|
||||
func (factory *ConfigFactory) makeDefaultErrorFunc(backoff *podBackoff, podQueue *cache.FIFO) func(pod *api.Pod, err error) {
|
||||
return func(pod *api.Pod, err error) {
|
||||
glog.Errorf("Error scheduling %v %v: %v; retrying", pod.Namespace, pod.Name, err)
|
||||
@@ -208,6 +226,35 @@ type nodeEnumerator struct {
|
||||
*api.NodeList
|
||||
}
|
||||
|
||||
// storeToServiceLister turns a store into a service lister. The store must contain (only) services.
|
||||
type storeToServiceLister struct {
|
||||
cache.Store
|
||||
}
|
||||
|
||||
func (s *storeToServiceLister) ListServices() (services api.ServiceList, err error) {
|
||||
for _, m := range s.List() {
|
||||
services.Items = append(services.Items, *(m.(*api.Service)))
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
func (s *storeToServiceLister) GetPodService(pod api.Pod) (service api.Service, err error) {
|
||||
var selector labels.Selector
|
||||
|
||||
for _, m := range s.List() {
|
||||
service = *m.(*api.Service)
|
||||
// consider only services that are in the same namespace as the pod
|
||||
if service.Namespace != pod.Namespace {
|
||||
continue
|
||||
}
|
||||
selector = labels.Set(service.Spec.Selector).AsSelector()
|
||||
if selector.Matches(labels.Set(pod.Labels)) {
|
||||
return service, nil
|
||||
}
|
||||
}
|
||||
return service, fmt.Errorf("Could not find service for pod %s in namespace %s with labels: %v", pod.Name, pod.Namespace, pod.Labels)
|
||||
}
|
||||
|
||||
// Len returns the number of items in the node list.
|
||||
func (ne *nodeEnumerator) Len() int {
|
||||
if ne.NodeList == nil {
|
||||
|
Reference in New Issue
Block a user