// CalculateSpreadPriority spreads pods by minimizing the number of pods belonging to the same service // on the same machine. func (s *ServiceSpread) CalculateSpreadPriority(pod *api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (api.HostPriorityList, error) { var maxCount int var nsServicePods []*api.Pod services, err := s.serviceLister.GetPodServices(pod) if err == nil { // just use the first service and get the other pods within the service // TODO: a separate predicate can be created that tries to handle all services for the pod selector := labels.SelectorFromSet(services[0].Spec.Selector) pods, err := podLister.List(selector) if err != nil { return nil, err } // consider only the pods that belong to the same namespace for _, nsPod := range pods { if nsPod.Namespace == pod.Namespace { nsServicePods = append(nsServicePods, nsPod) } } } minions, err := minionLister.List() if err != nil { return nil, err } counts := map[string]int{} if len(nsServicePods) > 0 { for _, pod := range nsServicePods { counts[pod.Spec.NodeName]++ // Compute the maximum number of pods hosted on any minion if counts[pod.Spec.NodeName] > maxCount { maxCount = counts[pod.Spec.NodeName] } } } result := []api.HostPriority{} //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)) } result = append(result, api.HostPriority{Host: minion.Name, Score: int(fScore)}) glog.V(10).Infof( "%v -> %v: ServiceSpreadPriority, Score: (%d)", pod.Name, minion.Name, int(fScore), ) } return result, nil }
// MapPodsToMachines obtains a list of pods and pivots that list into a map where the keys are host names // and the values are the list of pods running on that host. func MapPodsToMachines(lister algorithm.PodLister) (map[string][]*api.Pod, error) { machineToPods := map[string][]*api.Pod{} // TODO: perform more targeted query... pods, err := lister.List(labels.Everything()) if err != nil { return map[string][]*api.Pod{}, err } for _, scheduledPod := range pods { host := scheduledPod.Spec.Host machineToPods[host] = append(machineToPods[host], scheduledPod) } return machineToPods, nil }
// CalculateSpreadPriority spreads pods by minimizing the number of pods belonging to the same service or replication controller. It counts number of pods that run under // Services or RCs as the pod being scheduled and tries to minimize the number of conflicts. I.e. pushes scheduler towards a Node where there's a smallest number of // pods which match the same selectors of Services and RCs as current pod. func (s *SelectorSpread) CalculateSpreadPriority(pod *api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { var maxCount int var nsPods []*api.Pod selectors := make([]labels.Selector, 0) services, err := s.serviceLister.GetPodServices(pod) if err == nil { for _, service := range services { selectors = append(selectors, labels.SelectorFromSet(service.Spec.Selector)) } } controllers, err := s.controllerLister.GetPodControllers(pod) if err == nil { for _, controller := range controllers { selectors = append(selectors, labels.SelectorFromSet(controller.Spec.Selector)) } } if len(selectors) > 0 { pods, err := podLister.List(labels.Everything()) if err != nil { return nil, err } // consider only the pods that belong to the same namespace for _, nsPod := range pods { if nsPod.Namespace == pod.Namespace { nsPods = append(nsPods, nsPod) } } } minions, err := minionLister.List() if err != nil { return nil, err } counts := map[string]int{} if len(nsPods) > 0 { for _, pod := range nsPods { matches := false for _, selector := range selectors { if selector.Matches(labels.Set(pod.ObjectMeta.Labels)) { matches = true break } } if matches { counts[pod.Spec.NodeName]++ // Compute the maximum number of pods hosted on any minion if counts[pod.Spec.NodeName] > maxCount { maxCount = counts[pod.Spec.NodeName] } } } } result := []algorithm.HostPriority{} //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)) } result = append(result, algorithm.HostPriority{Host: minion.Name, Score: int(fScore)}) glog.V(10).Infof( "%v -> %v: SelectorSpreadPriority, Score: (%d)", pod.Name, minion.Name, int(fScore), ) } return result, nil }
// CalculateAntiAffinityPriority spreads pods by minimizing the number of pods belonging to the same service // on machines with the same value for a particular label. // The label to be considered is provided to the struct (ServiceAntiAffinity). func (s *ServiceAntiAffinity) CalculateAntiAffinityPriority(pod *api.Pod, podLister algorithm.PodLister, minionLister algorithm.MinionLister) (algorithm.HostPriorityList, error) { var nsServicePods []*api.Pod services, err := s.serviceLister.GetPodServices(pod) if err == nil { // just use the first service and get the other pods within the service // TODO: a separate predicate can be created that tries to handle all services for the pod selector := labels.SelectorFromSet(services[0].Spec.Selector) pods, err := podLister.List(selector) if err != nil { return nil, err } // consider only the pods that belong to the same namespace for _, nsPod := range pods { if nsPod.Namespace == pod.Namespace { nsServicePods = append(nsServicePods, nsPod) } } } minions, err := minionLister.List() if err != nil { return nil, err } // separate out the minions that have the label from the ones that don't otherMinions := []string{} labeledMinions := map[string]string{} for _, minion := range minions.Items { if labels.Set(minion.Labels).Has(s.label) { label := labels.Set(minion.Labels).Get(s.label) labeledMinions[minion.Name] = label } else { otherMinions = append(otherMinions, minion.Name) } } podCounts := map[string]int{} for _, pod := range nsServicePods { label, exists := labeledMinions[pod.Spec.NodeName] if !exists { continue } podCounts[label]++ } numServicePods := len(nsServicePods) result := []algorithm.HostPriority{} //score int - scale of 0-10 // 0 being the lowest priority and 10 being the highest for minion := range labeledMinions { // initializing to the default/max minion score of 10 fScore := float32(10) if numServicePods > 0 { fScore = 10 * (float32(numServicePods-podCounts[labeledMinions[minion]]) / float32(numServicePods)) } result = append(result, algorithm.HostPriority{Host: minion, Score: int(fScore)}) } // add the open minions with a score of 0 for _, minion := range otherMinions { result = append(result, algorithm.HostPriority{Host: minion, Score: 0}) } return result, nil }