Change:
useMetricsAPI:   true, recommendations: []timestampedRecommendation{}, } <ins> tc1.runTest(t) </ins> <del> tc.runTest(t) // Reuse the data structure above, now testing "unscaling". // Now, we test that no scaling happens if we are in a very close margin to the tolerance </del> target = math.Abs(1/(requestedToUsed*(1-defaultTestingTolerance))) + .004 finalCPUPercentTarget = int32(target * 100) <del> tc.CPUTarget = finalCPUPercentTarget tc.initialReplicas = startPods tc.expectedDesiredReplicas = startPods tc.expectedConditions = statusOkWithOverrides(autoscalingv2.HorizontalPodAutoscalerCondition{ Type:   autoscalingv2.AbleToScale, Status: v1.ConditionTrue, Reason: "ReadyForNewScale", }) tc.runTest(t) </del> <ins> tc2 := testCase{ minReplicas:             0, maxReplicas:             1000, initialReplicas:         startPods, expectedDesiredReplicas: startPods, CPUTarget:               finalCPUPercentTarget, reportedLevels: []uint64{ totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, totalUsedCPUOfAllPods / 10, }, reportedCPURequests: []resource.Quantity{ resource.MustParse(fmt.Sprint(perPodRequested+100) + "m"), resource.MustParse(fmt.Sprint(perPodRequested-100) + "m"), resource.MustParse(fmt.Sprint(perPodRequested+10) + "m"), resource.MustParse(fmt.Sprint(perPodRequested-10) + "m"), resource.MustParse(fmt.Sprint(perPodRequested+2) + "m"), resource.MustParse(fmt.Sprint(perPodRequested-2) + "m"), resource.MustParse(fmt.Sprint(perPodRequested+1) + "m"), resource.MustParse(fmt.Sprint(perPodRequested-1) + "m"), resource.MustParse(fmt.Sprint(perPodRequested) + "m"), resource.MustParse(fmt.Sprint(perPodRequested) + "m"), }, useMetricsAPI:   true, recommendations: []timestampedRecommendation{}, expectedConditions: statusOkWithOverrides(autoscalingv2.HorizontalPodAutoscalerCondition{ Type:   autoscalingv2.AbleToScale, Status: v1.ConditionTrue, Reason: "ReadyForNewScale", }), } tc2.runTest(t) </ins> } func TestScaleUpRCImmediately(t *testing.T) {

Discussion:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks!--What happened: Resync period for HorizontalPodAutoscaler controller is set to 15 seconds in order to update HPAs every 15 seconds. Sometimes updates are skipped and period between two updates is 30 seconds. What you expected to happen: HPA should be updated every 15 seconds. How to reproduce it (as minimally and precisely as possible): Add debugs to HPA controller showing how often HPAs are processed. Create HPA. Anything else we need to know?: HPA controller uses rate RateLimitingQueue: New requests are always with 15 seconds delay: If request for the given HPA is in the queue then newly request is skipped. Requests are and removed from the queue at the same moment so there is a race condition. See following scenario: 00:00:00 - Resync adds request to queue to be executed at 00:00:15 00:00:15 - Resync adds next request to queue to be executed at 00:00:30 but it is skipped because previous request is still in the queue 00:00:15 - Request at 00:00:00 is executed 00:00:30 - Resync adds next request to queue to be executed at 00:00:45 00:00:45 - Request at 00:00:30 is executed In above scenario HPA wasn't updated between 00:00:15 and 00:00:45. Environment: Kubernetes version (use ): HEAD Cloud provider or hardware configuration: GKE <!-- DO NOT EDIT BELOW THIS LINE --/kind bug
/sig autoscaling
/assign krzysztof-jastrzebski