@@ -22,6 +22,7 @@ import (
22
22
"time"
23
23
24
24
"github.com/golang/glog"
25
+ apiequality "k8s.io/apimachinery/pkg/api/equality"
25
26
"k8s.io/apimachinery/pkg/api/errors"
26
27
"k8s.io/apimachinery/pkg/api/resource"
27
28
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -371,14 +372,20 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
371
372
return fmt .Errorf ("failed to convert the given HPA to %s: %v" , autoscalingv2 .SchemeGroupVersion .String (), err )
372
373
}
373
374
hpa := hpaRaw .(* autoscalingv2.HorizontalPodAutoscaler )
375
+ hpaStatusOriginalRaw , err := api .Scheme .DeepCopy (& hpa .Status )
376
+ if err != nil {
377
+ a .eventRecorder .Event (hpav1Shared , v1 .EventTypeWarning , "FailedConvertHPA" , err .Error ())
378
+ return fmt .Errorf ("failed to deep-copy the HPA status: %v" , err )
379
+ }
380
+ hpaStatusOriginal := hpaStatusOriginalRaw .(* autoscalingv2.HorizontalPodAutoscalerStatus )
374
381
375
382
reference := fmt .Sprintf ("%s/%s/%s" , hpa .Spec .ScaleTargetRef .Kind , hpa .Namespace , hpa .Spec .ScaleTargetRef .Name )
376
383
377
384
scale , err := a .scaleNamespacer .Scales (hpa .Namespace ).Get (hpa .Spec .ScaleTargetRef .Kind , hpa .Spec .ScaleTargetRef .Name )
378
385
if err != nil {
379
386
a .eventRecorder .Event (hpa , v1 .EventTypeWarning , "FailedGetScale" , err .Error ())
380
387
setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionFalse , "FailedGetScale" , "the HPA controller was unable to get the target's current scale: %v" , err )
381
- a .update ( hpa )
388
+ a .updateStatusIfNeeded ( hpaStatusOriginal , hpa )
382
389
return fmt .Errorf ("failed to query scale subresource for %s: %v" , reference , err )
383
390
}
384
391
setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionTrue , "SucceededGetScale" , "the HPA controller was able to get the target's current scale" )
@@ -412,7 +419,10 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
412
419
} else {
413
420
metricDesiredReplicas , metricName , metricStatuses , metricTimestamp , err = a .computeReplicasForMetrics (hpa , scale , hpa .Spec .Metrics )
414
421
if err != nil {
415
- a .updateCurrentReplicasInStatus (hpa , currentReplicas )
422
+ a .setCurrentReplicasInStatus (hpa , currentReplicas )
423
+ if err := a .updateStatusIfNeeded (hpaStatusOriginal , hpa ); err != nil {
424
+ utilruntime .HandleError (err )
425
+ }
416
426
a .eventRecorder .Event (hpa , v1 .EventTypeWarning , "FailedComputeMetricsReplicas" , err .Error ())
417
427
return fmt .Errorf ("failed to compute desired number of replicas based on listed metrics for %s: %v" , reference , err )
418
428
}
@@ -489,7 +499,10 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
489
499
if err != nil {
490
500
a .eventRecorder .Eventf (hpa , v1 .EventTypeWarning , "FailedRescale" , "New size: %d; reason: %s; error: %v" , desiredReplicas , rescaleReason , err .Error ())
491
501
setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionFalse , "FailedUpdateScale" , "the HPA controller was unable to update the target scale: %v" , err )
492
- a .updateCurrentReplicasInStatus (hpa , currentReplicas )
502
+ a .setCurrentReplicasInStatus (hpa , currentReplicas )
503
+ if err := a .updateStatusIfNeeded (hpaStatusOriginal , hpa ); err != nil {
504
+ utilruntime .HandleError (err )
505
+ }
493
506
return fmt .Errorf ("failed to rescale %s: %v" , reference , err )
494
507
}
495
508
setCondition (hpa , autoscalingv2 .AbleToScale , v1 .ConditionTrue , "SucceededRescale" , "the HPA controller was able to update the target scale to %d" , desiredReplicas )
@@ -501,7 +514,8 @@ func (a *HorizontalController) reconcileAutoscaler(hpav1Shared *autoscalingv1.Ho
501
514
desiredReplicas = currentReplicas
502
515
}
503
516
504
- return a .updateStatusWithReplicas (hpa , currentReplicas , desiredReplicas , metricStatuses , rescale )
517
+ a .setStatus (hpa , currentReplicas , desiredReplicas , metricStatuses , rescale )
518
+ return a .updateStatusIfNeeded (hpaStatusOriginal , hpa )
505
519
}
506
520
507
521
func (a * HorizontalController ) shouldScale (hpa * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas int32 , timestamp time.Time ) bool {
@@ -528,14 +542,14 @@ func (a *HorizontalController) shouldScale(hpa *autoscalingv2.HorizontalPodAutos
528
542
return false
529
543
}
530
544
531
- func (a * HorizontalController ) updateCurrentReplicasInStatus (hpa * autoscalingv2.HorizontalPodAutoscaler , currentReplicas int32 ) {
532
- err := a .updateStatusWithReplicas (hpa , currentReplicas , hpa .Status .DesiredReplicas , hpa .Status .CurrentMetrics , false )
533
- if err != nil {
534
- utilruntime .HandleError (err )
535
- }
545
+ // setCurrentReplicasInStatus sets the current replica count in the status of the HPA.
546
+ func (a * HorizontalController ) setCurrentReplicasInStatus (hpa * autoscalingv2.HorizontalPodAutoscaler , currentReplicas int32 ) {
547
+ a .setStatus (hpa , currentReplicas , hpa .Status .DesiredReplicas , hpa .Status .CurrentMetrics , false )
536
548
}
537
549
538
- func (a * HorizontalController ) updateStatusWithReplicas (hpa * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas int32 , metricStatuses []autoscalingv2.MetricStatus , rescale bool ) error {
550
+ // setStatus recreates the status of the given HPA, updating the current and
551
+ // desired replicas, as well as the metric statuses
552
+ func (a * HorizontalController ) setStatus (hpa * autoscalingv2.HorizontalPodAutoscaler , currentReplicas , desiredReplicas int32 , metricStatuses []autoscalingv2.MetricStatus , rescale bool ) {
539
553
hpa .Status = autoscalingv2.HorizontalPodAutoscalerStatus {
540
554
CurrentReplicas : currentReplicas ,
541
555
DesiredReplicas : desiredReplicas ,
@@ -548,11 +562,19 @@ func (a *HorizontalController) updateStatusWithReplicas(hpa *autoscalingv2.Horiz
548
562
now := metav1 .NewTime (time .Now ())
549
563
hpa .Status .LastScaleTime = & now
550
564
}
565
+ }
551
566
552
- return a .update (hpa )
567
+ // updateStatusIfNeeded calls updateStatus only if the status of the new HPA is not the same as the old status
568
+ func (a * HorizontalController ) updateStatusIfNeeded (oldStatus * autoscalingv2.HorizontalPodAutoscalerStatus , newHPA * autoscalingv2.HorizontalPodAutoscaler ) error {
569
+ // skip a write if we wouldn't need to update
570
+ if apiequality .Semantic .DeepEqual (oldStatus , & newHPA .Status ) {
571
+ return nil
572
+ }
573
+ return a .updateStatus (newHPA )
553
574
}
554
575
555
- func (a * HorizontalController ) update (hpa * autoscalingv2.HorizontalPodAutoscaler ) error {
576
+ // updateStatus actually does the update request for the status of the given HPA
577
+ func (a * HorizontalController ) updateStatus (hpa * autoscalingv2.HorizontalPodAutoscaler ) error {
556
578
// convert back to autoscalingv1
557
579
hpaRaw , err := UnsafeConvertToVersionVia (hpa , autoscalingv1 .SchemeGroupVersion )
558
580
if err != nil {
0 commit comments