diff --git a/cluster-autoscaler/loop/trigger.go b/cluster-autoscaler/loop/trigger.go index 85d6e14b2237..093773cb9d0f 100644 --- a/cluster-autoscaler/loop/trigger.go +++ b/cluster-autoscaler/loop/trigger.go @@ -43,8 +43,12 @@ type scalingTimesGetter interface { LastScaleDownDeleteTime() time.Time } -type provisioningRequestProcessTimeGetter interface { - LastProvisioningRequestProcessedTime() time.Time +// provisioningRequestProcessingTimesGetter exposes recent provisioning request processing activity regardless of wether the +// ProvisioningRequest was marked as accepted or failed. This is because a ProvisioningRequest being processed indicates that +// there are other ProvisioningRequests that require processing regardless of the outcome of the current one. Thus, the next iteration +// should be started immediately. +type provisioningRequestProcessingTimesGetter interface { + LastProvisioningRequestProcessTime() time.Time } // LoopTrigger object implements criteria used to start new autoscaling iteration @@ -52,11 +56,11 @@ type LoopTrigger struct { podObserver *UnschedulablePodObserver scanInterval time.Duration scalingTimesGetter scalingTimesGetter - provisioningRequestProcessTimeGetter provisioningRequestProcessTimeGetter + provisioningRequestProcessTimeGetter provisioningRequestProcessingTimesGetter } // NewLoopTrigger creates a LoopTrigger object -func NewLoopTrigger(podObserver *UnschedulablePodObserver, scalingTimesGetter scalingTimesGetter, scanInterval time.Duration, provisioningRequestProcessTimeGetter provisioningRequestProcessTimeGetter) *LoopTrigger { +func NewLoopTrigger(podObserver *UnschedulablePodObserver, scalingTimesGetter scalingTimesGetter, provisioningRequestProcessTimeGetter provisioningRequestProcessingTimesGetter, scanInterval time.Duration) *LoopTrigger { return &LoopTrigger{ podObserver: podObserver, scanInterval: scanInterval, @@ -74,7 +78,7 @@ func (t *LoopTrigger) Wait(lastRun time.Time) { // immediately if the previous one was productive. if !t.scalingTimesGetter.LastScaleUpTime().Before(lastRun) || !t.scalingTimesGetter.LastScaleDownDeleteTime().Before(lastRun) || - !t.provisioningRequestProcessTimeGetter.LastProvisioningRequestProcessedTime().Before(lastRun) { + !t.provisioningRequestProcessTimeGetter.LastProvisioningRequestProcessTime().Before(lastRun) { select { case <-t.podObserver.unschedulablePodChan: klog.Info("Autoscaler loop triggered by unschedulable pod appearing") diff --git a/cluster-autoscaler/main.go b/cluster-autoscaler/main.go index 3d8b57b890bf..8ce451705315 100644 --- a/cluster-autoscaler/main.go +++ b/cluster-autoscaler/main.go @@ -633,7 +633,10 @@ func run(healthCheck *metrics.HealthCheck, debuggingSnapshotter debuggingsnapsho defer cancel() if *frequentLoopsEnabled { podObserver := loop.StartPodObserver(context, kube_util.CreateKubeClient(createAutoscalingOptions().KubeClientOpts)) - trigger := loop.NewLoopTrigger(podObserver, autoscaler, *scanInterval, injector) + // A ProvisioningRequestPodsInjector is used as provisioningRequestProcessingTimesGetter here to obtain the last time a + // ProvisioningRequest was processed. This is because the ProvisioningRequestPodsInjector in addition to injecting pods + // also marks the ProvisioningRequest as accepted or failed. + trigger := loop.NewLoopTrigger(podObserver, autoscaler, injector, *scanInterval) lastRun := time.Now() for { trigger.Wait(lastRun) diff --git a/cluster-autoscaler/processors/provreq/injector.go b/cluster-autoscaler/processors/provreq/injector.go index b4718c1ec5d7..94eb0a3f2ea7 100644 --- a/cluster-autoscaler/processors/provreq/injector.go +++ b/cluster-autoscaler/processors/provreq/injector.go @@ -24,7 +24,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/autoscaler/cluster-autoscaler/apis/provisioningrequest/autoscaling.x-k8s.io/v1" "k8s.io/autoscaler/cluster-autoscaler/context" - // "k8s.io/autoscaler/cluster-autoscaler/processors/pods" "k8s.io/autoscaler/cluster-autoscaler/provisioningrequest" provreqconditions "k8s.io/autoscaler/cluster-autoscaler/provisioningrequest/conditions" provreqpods "k8s.io/autoscaler/cluster-autoscaler/provisioningrequest/pods" @@ -147,7 +146,7 @@ func NewProvisioningRequestPodsInjector(kubeConfig *rest.Config) (*ProvisioningR return &ProvisioningRequestPodsInjector{client: client, clock: clock.RealClock{}}, nil } -// LastProvisioningRequestProcessedTime returns the time when the last provisioning request was processed. -func (p *ProvisioningRequestPodsInjector) LastProvisioningRequestProcessedTime() time.Time { +// LastProvisioningRequestProcessTime returns the time when the last provisioning request was processed. +func (p *ProvisioningRequestPodsInjector) LastProvisioningRequestProcessTime() time.Time { return p.lastProvisioningRequestProcessedTime }