func (rc *replicationController) removePods(current types.PodLocations) error { currentNodes := current.Nodes() eligible, err := rc.eligibleNodes() if err != nil { return err } // If we need to downsize the number of nodes, prefer any in current that are not eligible anymore. // TODO: evaluate changes to 'eligible' more frequently preferred := types.NewNodeSet(currentNodes...).Difference(types.NewNodeSet(eligible...)) rest := types.NewNodeSet(currentNodes...).Difference(preferred) toUnschedule := len(current) - rc.ReplicasDesired rc.logger.NoFields().Infof("Need to unschedule %d nodes out of %s", toUnschedule, current) for i := 0; i < toUnschedule; i++ { unscheduleFrom, ok := preferred.PopAny() if !ok { var ok bool unscheduleFrom, ok = rest.PopAny() if !ok { // This should be mathematically impossible unless replicasDesired was negative return util.Errorf( "Unable to unschedule enough nodes to meet replicas desired: %d replicas desired, %d current.", rc.ReplicasDesired, len(current), ) } } err := rc.unschedule(unscheduleFrom) if err != nil { return err } } return nil }
func (rc *replicationController) addPods(current types.PodLocations) error { currentNodes := current.Nodes() eligible, err := rc.eligibleNodes() if err != nil { return err } // TODO: With Docker or runc we would not be constrained to running only once per node. // So it may be the case that we need to make the Scheduler interface smarter and use it here. possible := types.NewNodeSet(eligible...).Difference(types.NewNodeSet(currentNodes...)) // Users want deterministic ordering of nodes being populated to a new // RC. Move nodes in sorted order by hostname to achieve this possibleSorted := possible.ListNodes() toSchedule := rc.ReplicasDesired - len(currentNodes) rc.logger.NoFields().Infof("Need to schedule %d nodes out of %s", toSchedule, possible) for i := 0; i < toSchedule; i++ { if len(possibleSorted) < i+1 { errMsg := fmt.Sprintf( "Not enough nodes to meet desire: %d replicas desired, %d currentNodes, %d eligible. Scheduled on %d nodes instead.", rc.ReplicasDesired, len(currentNodes), len(eligible), i, ) err := rc.alerter.Alert(rc.alertInfo(errMsg)) if err != nil { rc.logger.WithError(err).Errorln("Unable to send alert") } return util.Errorf(errMsg) } scheduleOn := possibleSorted[i] err := rc.schedule(scheduleOn) if err != nil { return err } } return nil }