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:
Abhishek Gupta
2014-12-12 14:29:20 -08:00
parent 3ca6c231b2
commit 04db076e5f
5 changed files with 399 additions and 41 deletions

View File

@@ -17,28 +17,44 @@ limitations under the License.
package scheduler
import (
"math/rand"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
)
type ServiceSpread struct {
serviceLister ServiceLister
}
func NewServiceSpreadPriority(serviceLister ServiceLister) PriorityFunction {
serviceSpread := &ServiceSpread{
serviceLister: serviceLister,
}
return serviceSpread.CalculateSpreadPriority
}
// CalculateSpreadPriority spreads pods by minimizing the number of pods on the same machine with the same labels.
// Importantly, if there are services in the system that span multiple heterogenous sets of pods, this spreading priority
// may not provide optimal spreading for the members of that Service.
// TODO: consider if we want to include Service label sets in the scheduling priority.
func CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) {
pods, err := podLister.List(labels.SelectorFromSet(pod.Labels))
if err != nil {
return nil, err
func (s *ServiceSpread) CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) {
var maxCount int
var pods []api.Pod
var err error
service, err := s.serviceLister.GetPodService(pod)
if err == nil {
selector := labels.SelectorFromSet(service.Spec.Selector)
pods, err = podLister.ListPods(selector)
if err != nil {
return nil, err
}
}
minions, err := minionLister.List()
if err != nil {
return nil, err
}
var maxCount int
var fScore float32 = 10.0
counts := map[string]int{}
if len(pods) > 0 {
for _, pod := range pods {
@@ -54,6 +70,8 @@ func CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister Mini
//score int - scale of 0-10
// 0 being the lowest priority and 10 being the highest
for _, minion := range minions.Items {
// initializing to the default/max minion score of 10
fScore := float32(10)
if maxCount > 0 {
fScore = 10 * (float32(maxCount-counts[minion.Name]) / float32(maxCount))
}
@@ -62,6 +80,77 @@ func CalculateSpreadPriority(pod api.Pod, podLister PodLister, minionLister Mini
return result, nil
}
func NewSpreadingScheduler(podLister PodLister, minionLister MinionLister, predicates []FitPredicate, random *rand.Rand) Scheduler {
return NewGenericScheduler(predicates, []PriorityConfig{{Function: CalculateSpreadPriority, Weight: 1}}, podLister, random)
type ZoneSpread struct {
serviceLister ServiceLister
zoneLabel string
}
func NewZoneSpreadPriority(serviceLister ServiceLister, zoneLabel string) PriorityFunction {
zoneSpread := &ZoneSpread{
serviceLister: serviceLister,
zoneLabel: zoneLabel,
}
return zoneSpread.ZoneSpreadPriority
}
func (z *ZoneSpread) ZoneSpreadPriority(pod api.Pod, podLister PodLister, minionLister MinionLister) (HostPriorityList, error) {
var service api.Service
var pods []api.Pod
var err error
service, err = z.serviceLister.GetPodService(pod)
if err == nil {
selector := labels.SelectorFromSet(service.Spec.Selector)
pods, err = podLister.ListPods(selector)
if err != nil {
return nil, err
}
}
minions, err := minionLister.List()
if err != nil {
return nil, err
}
// find the zones that the minions belong to
openMinions := []string{}
zonedMinions := map[string]string{}
for _, minion := range minions.Items {
if labels.Set(minion.Labels).Has(z.zoneLabel) {
zone := labels.Set(minion.Labels).Get(z.zoneLabel)
zonedMinions[minion.Name] = zone
} else {
openMinions = append(openMinions, minion.Name)
}
}
podCounts := map[string]int{}
numServicePods := len(pods)
if numServicePods > 0 {
for _, pod := range pods {
zone, exists := zonedMinions[pod.Status.Host]
if !exists {
continue
}
podCounts[zone]++
}
}
result := []HostPriority{}
//score int - scale of 0-10
// 0 being the lowest priority and 10 being the highest
for minion := range zonedMinions {
// initializing to the default/max minion score of 10
fScore := float32(10)
if numServicePods > 0 {
fScore = 10 * (float32(numServicePods-podCounts[zonedMinions[minion]]) / float32(numServicePods))
}
result = append(result, HostPriority{host: minion, score: int(fScore)})
}
// add the open minions with a score of 0
for _, minion := range openMinions {
result = append(result, HostPriority{host: minion, score: 0})
}
return result, nil
}