mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Implement autoscaling/v2beta2 features in HPA controller
This commit is contained in:
parent
a79916fa84
commit
c7102ee5dc
@ -1,10 +1,4 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
"go_test",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
@ -15,13 +9,14 @@ go_library(
|
|||||||
"replica_calculator.go",
|
"replica_calculator.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler",
|
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/api/v1/pod:go_default_library",
|
"//pkg/api/v1/pod:go_default_library",
|
||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/controller/podautoscaler/metrics:go_default_library",
|
"//pkg/controller/podautoscaler/metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
@ -66,6 +61,7 @@ go_test(
|
|||||||
"//pkg/controller/podautoscaler/metrics:go_default_library",
|
"//pkg/controller/podautoscaler/metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
||||||
|
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
@ -80,7 +76,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/scale/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/scale/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
|
||||||
@ -107,4 +103,5 @@ filegroup(
|
|||||||
"//pkg/controller/podautoscaler/metrics:all-srcs",
|
"//pkg/controller/podautoscaler/metrics:all-srcs",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||||
autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
|
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -218,12 +218,24 @@ func (a *HorizontalController) computeReplicasForMetrics(hpa *autoscalingv2.Hori
|
|||||||
|
|
||||||
switch metricSpec.Type {
|
switch metricSpec.Type {
|
||||||
case autoscalingv2.ObjectMetricSourceType:
|
case autoscalingv2.ObjectMetricSourceType:
|
||||||
replicaCountProposal, timestampProposal, metricNameProposal, err = a.computeStatusForObjectMetric(currentReplicas, metricSpec, hpa, selector, &statuses[i])
|
metricSelector, err := metav1.LabelSelectorAsSelector(metricSpec.Object.Metric.Selector)
|
||||||
|
if err != nil {
|
||||||
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetObjectMetric", err.Error())
|
||||||
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetObjectMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
|
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get object metric value: %v", err)
|
||||||
|
}
|
||||||
|
replicaCountProposal, timestampProposal, metricNameProposal, err = a.computeStatusForObjectMetric(currentReplicas, metricSpec, hpa, selector, &statuses[i], metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get object metric value: %v", err)
|
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get object metric value: %v", err)
|
||||||
}
|
}
|
||||||
case autoscalingv2.PodsMetricSourceType:
|
case autoscalingv2.PodsMetricSourceType:
|
||||||
replicaCountProposal, timestampProposal, metricNameProposal, err = a.computeStatusForPodsMetric(currentReplicas, metricSpec, hpa, selector, &statuses[i])
|
metricSelector, err := metav1.LabelSelectorAsSelector(metricSpec.Pods.Metric.Selector)
|
||||||
|
if err != nil {
|
||||||
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetPodsMetric", err.Error())
|
||||||
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetPodsMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
|
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get pods metric value: %v", err)
|
||||||
|
}
|
||||||
|
replicaCountProposal, timestampProposal, metricNameProposal, err = a.computeStatusForPodsMetric(currentReplicas, metricSpec, hpa, selector, &statuses[i], metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get object metric value: %v", err)
|
return 0, "", nil, time.Time{}, fmt.Errorf("failed to get object metric value: %v", err)
|
||||||
}
|
}
|
||||||
@ -270,8 +282,8 @@ func (a *HorizontalController) reconcileKey(key string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// computeStatusForObjectMetric computes the desired number of replicas for the specified metric of type ObjectMetricSourceType.
|
// computeStatusForObjectMetric computes the desired number of replicas for the specified metric of type ObjectMetricSourceType.
|
||||||
func (a *HorizontalController) computeStatusForObjectMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (int32, time.Time, string, error) {
|
func (a *HorizontalController) computeStatusForObjectMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (int32, time.Time, string, error) {
|
||||||
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(currentReplicas, metricSpec.Object.TargetValue.MilliValue(), metricSpec.Object.MetricName, hpa.Namespace, &metricSpec.Object.Target, selector)
|
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetObjectMetricReplicas(currentReplicas, metricSpec.Object.Target.Value.MilliValue(), metricSpec.Object.Metric.Name, hpa.Namespace, &metricSpec.Object.DescribedObject, selector, metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetObjectMetric", err.Error())
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetObjectMetric", err.Error())
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetObjectMetric", "the HPA was unable to compute the replica count: %v", err)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetObjectMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
@ -280,17 +292,22 @@ func (a *HorizontalController) computeStatusForObjectMetric(currentReplicas int3
|
|||||||
*status = autoscalingv2.MetricStatus{
|
*status = autoscalingv2.MetricStatus{
|
||||||
Type: autoscalingv2.ObjectMetricSourceType,
|
Type: autoscalingv2.ObjectMetricSourceType,
|
||||||
Object: &autoscalingv2.ObjectMetricStatus{
|
Object: &autoscalingv2.ObjectMetricStatus{
|
||||||
Target: metricSpec.Object.Target,
|
DescribedObject: metricSpec.Object.DescribedObject,
|
||||||
MetricName: metricSpec.Object.MetricName,
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
CurrentValue: *resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
Name: metricSpec.Object.Metric.Name,
|
||||||
|
Selector: metricSpec.Object.Metric.Selector,
|
||||||
|
},
|
||||||
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
|
Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return replicaCountProposal, timestampProposal, fmt.Sprintf("%s metric %s", metricSpec.Object.Target.Kind, metricSpec.Object.MetricName), nil
|
return replicaCountProposal, timestampProposal, fmt.Sprintf("%s metric %s", metricSpec.Object.DescribedObject.Kind, metricSpec.Object.Metric.Name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeStatusForPodsMetric computes the desired number of replicas for the specified metric of type PodsMetricSourceType.
|
// 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) (int32, time.Time, string, error) {
|
func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus, metricSelector labels.Selector) (int32, time.Time, string, error) {
|
||||||
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.TargetAverageValue.MilliValue(), metricSpec.Pods.MetricName, hpa.Namespace, selector)
|
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetMetricReplicas(currentReplicas, metricSpec.Pods.Target.AverageValue.MilliValue(), metricSpec.Pods.Metric.Name, hpa.Namespace, selector, metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetPodsMetric", err.Error())
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetPodsMetric", err.Error())
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetPodsMetric", "the HPA was unable to compute the replica count: %v", err)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetPodsMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
@ -299,19 +316,24 @@ func (a *HorizontalController) computeStatusForPodsMetric(currentReplicas int32,
|
|||||||
*status = autoscalingv2.MetricStatus{
|
*status = autoscalingv2.MetricStatus{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricStatus{
|
Pods: &autoscalingv2.PodsMetricStatus{
|
||||||
MetricName: metricSpec.Pods.MetricName,
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
CurrentAverageValue: *resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
Name: metricSpec.Pods.Metric.Name,
|
||||||
|
Selector: metricSpec.Pods.Metric.Selector,
|
||||||
|
},
|
||||||
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
|
AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return replicaCountProposal, timestampProposal, fmt.Sprintf("pods metric %s", metricSpec.Pods.MetricName), nil
|
return replicaCountProposal, timestampProposal, fmt.Sprintf("pods metric %s", metricSpec.Pods.Metric.Name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeStatusForResourceMetric computes the desired number of replicas for the specified metric of type ResourceMetricSourceType.
|
// computeStatusForResourceMetric computes the desired number of replicas for the specified metric of type ResourceMetricSourceType.
|
||||||
func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (int32, time.Time, string, error) {
|
func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (int32, time.Time, string, error) {
|
||||||
if metricSpec.Resource.TargetAverageValue != nil {
|
if metricSpec.Resource.Target.AverageValue != nil {
|
||||||
var rawProposal int64
|
var rawProposal int64
|
||||||
replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(currentReplicas, metricSpec.Resource.TargetAverageValue.MilliValue(), metricSpec.Resource.Name, hpa.Namespace, selector)
|
replicaCountProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetRawResourceReplicas(currentReplicas, metricSpec.Resource.Target.AverageValue.MilliValue(), metricSpec.Resource.Name, hpa.Namespace, selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetResourceMetric", err.Error())
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetResourceMetric", err.Error())
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetResourceMetric", "the HPA was unable to compute the replica count: %v", err)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetResourceMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
@ -322,18 +344,20 @@ func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas in
|
|||||||
Type: autoscalingv2.ResourceMetricSourceType,
|
Type: autoscalingv2.ResourceMetricSourceType,
|
||||||
Resource: &autoscalingv2.ResourceMetricStatus{
|
Resource: &autoscalingv2.ResourceMetricStatus{
|
||||||
Name: metricSpec.Resource.Name,
|
Name: metricSpec.Resource.Name,
|
||||||
CurrentAverageValue: *resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
|
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return replicaCountProposal, timestampProposal, metricNameProposal, nil
|
return replicaCountProposal, timestampProposal, metricNameProposal, nil
|
||||||
} else {
|
} else {
|
||||||
if metricSpec.Resource.TargetAverageUtilization == nil {
|
if metricSpec.Resource.Target.AverageUtilization == nil {
|
||||||
errMsg := "invalid resource metric source: neither a utilization target nor a value target was set"
|
errMsg := "invalid resource metric source: neither a utilization target nor a value target was set"
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetResourceMetric", errMsg)
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetResourceMetric", errMsg)
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetResourceMetric", "the HPA was unable to compute the replica count: %s", errMsg)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetResourceMetric", "the HPA was unable to compute the replica count: %s", errMsg)
|
||||||
return 0, time.Time{}, "", fmt.Errorf(errMsg)
|
return 0, time.Time{}, "", fmt.Errorf(errMsg)
|
||||||
}
|
}
|
||||||
targetUtilization := *metricSpec.Resource.TargetAverageUtilization
|
targetUtilization := *metricSpec.Resource.Target.AverageUtilization
|
||||||
var percentageProposal int32
|
var percentageProposal int32
|
||||||
var rawProposal int64
|
var rawProposal int64
|
||||||
replicaCountProposal, percentageProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetResourceReplicas(currentReplicas, targetUtilization, metricSpec.Resource.Name, hpa.Namespace, selector)
|
replicaCountProposal, percentageProposal, rawProposal, timestampProposal, err := a.replicaCalc.GetResourceReplicas(currentReplicas, targetUtilization, metricSpec.Resource.Name, hpa.Namespace, selector)
|
||||||
@ -347,8 +371,10 @@ func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas in
|
|||||||
Type: autoscalingv2.ResourceMetricSourceType,
|
Type: autoscalingv2.ResourceMetricSourceType,
|
||||||
Resource: &autoscalingv2.ResourceMetricStatus{
|
Resource: &autoscalingv2.ResourceMetricStatus{
|
||||||
Name: metricSpec.Resource.Name,
|
Name: metricSpec.Resource.Name,
|
||||||
CurrentAverageUtilization: &percentageProposal,
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
CurrentAverageValue: *resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
AverageUtilization: &percentageProposal,
|
||||||
|
AverageValue: resource.NewMilliQuantity(rawProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return replicaCountProposal, timestampProposal, metricNameProposal, nil
|
return replicaCountProposal, timestampProposal, metricNameProposal, nil
|
||||||
@ -357,39 +383,47 @@ func (a *HorizontalController) computeStatusForResourceMetric(currentReplicas in
|
|||||||
|
|
||||||
// computeStatusForExternalMetric computes the desired number of replicas for the specified metric of type ExternalMetricSourceType.
|
// computeStatusForExternalMetric computes the desired number of replicas for the specified metric of type ExternalMetricSourceType.
|
||||||
func (a *HorizontalController) computeStatusForExternalMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (int32, time.Time, string, error) {
|
func (a *HorizontalController) computeStatusForExternalMetric(currentReplicas int32, metricSpec autoscalingv2.MetricSpec, hpa *autoscalingv2.HorizontalPodAutoscaler, selector labels.Selector, status *autoscalingv2.MetricStatus) (int32, time.Time, string, error) {
|
||||||
if metricSpec.External.TargetAverageValue != nil {
|
if metricSpec.External.Target.AverageValue != nil {
|
||||||
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(currentReplicas, metricSpec.External.TargetAverageValue.MilliValue(), metricSpec.External.MetricName, hpa.Namespace, metricSpec.External.MetricSelector)
|
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalPerPodMetricReplicas(currentReplicas, metricSpec.External.Target.AverageValue.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", err.Error())
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", err.Error())
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetExternalMetric", "the HPA was unable to compute the replica count: %v", err)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetExternalMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
return 0, time.Time{}, "", fmt.Errorf("failed to get %s external metric: %v", metricSpec.External.MetricName, err)
|
return 0, time.Time{}, "", fmt.Errorf("failed to get %s external metric: %v", metricSpec.External.Metric.Name, err)
|
||||||
}
|
}
|
||||||
*status = autoscalingv2.MetricStatus{
|
*status = autoscalingv2.MetricStatus{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricStatus{
|
External: &autoscalingv2.ExternalMetricStatus{
|
||||||
MetricSelector: metricSpec.External.MetricSelector,
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: metricSpec.External.MetricName,
|
Name: metricSpec.External.Metric.Name,
|
||||||
CurrentAverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
Selector: metricSpec.External.Metric.Selector,
|
||||||
|
},
|
||||||
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
|
AverageValue: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.MetricName, metricSpec.External.MetricSelector), nil
|
return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.Metric.Name, metricSpec.External.Metric.Selector), nil
|
||||||
}
|
}
|
||||||
if metricSpec.External.TargetValue != nil {
|
if metricSpec.External.Target.Value != nil {
|
||||||
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(currentReplicas, metricSpec.External.TargetValue.MilliValue(), metricSpec.External.MetricName, hpa.Namespace, metricSpec.External.MetricSelector, selector)
|
replicaCountProposal, utilizationProposal, timestampProposal, err := a.replicaCalc.GetExternalMetricReplicas(currentReplicas, metricSpec.External.Target.Value.MilliValue(), metricSpec.External.Metric.Name, hpa.Namespace, metricSpec.External.Metric.Selector, selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", err.Error())
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", err.Error())
|
||||||
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetExternalMetric", "the HPA was unable to compute the replica count: %v", err)
|
setCondition(hpa, autoscalingv2.ScalingActive, v1.ConditionFalse, "FailedGetExternalMetric", "the HPA was unable to compute the replica count: %v", err)
|
||||||
return 0, time.Time{}, "", fmt.Errorf("failed to get external metric %s: %v", metricSpec.External.MetricName, err)
|
return 0, time.Time{}, "", fmt.Errorf("failed to get external metric %s: %v", metricSpec.External.Metric.Name, err)
|
||||||
}
|
}
|
||||||
*status = autoscalingv2.MetricStatus{
|
*status = autoscalingv2.MetricStatus{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricStatus{
|
External: &autoscalingv2.ExternalMetricStatus{
|
||||||
MetricSelector: metricSpec.External.MetricSelector,
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: metricSpec.External.MetricName,
|
Name: metricSpec.External.Metric.Name,
|
||||||
CurrentValue: *resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
Selector: metricSpec.External.Metric.Selector,
|
||||||
|
},
|
||||||
|
Current: autoscalingv2.MetricValueStatus{
|
||||||
|
Value: resource.NewMilliQuantity(utilizationProposal, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.MetricName, metricSpec.External.MetricSelector), nil
|
return replicaCountProposal, timestampProposal, fmt.Sprintf("external metric %s(%+v)", metricSpec.External.Metric.Name, metricSpec.External.Metric.Selector), nil
|
||||||
}
|
}
|
||||||
errMsg := "invalid external metric source: neither a value target nor an average value target was set"
|
errMsg := "invalid external metric source: neither a value target nor an average value target was set"
|
||||||
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", errMsg)
|
a.eventRecorder.Event(hpa, v1.EventTypeWarning, "FailedGetExternalMetric", errMsg)
|
||||||
|
@ -25,7 +25,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||||
autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
|
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
@ -42,7 +42,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
|
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
|
||||||
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||||
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
||||||
@ -214,7 +214,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
|||||||
Type: autoscalingv2.ResourceMetricSourceType,
|
Type: autoscalingv2.ResourceMetricSourceType,
|
||||||
Resource: &autoscalingv2.ResourceMetricSource{
|
Resource: &autoscalingv2.ResourceMetricSource{
|
||||||
Name: v1.ResourceCPU,
|
Name: v1.ResourceCPU,
|
||||||
TargetAverageUtilization: &tc.CPUTarget,
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageUtilization: &tc.CPUTarget,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -508,7 +510,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
|||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
},
|
},
|
||||||
Timestamp: metav1.Time{Time: time.Now()},
|
Timestamp: metav1.Time{Time: time.Now()},
|
||||||
MetricName: "qps",
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: "qps",
|
||||||
|
},
|
||||||
Value: *resource.NewMilliQuantity(int64(level), resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(int64(level), resource.DecimalSI),
|
||||||
}
|
}
|
||||||
metrics.Items = append(metrics.Items, podMetric)
|
metrics.Items = append(metrics.Items, podMetric)
|
||||||
@ -522,8 +526,8 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
|||||||
metrics := &cmapi.MetricValueList{}
|
metrics := &cmapi.MetricValueList{}
|
||||||
var matchedTarget *autoscalingv2.MetricSpec
|
var matchedTarget *autoscalingv2.MetricSpec
|
||||||
for i, target := range tc.metricsTarget {
|
for i, target := range tc.metricsTarget {
|
||||||
if target.Type == autoscalingv2.ObjectMetricSourceType && name == target.Object.Target.Name {
|
if target.Type == autoscalingv2.ObjectMetricSourceType && name == target.Object.DescribedObject.Name {
|
||||||
gk := schema.FromAPIVersionAndKind(target.Object.Target.APIVersion, target.Object.Target.Kind).GroupKind()
|
gk := schema.FromAPIVersionAndKind(target.Object.DescribedObject.APIVersion, target.Object.DescribedObject.Kind).GroupKind()
|
||||||
mapping, err := mapper.RESTMapping(gk)
|
mapping, err := mapper.RESTMapping(gk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("unable to get mapping for %s: %v", gk.String(), err)
|
t.Logf("unable to get mapping for %s: %v", gk.String(), err)
|
||||||
@ -542,12 +546,14 @@ func (tc *testCase) prepareTestClient(t *testing.T) (*fake.Clientset, *metricsfa
|
|||||||
metrics.Items = []cmapi.MetricValue{
|
metrics.Items = []cmapi.MetricValue{
|
||||||
{
|
{
|
||||||
DescribedObject: v1.ObjectReference{
|
DescribedObject: v1.ObjectReference{
|
||||||
Kind: matchedTarget.Object.Target.Kind,
|
Kind: matchedTarget.Object.DescribedObject.Kind,
|
||||||
APIVersion: matchedTarget.Object.Target.APIVersion,
|
APIVersion: matchedTarget.Object.DescribedObject.APIVersion,
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Timestamp: metav1.Time{Time: time.Now()},
|
Timestamp: metav1.Time{Time: time.Now()},
|
||||||
MetricName: "qps",
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: "qps",
|
||||||
|
},
|
||||||
Value: *resource.NewMilliQuantity(int64(tc.reportedLevels[0]), resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(int64(tc.reportedLevels[0]), resource.DecimalSI),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -847,6 +853,7 @@ func TestScaleUpReplicaSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleUpCM(t *testing.T) {
|
func TestScaleUpCM(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -857,8 +864,12 @@ func TestScaleUpCM(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -869,6 +880,7 @@ func TestScaleUpCM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleUpCMUnreadyAndHotCpuNoLessScale(t *testing.T) {
|
func TestScaleUpCMUnreadyAndHotCpuNoLessScale(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -879,8 +891,12 @@ func TestScaleUpCMUnreadyAndHotCpuNoLessScale(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -893,6 +909,7 @@ func TestScaleUpCMUnreadyAndHotCpuNoLessScale(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleUpCMUnreadyandCpuHot(t *testing.T) {
|
func TestScaleUpCMUnreadyandCpuHot(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -903,8 +920,12 @@ func TestScaleUpCMUnreadyandCpuHot(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -926,6 +947,7 @@ func TestScaleUpCMUnreadyandCpuHot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleUpHotCpuNoScaleWouldScaleDown(t *testing.T) {
|
func TestScaleUpHotCpuNoScaleWouldScaleDown(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -936,8 +958,12 @@ func TestScaleUpHotCpuNoScaleWouldScaleDown(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -958,6 +984,7 @@ func TestScaleUpHotCpuNoScaleWouldScaleDown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleUpCMObject(t *testing.T) {
|
func TestScaleUpCMObject(t *testing.T) {
|
||||||
|
targetValue := resource.MustParse("15.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -968,13 +995,17 @@ func TestScaleUpCMObject(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ObjectMetricSourceType,
|
Type: autoscalingv2.ObjectMetricSourceType,
|
||||||
Object: &autoscalingv2.ObjectMetricSource{
|
Object: &autoscalingv2.ObjectMetricSource{
|
||||||
Target: autoscalingv2.CrossVersionObjectReference{
|
DescribedObject: autoscalingv2.CrossVersionObjectReference{
|
||||||
APIVersion: "extensions/v1beta1",
|
APIVersion: "extensions/v1beta1",
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
Name: "some-deployment",
|
Name: "some-deployment",
|
||||||
},
|
},
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: &targetValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -993,9 +1024,13 @@ func TestScaleUpCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetValue: resource.NewMilliQuantity(6666, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: resource.NewMilliQuantity(6666, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1014,9 +1049,13 @@ func TestScaleUpPerPodCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetAverageValue: resource.NewMilliQuantity(2222, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: resource.NewMilliQuantity(2222, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1041,6 +1080,7 @@ func TestScaleDown(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleDownCM(t *testing.T) {
|
func TestScaleDownCM(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("20.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -1051,8 +1091,12 @@ func TestScaleDownCM(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("20.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1063,6 +1107,7 @@ func TestScaleDownCM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestScaleDownCMObject(t *testing.T) {
|
func TestScaleDownCMObject(t *testing.T) {
|
||||||
|
targetValue := resource.MustParse("20.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 2,
|
minReplicas: 2,
|
||||||
maxReplicas: 6,
|
maxReplicas: 6,
|
||||||
@ -1073,13 +1118,17 @@ func TestScaleDownCMObject(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ObjectMetricSourceType,
|
Type: autoscalingv2.ObjectMetricSourceType,
|
||||||
Object: &autoscalingv2.ObjectMetricSource{
|
Object: &autoscalingv2.ObjectMetricSource{
|
||||||
Target: autoscalingv2.CrossVersionObjectReference{
|
DescribedObject: autoscalingv2.CrossVersionObjectReference{
|
||||||
APIVersion: "extensions/v1beta1",
|
APIVersion: "extensions/v1beta1",
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
Name: "some-deployment",
|
Name: "some-deployment",
|
||||||
},
|
},
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetValue: resource.MustParse("20.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: &targetValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1099,9 +1148,13 @@ func TestScaleDownCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetValue: resource.NewMilliQuantity(14400, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: resource.NewMilliQuantity(14400, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1120,9 +1173,13 @@ func TestScaleDownPerPodCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetAverageValue: resource.NewMilliQuantity(3000, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: resource.NewMilliQuantity(3000, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1203,6 +1260,7 @@ func TestTolerance(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToleranceCM(t *testing.T) {
|
func TestToleranceCM(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("20.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 1,
|
minReplicas: 1,
|
||||||
maxReplicas: 5,
|
maxReplicas: 5,
|
||||||
@ -1212,8 +1270,12 @@ func TestToleranceCM(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("20.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1229,6 +1291,7 @@ func TestToleranceCM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestToleranceCMObject(t *testing.T) {
|
func TestToleranceCMObject(t *testing.T) {
|
||||||
|
targetValue := resource.MustParse("20.0")
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 1,
|
minReplicas: 1,
|
||||||
maxReplicas: 5,
|
maxReplicas: 5,
|
||||||
@ -1238,13 +1301,17 @@ func TestToleranceCMObject(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ObjectMetricSourceType,
|
Type: autoscalingv2.ObjectMetricSourceType,
|
||||||
Object: &autoscalingv2.ObjectMetricSource{
|
Object: &autoscalingv2.ObjectMetricSource{
|
||||||
Target: autoscalingv2.CrossVersionObjectReference{
|
DescribedObject: autoscalingv2.CrossVersionObjectReference{
|
||||||
APIVersion: "extensions/v1beta1",
|
APIVersion: "extensions/v1beta1",
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
Name: "some-deployment",
|
Name: "some-deployment",
|
||||||
},
|
},
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetValue: resource.MustParse("20.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: &targetValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1269,9 +1336,13 @@ func TestToleranceCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetValue: resource.NewMilliQuantity(8666, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: resource.NewMilliQuantity(8666, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1295,9 +1366,13 @@ func TestTolerancePerPodCMExternal(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetAverageValue: resource.NewMilliQuantity(2200, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: resource.NewMilliQuantity(2200, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1669,14 +1744,20 @@ func TestConditionInvalidSelectorUnparsable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConditionFailedGetMetrics(t *testing.T) {
|
func TestConditionFailedGetMetrics(t *testing.T) {
|
||||||
|
targetValue := resource.MustParse("15.0")
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
metricsTargets := map[string][]autoscalingv2.MetricSpec{
|
metricsTargets := map[string][]autoscalingv2.MetricSpec{
|
||||||
"FailedGetResourceMetric": nil,
|
"FailedGetResourceMetric": nil,
|
||||||
"FailedGetPodsMetric": {
|
"FailedGetPodsMetric": {
|
||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1684,13 +1765,17 @@ func TestConditionFailedGetMetrics(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ObjectMetricSourceType,
|
Type: autoscalingv2.ObjectMetricSourceType,
|
||||||
Object: &autoscalingv2.ObjectMetricSource{
|
Object: &autoscalingv2.ObjectMetricSource{
|
||||||
Target: autoscalingv2.CrossVersionObjectReference{
|
DescribedObject: autoscalingv2.CrossVersionObjectReference{
|
||||||
APIVersion: "extensions/v1beta1",
|
APIVersion: "extensions/v1beta1",
|
||||||
Kind: "Deployment",
|
Kind: "Deployment",
|
||||||
Name: "some-deployment",
|
Name: "some-deployment",
|
||||||
},
|
},
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: &targetValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1698,9 +1783,13 @@ func TestConditionFailedGetMetrics(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.ExternalMetricSourceType,
|
Type: autoscalingv2.ExternalMetricSourceType,
|
||||||
External: &autoscalingv2.ExternalMetricSource{
|
External: &autoscalingv2.ExternalMetricSource{
|
||||||
MetricSelector: &metav1.LabelSelector{},
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
MetricName: "qps",
|
Name: "qps",
|
||||||
TargetValue: resource.NewMilliQuantity(300, resource.DecimalSI),
|
Selector: &metav1.LabelSelector{},
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
Value: resource.NewMilliQuantity(300, resource.DecimalSI),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1857,6 +1946,7 @@ func NoTestBackoffUpscale(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNoBackoffUpscaleCM(t *testing.T) {
|
func TestNoBackoffUpscaleCM(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
time := metav1.Time{Time: time.Now()}
|
time := metav1.Time{Time: time.Now()}
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 1,
|
minReplicas: 1,
|
||||||
@ -1868,8 +1958,12 @@ func TestNoBackoffUpscaleCM(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1895,6 +1989,7 @@ func TestNoBackoffUpscaleCM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNoBackoffUpscaleCMNoBackoffCpu(t *testing.T) {
|
func TestNoBackoffUpscaleCMNoBackoffCpu(t *testing.T) {
|
||||||
|
averageValue := resource.MustParse("15.0")
|
||||||
time := metav1.Time{Time: time.Now()}
|
time := metav1.Time{Time: time.Now()}
|
||||||
tc := testCase{
|
tc := testCase{
|
||||||
minReplicas: 1,
|
minReplicas: 1,
|
||||||
@ -1906,8 +2001,12 @@ func TestNoBackoffUpscaleCMNoBackoffCpu(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Type: autoscalingv2.PodsMetricSourceType,
|
Type: autoscalingv2.PodsMetricSourceType,
|
||||||
Pods: &autoscalingv2.PodsMetricSource{
|
Pods: &autoscalingv2.PodsMetricSource{
|
||||||
MetricName: "qps",
|
Metric: autoscalingv2.MetricIdentifier{
|
||||||
TargetAverageValue: resource.MustParse("15.0"),
|
Name: "qps",
|
||||||
|
},
|
||||||
|
Target: autoscalingv2.MetricTarget{
|
||||||
|
AverageValue: &averageValue,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -210,7 +210,7 @@ func (tc *legacyReplicaCalcTestCase) runTest(t *testing.T) {
|
|||||||
assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
|
assert.True(t, tc.timestamp.Equal(outTimestamp), "timestamp should be as expected")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
outReplicas, outUtilization, outTimestamp, err := replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector)
|
outReplicas, outUtilization, outTimestamp, err := replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
|
||||||
|
|
||||||
if tc.expectedError != nil {
|
if tc.expectedError != nil {
|
||||||
require.Error(t, err, "there should be an error calculating the replica count")
|
require.Error(t, err, "there should be an error calculating the replica count")
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
"go_test",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
@ -15,15 +9,16 @@ go_library(
|
|||||||
"utilization.go",
|
"utilization.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics",
|
importpath = "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
|
||||||
@ -44,7 +39,7 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/extensions/install:go_default_library",
|
"//pkg/apis/extensions/install:go_default_library",
|
||||||
"//staging/src/k8s.io/api/autoscaling/v2beta1:go_default_library",
|
"//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
@ -55,7 +50,7 @@ go_test(
|
|||||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/custom_metrics/v1beta2:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/external_metrics/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1alpha1:go_default_library",
|
||||||
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
|
"//staging/src/k8s.io/metrics/pkg/apis/metrics/v1beta1:go_default_library",
|
||||||
@ -78,4 +73,5 @@ filegroup(
|
|||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [":package-srcs"],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,7 @@ package metrics
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
autoscaling "k8s.io/api/autoscaling/v2beta1"
|
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
)
|
)
|
||||||
@ -37,11 +37,11 @@ type MetricsClient interface {
|
|||||||
|
|
||||||
// GetRawMetric gets the given metric (and an associated oldest timestamp)
|
// GetRawMetric gets the given metric (and an associated oldest timestamp)
|
||||||
// for all pods matching the specified selector in the given namespace
|
// for all pods matching the specified selector in the given namespace
|
||||||
GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error)
|
GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error)
|
||||||
|
|
||||||
// GetObjectMetric gets the given metric (and an associated timestamp) for the given
|
// GetObjectMetric gets the given metric (and an associated timestamp) for the given
|
||||||
// object in the given namespace
|
// object in the given namespace
|
||||||
GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error)
|
GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error)
|
||||||
|
|
||||||
// GetExternalMetric gets all the values of a given external metric
|
// GetExternalMetric gets all the values of a given external metric
|
||||||
// that match the specified selector.
|
// that match the specified selector.
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
heapster "k8s.io/heapster/metrics/api/v1/types"
|
heapster "k8s.io/heapster/metrics/api/v1/types"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||||
|
|
||||||
autoscaling "k8s.io/api/autoscaling/v2beta1"
|
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
@ -109,7 +109,7 @@ func (h *HeapsterMetricsClient) GetResourceMetric(resource v1.ResourceName, name
|
|||||||
return res, timestamp, nil
|
return res, timestamp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
||||||
podList, err := h.podsGetter.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
|
podList, err := h.podsGetter.Pods(namespace).List(metav1.ListOptions{LabelSelector: selector.String()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, time.Time{}, fmt.Errorf("failed to get pod list while fetching metrics: %v", err)
|
return nil, time.Time{}, fmt.Errorf("failed to get pod list while fetching metrics: %v", err)
|
||||||
@ -173,7 +173,7 @@ func (h *HeapsterMetricsClient) GetRawMetric(metricName string, namespace string
|
|||||||
return res, *timestamp, nil
|
return res, *timestamp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeapsterMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error) {
|
func (h *HeapsterMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error) {
|
||||||
return 0, time.Time{}, fmt.Errorf("object metrics are not yet supported")
|
return 0, time.Time{}, fmt.Errorf("object metrics are not yet supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ type testCase struct {
|
|||||||
|
|
||||||
namespace string
|
namespace string
|
||||||
selector labels.Selector
|
selector labels.Selector
|
||||||
|
metricSelector labels.Selector
|
||||||
resourceName v1.ResourceName
|
resourceName v1.ResourceName
|
||||||
metricName string
|
metricName string
|
||||||
}
|
}
|
||||||
@ -211,7 +212,7 @@ func (tc *testCase) runTest(t *testing.T) {
|
|||||||
info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector)
|
info, timestamp, err := metricsClient.GetResourceMetric(tc.resourceName, tc.namespace, tc.selector)
|
||||||
tc.verifyResults(t, info, timestamp, err)
|
tc.verifyResults(t, info, timestamp, err)
|
||||||
} else {
|
} else {
|
||||||
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector)
|
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector, tc.metricSelector)
|
||||||
tc.verifyResults(t, info, timestamp, err)
|
tc.verifyResults(t, info, timestamp, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,12 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
autoscaling "k8s.io/api/autoscaling/v2beta1"
|
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
customapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
customapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||||
resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
|
resourceclient "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1"
|
||||||
customclient "k8s.io/metrics/pkg/client/custom_metrics"
|
customclient "k8s.io/metrics/pkg/client/custom_metrics"
|
||||||
externalclient "k8s.io/metrics/pkg/client/external_metrics"
|
externalclient "k8s.io/metrics/pkg/client/external_metrics"
|
||||||
@ -101,8 +101,8 @@ type customMetricsClient struct {
|
|||||||
|
|
||||||
// GetRawMetric gets the given metric (and an associated oldest timestamp)
|
// GetRawMetric gets the given metric (and an associated oldest timestamp)
|
||||||
// for all pods matching the specified selector in the given namespace
|
// for all pods matching the specified selector in the given namespace
|
||||||
func (c *customMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
func (c *customMetricsClient) GetRawMetric(metricName string, namespace string, selector labels.Selector, metricSelector labels.Selector) (PodMetricsInfo, time.Time, error) {
|
||||||
metrics, err := c.client.NamespacedMetrics(namespace).GetForObjects(schema.GroupKind{Kind: "Pod"}, selector, metricName)
|
metrics, err := c.client.NamespacedMetrics(namespace).GetForObjects(schema.GroupKind{Kind: "Pod"}, selector, metricName, metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, time.Time{}, fmt.Errorf("unable to fetch metrics from custom metrics API: %v", err)
|
return nil, time.Time{}, fmt.Errorf("unable to fetch metrics from custom metrics API: %v", err)
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ func (c *customMetricsClient) GetRawMetric(metricName string, namespace string,
|
|||||||
|
|
||||||
// GetObjectMetric gets the given metric (and an associated timestamp) for the given
|
// GetObjectMetric gets the given metric (and an associated timestamp) for the given
|
||||||
// object in the given namespace
|
// object in the given namespace
|
||||||
func (c *customMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference) (int64, time.Time, error) {
|
func (c *customMetricsClient) GetObjectMetric(metricName string, namespace string, objectRef *autoscaling.CrossVersionObjectReference, metricSelector labels.Selector) (int64, time.Time, error) {
|
||||||
gvk := schema.FromAPIVersionAndKind(objectRef.APIVersion, objectRef.Kind)
|
gvk := schema.FromAPIVersionAndKind(objectRef.APIVersion, objectRef.Kind)
|
||||||
var metricValue *customapi.MetricValue
|
var metricValue *customapi.MetricValue
|
||||||
var err error
|
var err error
|
||||||
@ -131,9 +131,9 @@ func (c *customMetricsClient) GetObjectMetric(metricName string, namespace strin
|
|||||||
// handle namespace separately
|
// handle namespace separately
|
||||||
// NB: we ignore namespace name here, since CrossVersionObjectReference isn't
|
// NB: we ignore namespace name here, since CrossVersionObjectReference isn't
|
||||||
// supposed to allow you to escape your namespace
|
// supposed to allow you to escape your namespace
|
||||||
metricValue, err = c.client.RootScopedMetrics().GetForObject(gvk.GroupKind(), namespace, metricName)
|
metricValue, err = c.client.RootScopedMetrics().GetForObject(gvk.GroupKind(), namespace, metricName, metricSelector)
|
||||||
} else {
|
} else {
|
||||||
metricValue, err = c.client.NamespacedMetrics(namespace).GetForObject(gvk.GroupKind(), objectRef.Name, metricName)
|
metricValue, err = c.client.NamespacedMetrics(namespace).GetForObject(gvk.GroupKind(), objectRef.Name, metricName, metricSelector)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
autoscalingapi "k8s.io/api/autoscaling/v2beta1"
|
autoscalingapi "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
@ -32,7 +32,7 @@ import (
|
|||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||||
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||||
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
||||||
@ -145,7 +145,9 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
|
|||||||
},
|
},
|
||||||
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
|
||||||
Timestamp: metav1.Time{Time: timestamp},
|
Timestamp: metav1.Time{Time: timestamp},
|
||||||
MetricName: tc.metricName,
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: tc.metricName,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.Items = append(metrics.Items, metric)
|
metrics.Items = append(metrics.Items, metric)
|
||||||
@ -177,7 +179,9 @@ func (tc *restClientTestCase) prepareTestClient(t *testing.T) (*metricsfake.Clie
|
|||||||
Name: tc.singleObject.Name,
|
Name: tc.singleObject.Name,
|
||||||
},
|
},
|
||||||
Timestamp: metav1.Time{Time: timestamp},
|
Timestamp: metav1.Time{Time: timestamp},
|
||||||
MetricName: tc.metricName,
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: tc.metricName,
|
||||||
|
},
|
||||||
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(int64(metricPoint.level), resource.DecimalSI),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -227,10 +231,10 @@ func (tc *restClientTestCase) runTest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tc.verifyResults(t, info, timestamp, err)
|
tc.verifyResults(t, info, timestamp, err)
|
||||||
} else if tc.singleObject == nil {
|
} else if tc.singleObject == nil {
|
||||||
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector)
|
info, timestamp, err := metricsClient.GetRawMetric(tc.metricName, tc.namespace, tc.selector, tc.metricLabelSelector)
|
||||||
tc.verifyResults(t, info, timestamp, err)
|
tc.verifyResults(t, info, timestamp, err)
|
||||||
} else {
|
} else {
|
||||||
val, timestamp, err := metricsClient.GetObjectMetric(tc.metricName, tc.namespace, tc.singleObject)
|
val, timestamp, err := metricsClient.GetObjectMetric(tc.metricName, tc.namespace, tc.singleObject, tc.metricLabelSelector)
|
||||||
info := PodMetricsInfo{tc.singleObject.Name: val}
|
info := PodMetricsInfo{tc.singleObject.Name: val}
|
||||||
tc.verifyResults(t, info, timestamp, err)
|
tc.verifyResults(t, info, timestamp, err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
autoscaling "k8s.io/api/autoscaling/v2beta1"
|
autoscaling "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
@ -159,8 +159,8 @@ func (c *ReplicaCalculator) GetRawResourceReplicas(currentReplicas int32, target
|
|||||||
// GetMetricReplicas calculates the desired replica count based on a target metric utilization
|
// GetMetricReplicas calculates the desired replica count based on a target metric utilization
|
||||||
// (as a milli-value) for pods matching the given selector in the given namespace, and the
|
// (as a milli-value) for pods matching the given selector in the given namespace, and the
|
||||||
// current replica count
|
// current replica count
|
||||||
func (c *ReplicaCalculator) GetMetricReplicas(currentReplicas int32, targetUtilization int64, metricName string, namespace string, selector labels.Selector) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
|
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) {
|
||||||
metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector)
|
metrics, timestamp, err := c.metricsClient.GetRawMetric(metricName, namespace, selector, metricSelector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err)
|
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v", metricName, err)
|
||||||
}
|
}
|
||||||
@ -238,8 +238,8 @@ func (c *ReplicaCalculator) calcPlainMetricReplicas(metrics metricsclient.PodMet
|
|||||||
|
|
||||||
// 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 utilization (as a milli-value)
|
||||||
// for the given object in the given namespace, and the current replica count.
|
// 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) (replicaCount int32, utilization int64, timestamp time.Time, err error) {
|
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, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef)
|
utilization, timestamp, err = c.metricsClient.GetObjectMetric(metricName, namespace, objectRef, metricSelector)
|
||||||
if err != nil {
|
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)
|
return 0, 0, time.Time{}, fmt.Errorf("unable to get metric %s: %v on %s %s/%s", metricName, objectRef.Kind, namespace, objectRef.Name, err)
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,20 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
autoscalingv2 "k8s.io/api/autoscaling/v2beta1"
|
autoscalingv2 "k8s.io/api/autoscaling/v2beta2"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
|
|
||||||
metricsclient "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
|
metricsclient "k8s.io/kubernetes/pkg/controller/podautoscaler/metrics"
|
||||||
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta1"
|
cmapi "k8s.io/metrics/pkg/apis/custom_metrics/v1beta2"
|
||||||
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
emapi "k8s.io/metrics/pkg/apis/external_metrics/v1beta1"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
metricsfake "k8s.io/metrics/pkg/client/clientset/versioned/fake"
|
||||||
@ -88,6 +88,7 @@ type replicaCalcTestCase struct {
|
|||||||
|
|
||||||
resource *resourceInfo
|
resource *resourceInfo
|
||||||
metric *metricInfo
|
metric *metricInfo
|
||||||
|
metricLabelSelector labels.Selector
|
||||||
|
|
||||||
podReadiness []v1.ConditionStatus
|
podReadiness []v1.ConditionStatus
|
||||||
podStartTime []metav1.Time
|
podStartTime []metav1.Time
|
||||||
@ -236,7 +237,9 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus
|
|||||||
Namespace: testNamespace,
|
Namespace: testNamespace,
|
||||||
},
|
},
|
||||||
Timestamp: metav1.Time{Time: tc.timestamp},
|
Timestamp: metav1.Time{Time: tc.timestamp},
|
||||||
MetricName: tc.metric.name,
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: tc.metric.name,
|
||||||
|
},
|
||||||
Value: *resource.NewMilliQuantity(level, resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(level, resource.DecimalSI),
|
||||||
}
|
}
|
||||||
metrics.Items = append(metrics.Items, podMetric)
|
metrics.Items = append(metrics.Items, podMetric)
|
||||||
@ -266,7 +269,9 @@ func (tc *replicaCalcTestCase) prepareTestCMClient(t *testing.T) *cmfake.FakeCus
|
|||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Timestamp: metav1.Time{Time: tc.timestamp},
|
Timestamp: metav1.Time{Time: tc.timestamp},
|
||||||
MetricName: tc.metric.name,
|
Metric: cmapi.MetricIdentifier{
|
||||||
|
Name: tc.metric.name,
|
||||||
|
},
|
||||||
Value: *resource.NewMilliQuantity(int64(tc.metric.levels[0]), resource.DecimalSI),
|
Value: *resource.NewMilliQuantity(int64(tc.metric.levels[0]), resource.DecimalSI),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -322,7 +327,7 @@ func (tc *replicaCalcTestCase) prepareTestClient(t *testing.T) (*fake.Clientset,
|
|||||||
|
|
||||||
func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
||||||
testClient, testMetricsClient, testCMClient, testEMClient := tc.prepareTestClient(t)
|
testClient, testMetricsClient, testCMClient, testEMClient := tc.prepareTestClient(t)
|
||||||
metricsClient := metrics.NewRESTMetricsClient(testMetricsClient.MetricsV1beta1(), testCMClient, testEMClient)
|
metricsClient := metricsclient.NewRESTMetricsClient(testMetricsClient.MetricsV1beta1(), testCMClient, testEMClient)
|
||||||
|
|
||||||
replicaCalc := NewReplicaCalculator(metricsClient, testClient.Core(), defaultTestingTolerance, defaultTestingCpuTaintAfterStart, defaultTestingDelayOfInitialReadinessStatus)
|
replicaCalc := NewReplicaCalculator(metricsClient, testClient.Core(), defaultTestingTolerance, defaultTestingCpuTaintAfterStart, defaultTestingDelayOfInitialReadinessStatus)
|
||||||
|
|
||||||
@ -357,7 +362,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
|||||||
if tc.metric.singleObject == nil {
|
if tc.metric.singleObject == nil {
|
||||||
t.Fatal("Metric specified as objectMetric but metric.singleObject is 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)
|
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetObjectMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, tc.metric.singleObject, selector, nil)
|
||||||
case externalMetric:
|
case externalMetric:
|
||||||
if tc.metric.selector == nil {
|
if tc.metric.selector == nil {
|
||||||
t.Fatal("Metric specified as externalMetric but metric.selector is nil.")
|
t.Fatal("Metric specified as externalMetric but metric.selector is nil.")
|
||||||
@ -376,7 +381,7 @@ func (tc *replicaCalcTestCase) runTest(t *testing.T) {
|
|||||||
|
|
||||||
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector)
|
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetExternalPerPodMetricReplicas(tc.currentReplicas, tc.metric.perPodTargetUtilization, tc.metric.name, testNamespace, tc.metric.selector)
|
||||||
case podMetric:
|
case podMetric:
|
||||||
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector)
|
outReplicas, outUtilization, outTimestamp, err = replicaCalc.GetMetricReplicas(tc.currentReplicas, tc.metric.targetUtilization, tc.metric.name, testNamespace, selector, nil)
|
||||||
default:
|
default:
|
||||||
t.Fatalf("Unknown metric type: %d", tc.metric.metricType)
|
t.Fatalf("Unknown metric type: %d", tc.metric.metricType)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user