Merge pull request #281 from MaciekPytel/disable_affinity_predicate
Disable MatchInterPodAffinity if there are no pods using affinity
This commit is contained in:
commit
7c1aa113f8
|
|
@ -187,6 +187,8 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) errors.AutoscalerError
|
|||
return errors.ToAutoscalerError(errors.ApiCallError, err)
|
||||
}
|
||||
|
||||
ConfigurePredicateCheckerForLoop(allUnschedulablePods, allScheduled, a.PredicateChecker)
|
||||
|
||||
// We need to check whether pods marked as unschedulable are actually unschedulable.
|
||||
// It's likely we added a new node and the scheduler just haven't managed to put the
|
||||
// pod on in yet. In this situation we don't want to trigger another scale-up.
|
||||
|
|
|
|||
|
|
@ -387,3 +387,27 @@ func getPotentiallyUnneededNodes(context *AutoscalingContext, nodes []*apiv1.Nod
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ConfigurePredicateCheckerForLoop can be run to update predicateChecker configuration
|
||||
// based on current state of the cluster.
|
||||
func ConfigurePredicateCheckerForLoop(unschedulablePods []*apiv1.Pod, schedulablePods []*apiv1.Pod, predicateChecker *simulator.PredicateChecker) {
|
||||
podsWithAffinityFound := false
|
||||
for _, pod := range unschedulablePods {
|
||||
if pod.Spec.Affinity != nil {
|
||||
podsWithAffinityFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !podsWithAffinityFound {
|
||||
for _, pod := range schedulablePods {
|
||||
if pod.Spec.Affinity != nil {
|
||||
podsWithAffinityFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
predicateChecker.SetAffinityPredicateEnabled(podsWithAffinityFound)
|
||||
if !podsWithAffinityFound {
|
||||
glog.V(1).Info("No pod using affinity / antiaffinity found in cluster, disabling affinity predicate for this loop")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ const (
|
|||
// This significantly improves performance and is useful if the error message
|
||||
// is discarded anyway.
|
||||
ReturnSimpleError ErrorVerbosity = false
|
||||
|
||||
// We want to disable affinity predicate for performance reasons if no ppod
|
||||
// requires it
|
||||
affinityPredicateName = "MatchInterPodAffinity"
|
||||
)
|
||||
|
||||
type predicateInfo struct {
|
||||
|
|
@ -57,6 +61,7 @@ type predicateInfo struct {
|
|||
type PredicateChecker struct {
|
||||
predicates []predicateInfo
|
||||
predicateMetadataProducer algorithm.MetadataProducer
|
||||
enableAffinityPredicate bool
|
||||
}
|
||||
|
||||
// there are no const arrays in go, this is meant to be used as a const
|
||||
|
|
@ -124,6 +129,7 @@ func NewPredicateChecker(kubeClient kube_client.Interface, stop <-chan struct{})
|
|||
return &PredicateChecker{
|
||||
predicates: predicateList,
|
||||
predicateMetadataProducer: metadataProducer,
|
||||
enableAffinityPredicate: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -149,12 +155,24 @@ func NewTestPredicateChecker() *PredicateChecker {
|
|||
}
|
||||
}
|
||||
|
||||
// SetAffinityPredicateEnabled can be used to enable or disable checking MatchInterPodAffinity
|
||||
// predicate. This will cause incorrect CA behavior if there is at least a single pod in
|
||||
// cluster using affinity/antiaffinity. However, checking affinity predicate is extremly
|
||||
// costly even if no pod is using it, so it may be worth disabling it in such situation.
|
||||
func (p *PredicateChecker) SetAffinityPredicateEnabled(enable bool) {
|
||||
p.enableAffinityPredicate = enable
|
||||
}
|
||||
|
||||
// GetPredicateMetadata precomputes some information useful for running predicates on a given pod in a given state
|
||||
// of the cluster (represented by nodeInfos map). Passing the result of this function to CheckPredicates can significantly
|
||||
// improve the performance of running predicates, especially MatchInterPodAffinity predicate. However, calculating
|
||||
// predicateMetadata is also quite expensive, so it's not always the best option to run this method.
|
||||
// Please refer to https://github.com/kubernetes/autoscaler/issues/257 for more details.
|
||||
func (p *PredicateChecker) GetPredicateMetadata(pod *apiv1.Pod, nodeInfos map[string]*schedulercache.NodeInfo) interface{} {
|
||||
// skip precomputation if affinity predicate is disabled - it's not worth it performance wise
|
||||
if !p.enableAffinityPredicate {
|
||||
return nil
|
||||
}
|
||||
return p.predicateMetadataProducer(pod, nodeInfos)
|
||||
}
|
||||
|
||||
|
|
@ -183,6 +201,12 @@ func (p *PredicateChecker) FitsAny(pod *apiv1.Pod, nodeInfos map[string]*schedul
|
|||
// Alternatively you can pass nil as predicateMetadata.
|
||||
func (p *PredicateChecker) CheckPredicates(pod *apiv1.Pod, predicateMetadata interface{}, nodeInfo *schedulercache.NodeInfo, verbosity ErrorVerbosity) error {
|
||||
for _, predInfo := range p.predicates {
|
||||
|
||||
// skip affinity predicate if it has been disabled
|
||||
if !p.enableAffinityPredicate && predInfo.name == affinityPredicateName {
|
||||
continue
|
||||
}
|
||||
|
||||
match, failureReason, err := predInfo.predicate(pod, predicateMetadata, nodeInfo)
|
||||
|
||||
if verbosity == ReturnSimpleError && (err != nil || !match) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue