mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-10 13:42:02 +00:00
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:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user