Skip iteration if pending pods are too new
This commit is contained in:
parent
8225983307
commit
15b10c8f67
|
|
@ -32,6 +32,11 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// How old the oldest unschedulable pod should be before starting scale up.
|
||||||
|
unschedulablePodTimeBuffer = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// StaticAutoscaler is an autoscaler which has all the core functionality of a CA but without the reconfiguration feature
|
// StaticAutoscaler is an autoscaler which has all the core functionality of a CA but without the reconfiguration feature
|
||||||
type StaticAutoscaler struct {
|
type StaticAutoscaler struct {
|
||||||
// AutoscalingContext consists of validated settings and options for this autoscaler
|
// AutoscalingContext consists of validated settings and options for this autoscaler
|
||||||
|
|
@ -240,10 +245,19 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) errors.AutoscalerError
|
||||||
glog.V(4).Info("No schedulable pods")
|
glog.V(4).Info("No schedulable pods")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If all pending pods are new we may want to skip a real scale down (just like if the pods were handled).
|
||||||
|
allPendingPodsToHelpAreNew := false
|
||||||
|
|
||||||
if len(unschedulablePodsToHelp) == 0 {
|
if len(unschedulablePodsToHelp) == 0 {
|
||||||
glog.V(1).Info("No unschedulable pods")
|
glog.V(1).Info("No unschedulable pods")
|
||||||
} else if a.MaxNodesTotal > 0 && len(readyNodes) >= a.MaxNodesTotal {
|
} else if a.MaxNodesTotal > 0 && len(readyNodes) >= a.MaxNodesTotal {
|
||||||
glog.V(1).Info("Max total nodes in cluster reached")
|
glog.V(1).Info("Max total nodes in cluster reached")
|
||||||
|
} else if getOldestCreateTime(unschedulablePodsToHelp).Add(unschedulablePodTimeBuffer).After(currentTime) {
|
||||||
|
// The assumption here is that these pods have been created very recently and probably there
|
||||||
|
// is more pods to come. In theory we could check the newest pod time but then if pod were created
|
||||||
|
// slowly but at the pace of 1 every 2 seconds then no scale up would be triggered for long time.
|
||||||
|
allPendingPodsToHelpAreNew = true
|
||||||
|
glog.V(1).Info("Unschedulable pods are very new, waiting one iteration for more")
|
||||||
} else {
|
} else {
|
||||||
daemonsets, err := a.ListerRegistry.DaemonSetLister().List()
|
daemonsets, err := a.ListerRegistry.DaemonSetLister().List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -301,7 +315,8 @@ func (a *StaticAutoscaler) RunOnce(currentTime time.Time) errors.AutoscalerError
|
||||||
a.lastScaleDownFailTime.Add(a.ScaleDownDelayAfterFailure).After(currentTime) ||
|
a.lastScaleDownFailTime.Add(a.ScaleDownDelayAfterFailure).After(currentTime) ||
|
||||||
a.lastScaleDownDeleteTime.Add(a.ScaleDownDelayAfterDelete).After(currentTime) ||
|
a.lastScaleDownDeleteTime.Add(a.ScaleDownDelayAfterDelete).After(currentTime) ||
|
||||||
schedulablePodsPresent ||
|
schedulablePodsPresent ||
|
||||||
scaleDown.nodeDeleteStatus.IsDeleteInProgress()
|
scaleDown.nodeDeleteStatus.IsDeleteInProgress() ||
|
||||||
|
allPendingPodsToHelpAreNew
|
||||||
|
|
||||||
glog.V(4).Infof("Scale down status: unneededOnly=%v lastScaleUpTime=%s "+
|
glog.V(4).Infof("Scale down status: unneededOnly=%v lastScaleUpTime=%s "+
|
||||||
"lastScaleDownDeleteTime=%v lastScaleDownFailTime=%s schedulablePodsPresent=%v isDeleteInProgress=%v",
|
"lastScaleDownDeleteTime=%v lastScaleDownFailTime=%s schedulablePodsPresent=%v isDeleteInProgress=%v",
|
||||||
|
|
|
||||||
|
|
@ -491,3 +491,13 @@ func UpdateClusterStateMetrics(csr *clusterstate.ClusterStateRegistry) {
|
||||||
readiness := csr.GetClusterReadiness()
|
readiness := csr.GetClusterReadiness()
|
||||||
metrics.UpdateNodesCount(readiness.Ready, readiness.Unready+readiness.LongNotStarted, readiness.NotStarted)
|
metrics.UpdateNodesCount(readiness.Ready, readiness.Unready+readiness.LongNotStarted, readiness.NotStarted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOldestCreateTime(pods []*apiv1.Pod) time.Time {
|
||||||
|
oldest := time.Now()
|
||||||
|
for _, pod := range pods {
|
||||||
|
if oldest.After(pod.CreationTimestamp.Time) {
|
||||||
|
oldest = pod.CreationTimestamp.Time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oldest
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -527,3 +527,15 @@ func TestGetNodeCoresAndMemory(t *testing.T) {
|
||||||
_, _, err = getNodeCoresAndMemory(node)
|
_, _, err = getNodeCoresAndMemory(node)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetOldestPod(t *testing.T) {
|
||||||
|
p1 := BuildTestPod("p1", 500, 1000)
|
||||||
|
p1.CreationTimestamp = metav1.NewTime(time.Now().Add(-1 * time.Minute))
|
||||||
|
p2 := BuildTestPod("p2", 500, 1000)
|
||||||
|
p2.CreationTimestamp = metav1.NewTime(time.Now().Add(+1 * time.Minute))
|
||||||
|
p3 := BuildTestPod("p3", 500, 1000)
|
||||||
|
p3.CreationTimestamp = metav1.NewTime(time.Now())
|
||||||
|
|
||||||
|
assert.Equal(t, p1.CreationTimestamp.Time, getOldestCreateTime([]*apiv1.Pod{p1, p2, p3}))
|
||||||
|
assert.Equal(t, p1.CreationTimestamp.Time, getOldestCreateTime([]*apiv1.Pod{p3, p2, p1}))
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue