Merge pull request #112554 from kushagra98/variable-name-change

variable name change for better understanding
This commit is contained in:
Kubernetes Prow Robot 2022-09-22 03:37:02 -07:00 committed by GitHub
commit 2dba4034f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 195 additions and 195 deletions

View File

@ -373,7 +373,7 @@ func (a *HorizontalController) reconcileKey(ctx context.Context, key string) (de
// computeStatusForObjectMetric computes the desired number of replicas for the specified metric of type ObjectMetricSourceType.
func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, statusReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (replicas int32, timestamp time.Time, metricName string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
if metricSpec.Object.Target.Type == autoscalingv2.ValueMetricType {
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(specReplicas, metricSpec.Object.Target.Value.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, selector, metricSelector)
replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(specReplicas, metricSpec.Object.Target.Value.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, selector, metricSelector)
if err != nil {
condition := a.getUnableComputeReplicaCountCondition(hpa, "FailedGetObjectMetric", err)
return 0, timestampProposal, "", condition, err
@ -387,13 +387,13 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
Selector: metricSpec.Object.Metric.Selector,
},
Current: autoscalingv2.MetricValueStatus{
Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
Value: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
},
},
}
return replicaCountProposal, timestampProposal, fmt.Sprintf("%s metric %s", metricSpec.Object.DescribedObject.Kind, metricSpec.Object.Metric.Name), autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
} else if metricSpec.Object.Target.Type == autoscalingv2.AverageValueMetricType {
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectPerPodMetricReplicas(statusReplicas, metricSpec.Object.Target.AverageValue.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, metricSelector)
replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetObjectPerPodMetricReplicas(statusReplicas, metricSpec.Object.Target.AverageValue.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, metricSelector)
if err != nil {
condition := a.getUnableComputeReplicaCountCondition(hpa, "FailedGetObjectMetric", err)
return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s object metric: %v", metricSpec.Object.Metric.Name, err)
@ -406,7 +406,7 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
Selector: metricSpec.Object.Metric.Selector,
},
Current: autoscalingv2.MetricValueStatus{
AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
},
},
}
@ -420,7 +420,7 @@ func (a *HorizontalController) computeStatusForObjectMetric(specReplicas, status
// computeStatusForPodsMetric computes the desired number of replicas for the specified metric of type PodsMetricSourceType.
func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (replicaCountProposal int32, timestampProposal time.Time, metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.Target.AverageValue.MilliValue(), metricSpec.Pods.Metric.Name, hpa.Namespace, selector, metricSelector)
replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.Target.AverageValue.MilliValue(), metricSpec.Pods.Metric.Name, hpa.Namespace, selector, metricSelector)
if err != nil {
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetPodsMetric", err)
return 0, timestampProposal, "", condition, err
@ -433,7 +433,7 @@ func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32,
Selector: metricSpec.Pods.Metric.Selector,
},
Current: autoscalingv2.MetricValueStatus{
AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
},
},
}
@ -449,7 +449,7 @@ func (a *HorizontalController) computeStatusForResourceMetricGeneric(ctx context
var rawProposal int64
replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(ctx, currentReplicas, target.AverageValue.MilliValue(), resourceName, namespace, selector, container)
if err != nil {
return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s utilization: %v", resourceName, err)
return 0, nil, time.Time{}, "", condition, fmt.Errorf("failed to get %s usage: %v", resourceName, err)
}
metricNameProposal = fmt.Sprintf("%s resource", resourceName.String())
status := autoscalingv2.MetricValueStatus{
@ -459,7 +459,7 @@ func (a *HorizontalController) computeStatusForResourceMetricGeneric(ctx context
}
if target.AverageUtilization == nil {
errMsg := "invalid resource metric source: neither an average utilization target nor an average value target was set"
errMsg := "invalid resource metric source: neither an average utilization target nor an average value (usage) target was set"
return 0, nil, time.Time{}, "", condition, fmt.Errorf(errMsg)
}
@ -519,7 +519,7 @@ func (a *HorizontalController) computeStatusForContainerResourceMetric(ctx conte
// computeStatusForExternalMetric computes the desired number of replicas for the specified metric of type ExternalMetricSourceType.
func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, statusReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (replicaCountProposal int32, timestampProposal time.Time, metricNameProposal string, condition autoscalingv2.HorizontalPodAutoscalerCondition, err error) {
if metricSpec.External.Target.AverageValue != nil {
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(statusReplicas, metricSpec.External.Target.AverageValue.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector)
replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(statusReplicas, metricSpec.External.Target.AverageValue.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector)
if err != nil {
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetExternalMetric", err)
return 0, time.Time{}, "", condition, fmt.Errorf("failed to get %s external metric: %v", metricSpec.External.Metric.Name, err)
@ -532,14 +532,14 @@ func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, stat
Selector: metricSpec.External.Metric.Selector,
},
Current: autoscalingv2.MetricValueStatus{
AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
AverageValue: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
},
},
}
return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.Metric.Name, metricSpec.External.Metric.Selector), autoscalingv2.HorizontalPodAutoscalerCondition{}, nil
}
if metricSpec.External.Target.Value != nil {
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(specReplicas, metricSpec.External.Target.Value.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector, selector)
replicaCountProposal, usageProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(specReplicas, metricSpec.External.Target.Value.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector, selector)
if err != nil {
condition = a.getUnableComputeReplicaCountCondition(hpa, "FailedGetExternalMetric", err)
return 0, time.Time{}, "", condition, fmt.Errorf("failed to get external metric %s: %v", metricSpec.External.Metric.Name, err)
@ -552,7 +552,7 @@ func (a *HorizontalController) computeStatusForExternalMetric(specReplicas, stat
Selector: metricSpec.External.Metric.Selector,
},
Current: autoscalingv2.MetricValueStatus{
Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
Value: resource.NewMilliQuantity(usageProposal, resource.DecimalSI),
},
},
}

View File

@ -51,16 +51,16 @@ func GetResourceUtilizationRatio(metrics PodMetricsInfo, requests map[string]int
return float64(currentUtilization) / float64(targetUtilization), currentUtilization, metricsTotal / int64(numEntries), nil
}
// GetMetricUtilizationRatio takes in a set of metrics and a target utilization value,
// and calculates the ratio of desired to actual utilization
// (returning that and the actual utilization)
func GetMetricUtilizationRatio(metrics PodMetricsInfo, targetUtilization int64) (utilizationRatio float64, currentUtilization int64) {
// GetMetricUsageRatio takes in a set of metrics and a target usage value,
// and calculates the ratio of desired to actual usage
// (returning that and the actual usage)
func GetMetricUsageRatio(metrics PodMetricsInfo, targetUsage int64) (usageRatio float64, currentUsage int64) {
metricsTotal := int64(0)
for _, metric := range metrics {
metricsTotal += metric.Value
}
currentUtilization = metricsTotal / int64(len(metrics))
currentUsage = metricsTotal / int64(len(metrics))
return float64(currentUtilization) / float64(targetUtilization), currentUtilization
return float64(currentUsage) / float64(targetUsage), currentUsage
}

View File

@ -49,19 +49,19 @@ func (tc *resourceUtilizationRatioTestCase) runTest(t *testing.T) {
assert.Equal(t, tc.expectedRawAverageValue, actualRawAverageValue, "the raw average value should be as expected")
}
type metricUtilizationRatioTestCase struct {
metrics PodMetricsInfo
targetUtilization int64
type metricUsageRatioTestCase struct {
metrics PodMetricsInfo
targetUsage int64
expectedUtilizationRatio float64
expectedCurrentUtilization int64
expectedUsageRatio float64
expectedCurrentUsage int64
}
func (tc *metricUtilizationRatioTestCase) runTest(t *testing.T) {
actualUtilizationRatio, actualCurrentUtilization := GetMetricUtilizationRatio(tc.metrics, tc.targetUtilization)
func (tc *metricUsageRatioTestCase) runTest(t *testing.T) {
actualUsageRatio, actualCurrentUsage := GetMetricUsageRatio(tc.metrics, tc.targetUsage)
assert.Equal(t, tc.expectedUtilizationRatio, actualUtilizationRatio, "the utilization ratios should be as expected")
assert.Equal(t, tc.expectedCurrentUtilization, actualCurrentUtilization, "the current utilization should be as expected")
assert.Equal(t, tc.expectedUsageRatio, actualUsageRatio, "the usage ratios should be as expected")
assert.Equal(t, tc.expectedCurrentUsage, actualCurrentUsage, "the current usage should be as expected")
}
func TestGetResourceUtilizationRatioBaseCase(t *testing.T) {
@ -135,14 +135,14 @@ func TestGetResourceUtilizationRatioNoRequests(t *testing.T) {
tc.runTest(t)
}
func TestGetMetricUtilizationRatioBaseCase(t *testing.T) {
tc := metricUtilizationRatioTestCase{
func TestGetMetricUsageRatioBaseCase(t *testing.T) {
tc := metricUsageRatioTestCase{
metrics: PodMetricsInfo{
"test-pod-0": {Value: 5000}, "test-pod-1": {Value: 10000},
},
targetUtilization: 10000,
expectedUtilizationRatio: .75,
expectedCurrentUtilization: 7500,
targetUsage: 10000,
expectedUsageRatio: .75,
expectedCurrentUsage: 7500,
}
tc.runTest(t)

View File

@ -149,33 +149,33 @@ func (c *ReplicaCalculator) GetResourceReplicas(ctx context.Context, currentRepl
return newReplicas, utilization, rawUtilization, timestamp, nil
}
// GetRawResourceReplicas calculates the desired replica count based on a target resource utilization (as a raw milli-value)
// GetRawResourceReplicas calculates the desired replica count based on a target resource usage (as a raw milli-value)
// for pods matching the given selector in the given namespace, and the current replica count
func (c *ReplicaCalculator) GetRawResourceReplicas(ctx context.Context, currentReplicas int32, targetUtilization int64, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
func (c *ReplicaCalculator) GetRawResourceReplicas(ctx context.Context, currentReplicas int32, targetUsage int64, resource v1.ResourceName, namespace string, selector labels.Selector, container string) (replicaCount int32, usage int64, timestamp time.Time, err error) {
metrics, timestamp, err := c.metricsClient.GetResourceMetric(ctx, resource, namespace, selector, container)
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metrics for resource %s: %v", resource, err)
}
replicaCount, utilization, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUtilization, namespace, selector, resource)
return replicaCount, utilization, timestamp, err
replicaCount, usage, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUsage, namespace, selector, resource)
return replicaCount, usage, timestamp, err
}
// GetMetricReplicas calculates the desired replica count based on a target metric utilization
// GetMetricReplicas calculates the desired replica count based on a target metric usage
// (as a milli-value) for pods matching the given selector in the given namespace, and the
// current replica count
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUsage int64, metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector, metricSelector)
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err)
}
replicaCount, utilization, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUtilization, namespace, selector, v1.ResourceName(""))
return replicaCount, utilization, timestamp, err
replicaCount, usage, err = c.calcPlainMetricReplicas(metrics, currentReplicas, targetUsage, namespace, selector, v1.ResourceName(""))
return replicaCount, usage, timestamp, err
}
// calcPlainMetricReplicas calculates the desired replicas for plain (i.e. non-utilization percentage) metrics.
func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUtilization int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, utilization int64, err error) {
func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMetricsInfo, currentReplicas int32, targetUsage int64, namespace string, selector labels.Selector, resource v1.ResourceName) (replicaCount int32, usage int64, err error) {
podList, err := c.podLister.Pods(namespace).List(selector)
if err != nil {
@ -194,25 +194,25 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
return 0, 0, fmt.Errorf("did not receive metrics for any ready pods")
}
usageRatio, utilization := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization)
usageRatio, usage := metricsclient.GetMetricUsageRatio(metrics, targetUsage)
scaleUpWithUnready := len(unreadyPods) > 0 && usageRatio > 1.0
if !scaleUpWithUnready && len(missingPods) == 0 {
if math.Abs(1.0-usageRatio) <= c.tolerance {
// return the current replicas if the change would be too small
return currentReplicas, utilization, nil
return currentReplicas, usage, nil
}
// if we don't have any unready or missing pods, we can calculate the new replica count now
return int32(math.Ceil(usageRatio * float64(readyPodCount))), utilization, nil
return int32(math.Ceil(usageRatio * float64(readyPodCount))), usage, nil
}
if len(missingPods) > 0 {
if usageRatio < 1.0 {
// on a scale-down, treat missing pods as using exactly the target amount
for podName := range missingPods {
metrics[podName] = metricsclient.PodMetric{Value: targetUtilization}
metrics[podName] = metricsclient.PodMetric{Value: targetUsage}
}
} else {
// on a scale-up, treat missing pods as using 0% of the resource request
@ -229,37 +229,37 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
}
}
// re-run the utilization calculation with our new numbers
newUsageRatio, _ := metricsclient.GetMetricUtilizationRatio(metrics, targetUtilization)
// re-run the usage calculation with our new numbers
newUsageRatio, _ := metricsclient.GetMetricUsageRatio(metrics, targetUsage)
if math.Abs(1.0-newUsageRatio) <= c.tolerance || (usageRatio < 1.0 && newUsageRatio > 1.0) || (usageRatio > 1.0 && newUsageRatio < 1.0) {
// return the current replicas if the change would be too small,
// or if the new usage ratio would cause a change in scale direction
return currentReplicas, utilization, nil
return currentReplicas, usage, nil
}
newReplicas := int32(math.Ceil(newUsageRatio * float64(len(metrics))))
if (newUsageRatio < 1.0 && newReplicas > currentReplicas) || (newUsageRatio > 1.0 && newReplicas < currentReplicas) {
// return the current replicas if the change of metrics length would cause a change in scale direction
return currentReplicas, utilization, nil
return currentReplicas, usage, nil
}
// return the result, where the number of replicas considered is
// however many replicas factored into our calculation
return newReplicas, utilization, nil
return newReplicas, usage, nil
}
// GetObjectMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value)
// GetObjectMetricReplicas calculates the desired replica count based on a target metric usage (as a milli-value)
// for the given object in the given namespace, and the current replica count.
func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
utilization, _, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
func (c *ReplicaCalculator) GetObjectMetricReplicas(currentReplicas int32, targetUsage int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, selector labels.Selector, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
usage, _, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
}
usageRatio := float64(utilization) / float64(targetUtilization)
usageRatio := float64(usage) / float64(targetUsage)
replicaCount, timestamp, err = c.getUsageRatioReplicaCount(currentReplicas, usageRatio, namespace, selector)
return replicaCount, utilization, timestamp, err
return replicaCount, usage, timestamp, err
}
// getUsageRatioReplicaCount calculates the desired replica count based on usageRatio and ready pods count.
@ -284,22 +284,22 @@ func (c *ReplicaCalculator) getUsageRatioReplicaCount(currentReplicas int32, usa
return replicaCount, timestamp, err
}
// GetObjectPerPodMetricReplicas calculates the desired replica count based on a target metric utilization (as a milli-value)
// GetObjectPerPodMetricReplicas calculates the desired replica count based on a target metric usage (as a milli-value)
// for the given object in the given namespace, and the current replica count.
func (c *ReplicaCalculator) GetObjectPerPodMetricReplicas(statusReplicas int32, targetAverageUtilization int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
func (c *ReplicaCalculator) GetObjectPerPodMetricReplicas(statusReplicas int32, targetAverageUsage int64, metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
usage, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
}
replicaCount = statusReplicas
usageRatio := float64(utilization) / (float64(targetAverageUtilization) * float64(replicaCount))
usageRatio := float64(usage) / (float64(targetAverageUsage) * float64(replicaCount))
if math.Abs(1.0-usageRatio) > c.tolerance {
// update number of replicas if change is large enough
replicaCount = int32(math.Ceil(float64(utilization) / float64(targetAverageUtilization)))
replicaCount = int32(math.Ceil(float64(usage) / float64(targetAverageUsage)))
}
utilization = int64(math.Ceil(float64(utilization) / float64(statusReplicas)))
return replicaCount, utilization, timestamp, nil
usage = int64(math.Ceil(float64(usage) / float64(statusReplicas)))
return replicaCount, usage, timestamp, nil
}
// @TODO(mattjmcnaughton) Many different functions in this module use variations
@ -329,7 +329,7 @@ func (c *ReplicaCalculator) getReadyPodsCount(namespace string, selector labels.
// GetExternalMetricReplicas calculates the desired replica count based on a
// target metric value (as a milli-value) for the external metric in the given
// namespace, and the current replica count.
func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUtilization int64, metricName, namespace string, metricSelector *metav1.LabelSelector, podSelector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, targetUsage int64, metricName, namespace string, metricSelector *metav1.LabelSelector, podSelector labels.Selector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector)
if err != nil {
return 0, 0, time.Time{}, err
@ -338,20 +338,20 @@ func (c *ReplicaCalculator) GetExternalMetricReplicas(currentReplicas int32, tar
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err)
}
utilization = 0
usage = 0
for _, val := range metrics {
utilization = utilization + val
usage = usage + val
}
usageRatio := float64(utilization) / float64(targetUtilization)
usageRatio := float64(usage) / float64(targetUsage)
replicaCount, timestamp, err = c.getUsageRatioReplicaCount(currentReplicas, usageRatio, namespace, podSelector)
return replicaCount, utilization, timestamp, err
return replicaCount, usage, timestamp, err
}
// GetExternalPerPodMetricReplicas calculates the desired replica count based on a
// target metric value per pod (as a milli-value) for the external metric in the
// given namespace, and the current replica count.
func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32, targetUtilizationPerPod int64, metricName, namespace string, metricSelector *metav1.LabelSelector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32, targetUsagePerPod int64, metricName, namespace string, metricSelector *metav1.LabelSelector) (replicaCount int32, usage int64, timestamp time.Time, err error) {
metricLabelSelector, err := metav1.LabelSelectorAsSelector(metricSelector)
if err != nil {
return 0, 0, time.Time{}, err
@ -360,19 +360,19 @@ func (c *ReplicaCalculator) GetExternalPerPodMetricReplicas(statusReplicas int32
if err != nil {
return 0, 0, time.Time{}, fmt.Errorf("unable to get external metric %s/%s/%+v: %s", namespace, metricName, metricSelector, err)
}
utilization = 0
usage = 0
for _, val := range metrics {
utilization = utilization + val
usage = usage + val
}
replicaCount = statusReplicas
usageRatio := float64(utilization) / (float64(targetUtilizationPerPod) * float64(replicaCount))
usageRatio := float64(usage) / (float64(targetUsagePerPod) * float64(replicaCount))
if math.Abs(1.0-usageRatio) > c.tolerance {
// update number of replicas if the change is large enough
replicaCount = int32(math.Ceil(float64(utilization) / float64(targetUtilizationPerPod)))
replicaCount = int32(math.Ceil(float64(usage) / float64(targetUsagePerPod)))
}
utilization = int64(math.Ceil(float64(utilization) / float64(statusReplicas)))
return replicaCount, utilization, timestamp, nil
usage = int64(math.Ceil(float64(usage) / float64(statusReplicas)))
return replicaCount, usage, timestamp, nil
}
func groupPods(pods []*v1.Pod, metrics metricsclient.PodMetricsInfo, resource v1.ResourceName, cpuInitializationPeriod, delayOfInitialReadinessStatus time.Duration) (readyPodCount int, unreadyPods, missingPods, ignoredPods sets.String) {

View File

@ -78,9 +78,9 @@ type metricInfo struct {
selector *metav1.LabelSelector
metricType metricType
targetUtilization int64
perPodTargetUtilization int64
expectedUtilization int64
targetUsage int64
perPodTargetUsage int64
expectedUsage int64
}
type replicaCalcTestCase struct {
@ -376,38 +376,38 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
}
var outReplicas int32
var outUtilization int64
var outUsage int64
var outTimestamp time.Time
switch tc.metric.metricType {
case objectMetric:
if tc.metric.singleObject == nil {
t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.")
}
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
outReplicas, outUsage, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
case objectPerPodMetric:
if tc.metric.singleObject == nil {
t.Fatal("Metric specified as objectMetric but metric.singleObject is nil.")
}
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, nil)
outReplicas, outUsage, outTimestamp, err = replicaCalc.GetObjectPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUsage, tc.metric.name, testNamespace, tc.metric.singleObject, nil)
case externalMetric:
if tc.metric.selector == nil {
t.Fatal("Metric specified as externalMetric but metric.selector is nil.")
}
if tc.metric.targetUtilization <= 0 {
t.Fatalf("Metric specified as externalMetric but metric.targetUtilization is %d which is <=0.", tc.metric.targetUtilization)
if tc.metric.targetUsage <= 0 {
t.Fatalf("Metric specified as externalMetric but metric.targetUsage is %d which is <=0.", tc.metric.targetUsage)
}
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.selector, selector)
outReplicas, outUsage, outTimestamp, err = replicaCalc.GetExternalMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, tc.metric.selector, selector)
case externalPerPodMetric:
if tc.metric.selector == nil {
t.Fatal("Metric specified as externalPerPodMetric but metric.selector is nil.")
}
if tc.metric.perPodTargetUtilization <= 0 {
t.Fatalf("Metric specified as externalPerPodMetric but metric.perPodTargetUtilization is %d which is <=0.", tc.metric.perPodTargetUtilization)
if tc.metric.perPodTargetUsage <= 0 {
t.Fatalf("Metric specified as externalPerPodMetric but metric.perPodTargetUsage is %d which is <=0.", tc.metric.perPodTargetUsage)
}
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector)
outReplicas, outUsage, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUsage, tc.metric.name, testNamespace, tc.metric.selector)
case podMetric:
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
outReplicas, outUsage, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUsage, tc.metric.name, testNamespace, selector, nil)
default:
t.Fatalf("Unknown metric type: %d", tc.metric.metricType)
}
@ -419,7 +419,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
}
require.NoError(t, err, "there should not have been an error calculating the replica count")
assert.Equal(t, tc.expectedReplicas, outReplicas, "replicas should be as expected")
assert.Equal(t, tc.metric.expectedUtilization, outUtilization, "utilization should be as expected")
assert.Equal(t, tc.metric.expectedUsage, outUsage, "usage should be as expected")
assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
}
func makePodMetricLevels(containerMetric ...int64) [][]int64 {
@ -674,11 +674,11 @@ func TestReplicaCalcScaleUpCM(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 4,
metric: &metricInfo{
name: "qps",
levels: []int64{20000, 10000, 30000},
targetUtilization: 15000,
expectedUtilization: 20000,
metricType: podMetric,
name: "qps",
levels: []int64{20000, 10000, 30000},
targetUsage: 15000,
expectedUsage: 20000,
metricType: podMetric,
},
}
tc.runTest(t)
@ -691,11 +691,11 @@ func TestReplicaCalcScaleUpCMUnreadyHotCpuNoLessScale(t *testing.T) {
podReadiness: []v1.ConditionStatus{v1.ConditionTrue, v1.ConditionTrue, v1.ConditionFalse},
podStartTime: []metav1.Time{coolCPUCreationTime(), coolCPUCreationTime(), hotCPUCreationTime()},
metric: &metricInfo{
name: "qps",
levels: []int64{50000, 10000, 30000},
targetUtilization: 15000,
expectedUtilization: 30000,
metricType: podMetric,
name: "qps",
levels: []int64{50000, 10000, 30000},
targetUsage: 15000,
expectedUsage: 30000,
metricType: podMetric,
},
}
tc.runTest(t)
@ -708,11 +708,11 @@ func TestReplicaCalcScaleUpCMUnreadyHotCpuScaleWouldScaleDown(t *testing.T) {
podReadiness: []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
podStartTime: []metav1.Time{hotCPUCreationTime(), coolCPUCreationTime(), hotCPUCreationTime()},
metric: &metricInfo{
name: "qps",
levels: []int64{50000, 15000, 30000},
targetUtilization: 15000,
expectedUtilization: 31666,
metricType: podMetric,
name: "qps",
levels: []int64{50000, 15000, 30000},
targetUsage: 15000,
expectedUsage: 31666,
metricType: podMetric,
},
}
tc.runTest(t)
@ -723,10 +723,10 @@ func TestReplicaCalcScaleUpCMObject(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 4,
metric: &metricInfo{
name: "qps",
levels: []int64{20000},
targetUtilization: 15000,
expectedUtilization: 20000,
name: "qps",
levels: []int64{20000},
targetUsage: 15000,
expectedUsage: 20000,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -742,11 +742,11 @@ func TestReplicaCalcScaleUpCMPerPodObject(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 4,
metric: &metricInfo{
metricType: objectPerPodMetric,
name: "qps",
levels: []int64{20000},
perPodTargetUtilization: 5000,
expectedUtilization: 6667,
metricType: objectPerPodMetric,
name: "qps",
levels: []int64{20000},
perPodTargetUsage: 5000,
expectedUsage: 6667,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -763,10 +763,10 @@ func TestReplicaCalcScaleUpCMObjectIgnoresUnreadyPods(t *testing.T) {
expectedReplicas: 5, // If we did not ignore unready pods, we'd expect 15 replicas.
podReadiness: []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
metric: &metricInfo{
name: "qps",
levels: []int64{50000},
targetUtilization: 10000,
expectedUtilization: 50000,
name: "qps",
levels: []int64{50000},
targetUsage: 10000,
expectedUsage: 50000,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -782,12 +782,12 @@ func TestReplicaCalcScaleUpCMExternal(t *testing.T) {
currentReplicas: 1,
expectedReplicas: 2,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
targetUtilization: 4400,
expectedUtilization: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: podMetric,
name: "qps",
levels: []int64{8600},
targetUsage: 4400,
expectedUsage: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: podMetric,
},
}
tc.runTest(t)
@ -799,12 +799,12 @@ func TestReplicaCalcScaleUpCMExternalIgnoresUnreadyPods(t *testing.T) {
expectedReplicas: 2, // Would expect 6 if we didn't ignore unready pods
podReadiness: []v1.ConditionStatus{v1.ConditionFalse, v1.ConditionTrue, v1.ConditionFalse},
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
targetUtilization: 4400,
expectedUtilization: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
name: "qps",
levels: []int64{8600},
targetUsage: 4400,
expectedUsage: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
},
}
tc.runTest(t)
@ -815,11 +815,11 @@ func TestReplicaCalcScaleUpCMExternalNoLabels(t *testing.T) {
currentReplicas: 1,
expectedReplicas: 2,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
targetUtilization: 4400,
expectedUtilization: 8600,
metricType: podMetric,
name: "qps",
levels: []int64{8600},
targetUsage: 4400,
expectedUsage: 8600,
metricType: podMetric,
},
}
tc.runTest(t)
@ -830,12 +830,12 @@ func TestReplicaCalcScaleUpPerPodCMExternal(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 4,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
perPodTargetUtilization: 2150,
expectedUtilization: 2867,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
name: "qps",
levels: []int64{8600},
perPodTargetUsage: 2150,
expectedUsage: 2867,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
},
}
tc.runTest(t)
@ -881,11 +881,11 @@ func TestReplicaCalcScaleDownCM(t *testing.T) {
currentReplicas: 5,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{12000, 12000, 12000, 12000, 12000},
targetUtilization: 20000,
expectedUtilization: 12000,
metricType: podMetric,
name: "qps",
levels: []int64{12000, 12000, 12000, 12000, 12000},
targetUsage: 20000,
expectedUsage: 12000,
metricType: podMetric,
},
}
tc.runTest(t)
@ -896,10 +896,10 @@ func TestReplicaCalcScaleDownPerPodCMObject(t *testing.T) {
currentReplicas: 5,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{6000},
perPodTargetUtilization: 2000,
expectedUtilization: 1200,
name: "qps",
levels: []int64{6000},
perPodTargetUsage: 2000,
expectedUsage: 1200,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -916,10 +916,10 @@ func TestReplicaCalcScaleDownCMObject(t *testing.T) {
currentReplicas: 5,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{12000},
targetUtilization: 20000,
expectedUtilization: 12000,
name: "qps",
levels: []int64{12000},
targetUsage: 20000,
expectedUsage: 12000,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -935,12 +935,12 @@ func TestReplicaCalcScaleDownCMExternal(t *testing.T) {
currentReplicas: 5,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
targetUtilization: 14334,
expectedUtilization: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
name: "qps",
levels: []int64{8600},
targetUsage: 14334,
expectedUsage: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
},
}
tc.runTest(t)
@ -951,12 +951,12 @@ func TestReplicaCalcScaleDownPerPodCMExternal(t *testing.T) {
currentReplicas: 5,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
perPodTargetUtilization: 2867,
expectedUtilization: 1720,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
name: "qps",
levels: []int64{8600},
perPodTargetUsage: 2867,
expectedUsage: 1720,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
},
}
tc.runTest(t)
@ -1178,11 +1178,11 @@ func TestReplicaCalcToleranceCM(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{20000, 21000, 21000},
targetUtilization: 20000,
expectedUtilization: 20666,
metricType: podMetric,
name: "qps",
levels: []int64{20000, 21000, 21000},
targetUsage: 20000,
expectedUsage: 20666,
metricType: podMetric,
},
}
tc.runTest(t)
@ -1193,10 +1193,10 @@ func TestReplicaCalcToleranceCMObject(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{20666},
targetUtilization: 20000,
expectedUtilization: 20666,
name: "qps",
levels: []int64{20666},
targetUsage: 20000,
expectedUsage: 20666,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -1212,11 +1212,11 @@ func TestReplicaCalcTolerancePerPodCMObject(t *testing.T) {
currentReplicas: 4,
expectedReplicas: 4,
metric: &metricInfo{
metricType: objectPerPodMetric,
name: "qps",
levels: []int64{20166},
perPodTargetUtilization: 5000,
expectedUtilization: 5042,
metricType: objectPerPodMetric,
name: "qps",
levels: []int64{20166},
perPodTargetUsage: 5000,
expectedUsage: 5042,
singleObject: &autoscalingv2.CrossVersionObjectReference{
Kind: "Deployment",
APIVersion: "apps/v1",
@ -1232,12 +1232,12 @@ func TestReplicaCalcToleranceCMExternal(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
targetUtilization: 8888,
expectedUtilization: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
name: "qps",
levels: []int64{8600},
targetUsage: 8888,
expectedUsage: 8600,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalMetric,
},
}
tc.runTest(t)
@ -1248,12 +1248,12 @@ func TestReplicaCalcTolerancePerPodCMExternal(t *testing.T) {
currentReplicas: 3,
expectedReplicas: 3,
metric: &metricInfo{
name: "qps",
levels: []int64{8600},
perPodTargetUtilization: 2900,
expectedUtilization: 2867,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
name: "qps",
levels: []int64{8600},
perPodTargetUsage: 2900,
expectedUsage: 2867,
selector: &metav1.LabelSelector{MatchLabels: map[string]string{"label": "value"}},
metricType: externalPerPodMetric,
},
}
tc.runTest(t)
@ -1506,11 +1506,11 @@ func TestReplicaCalcDuringRollingUpdateWithMaxSurgeCM(t *testing.T) {
expectedReplicas: 2,
podPhase: []v1.PodPhase{v1.PodRunning, v1.PodRunning, v1.PodRunning},
metric: &metricInfo{
name: "qps",
levels: []int64{10000, 10000},
targetUtilization: 17000,
expectedUtilization: 10000,
metricType: podMetric,
name: "qps",
levels: []int64{10000, 10000},
targetUsage: 17000,
expectedUsage: 10000,
metricType: podMetric,
},
}
tc.runTest(t)