From 6f54f382aae5cba6a4ca1fb4c21de62d6d3d7e92 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 18:41:01 +0200 Subject: [PATCH] Expose Horizontal Pod Autoscaler Behavior and add hpa scaledown test (#1077) * Add scaledown test for autoscaling Signed-off-by: Kevin Earls * Fix nits Signed-off-by: Kevin Earls * Appease the linter Signed-off-by: Kevin Earls * Don't use a default, only set scaleUp/scaleDown if they are in the CR Signed-off-by: Kevin Earls * Removed commented out code Signed-off-by: Kevin Earls * Change defaults for scaleUp/scaleDown Signed-off-by: Kevin Earls * Update autoscaling scaleup/scaledown Signed-off-by: Kevin Earls * Run generate Signed-off-by: Kevin Earls * Ran make api-docs Signed-off-by: Kevin Earls * Update HPA implementation to embed HorizontalPodAutoscalerBehavior Signed-off-by: Kevin Earls * Only set behavior if it exists in the collector CR Signed-off-by: Kevin Earls * Aded some unit tests Signed-off-by: Kevin Earls * Add kuttl assertion that hpa scaled down Signed-off-by: Kevin Earls * added whitespace to rerun tests Signed-off-by: Kevin Earls Signed-off-by: Kevin Earls --- apis/v1alpha1/opentelemetrycollector_types.go | 14 + .../opentelemetrycollector_webhook.go | 9 + apis/v1alpha1/zz_generated.deepcopy.go | 28 +- ...ntelemetry.io_opentelemetrycollectors.yaml | 124 +++++++++ ...ntelemetry.io_opentelemetrycollectors.yaml | 124 +++++++++ docs/api.md | 244 ++++++++++++++++++ pkg/collector/horizontalpodautoscaler.go | 91 +++++++ pkg/collector/horizontalpodautoscaler_test.go | 53 ++++ tests/e2e/autoscale/00-assert.yaml | 3 + tests/e2e/autoscale/00-install.yaml | 6 + tests/e2e/autoscale/02-assert.yaml | 8 + 11 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 tests/e2e/autoscale/02-assert.yaml diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index ac79522da0..862d91f6db 100644 --- a/apis/v1alpha1/opentelemetrycollector_types.go +++ b/apis/v1alpha1/opentelemetrycollector_types.go @@ -15,6 +15,7 @@ package v1alpha1 import ( + autoscalingv2 "k8s.io/api/autoscaling/v2" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -40,6 +41,13 @@ type OpenTelemetryCollectorSpec struct { // MaxReplicas sets an upper bound to the autoscaling feature. If MaxReplicas is set autoscaling is enabled. // +optional MaxReplicas *int32 `json:"maxReplicas,omitempty"` + + // Autoscaler specifies the pod autoscaling configuration to use + // for the OpenTelemetryCollector workload. + // + // +optional + Autoscaler *AutoscalerSpec `json:"autoscaler,omitempty"` + // SecurityContext will be set as the container security context. // +optional SecurityContext *v1.SecurityContext `json:"securityContext,omitempty"` @@ -197,6 +205,12 @@ type OpenTelemetryCollectorList struct { Items []OpenTelemetryCollector `json:"items"` } +// AutoscalerSpec defines the OpenTelemetryCollector's pod autoscaling specification. +type AutoscalerSpec struct { + // +optional + Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"` +} + func init() { SchemeBuilder.Register(&OpenTelemetryCollector{}, &OpenTelemetryCollectorList{}) } diff --git a/apis/v1alpha1/opentelemetrycollector_webhook.go b/apis/v1alpha1/opentelemetrycollector_webhook.go index 6a4b1e936f..b8df65c956 100644 --- a/apis/v1alpha1/opentelemetrycollector_webhook.go +++ b/apis/v1alpha1/opentelemetrycollector_webhook.go @@ -129,6 +129,15 @@ func (r *OpenTelemetryCollector) validateCRDSpec() error { return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, minReplicas should be one or more") } + if r.Spec.Autoscaler != nil && r.Spec.Autoscaler.Behavior != nil { + if r.Spec.Autoscaler.Behavior.ScaleDown != nil && *r.Spec.Autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds < int32(1) { + return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleDown should be one or more") + } + + if r.Spec.Autoscaler.Behavior.ScaleUp != nil && *r.Spec.Autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds < int32(1) { + return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleUp should be one or more") + } + } } return nil diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 776bebf9fd..0f81becc74 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -20,10 +20,31 @@ package v1alpha1 import ( - v1 "k8s.io/api/core/v1" + "k8s.io/api/autoscaling/v2" + "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscalerSpec) DeepCopyInto(out *AutoscalerSpec) { + *out = *in + if in.Behavior != nil { + in, out := &in.Behavior, &out.Behavior + *out = new(v2.HorizontalPodAutoscalerBehavior) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerSpec. +func (in *AutoscalerSpec) DeepCopy() *AutoscalerSpec { + if in == nil { + return nil + } + out := new(AutoscalerSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DotNet) DeepCopyInto(out *DotNet) { *out = *in @@ -305,6 +326,11 @@ func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSp *out = new(int32) **out = **in } + if in.Autoscaler != nil { + in, out := &in.Autoscaler, &out.Autoscaler + *out = new(AutoscalerSpec) + (*in).DeepCopyInto(*out) + } if in.SecurityContext != nil { in, out := &in.SecurityContext, &out.SecurityContext *out = new(v1.SecurityContext) diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index 01dc8f2e2b..d7f09b06a0 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -59,6 +59,130 @@ spec: description: Args is the set of arguments to pass to the OpenTelemetry Collector binary type: object + autoscaler: + description: Autoscaler specifies the pod autoscaling configuration + to use for the OpenTelemetryCollector workload. + properties: + behavior: + description: HorizontalPodAutoscalerBehavior configures the scaling + behavior of the target in both Up and Down directions (scaleUp + and scaleDown fields respectively). + properties: + scaleDown: + description: scaleDown is scaling policy for scaling Down. + If not set, the default value is to allow to scale down + to minReplicas pods, with a 300 second stabilization window + (i.e., the highest recommendation for the last 300sec is + used). + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: PeriodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: Type is used to specify the scaling + policy. + type: string + value: + description: Value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: 'StabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. StabilizationWindowSeconds + must be greater than or equal to zero and less than + or equal to 3600 (one hour). If not set, use the default + values: - For scale up: 0 (i.e. no stabilization is + done). - For scale down: 300 (i.e. the stabilization + window is 300 seconds long).' + format: int32 + type: integer + type: object + scaleUp: + description: 'scaleUp is scaling policy for scaling Up. If + not set, the default value is the higher of: * increase + no more than 4 pods per 60 seconds * double the number of + pods per 60 seconds No stabilization is used.' + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: PeriodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: Type is used to specify the scaling + policy. + type: string + value: + description: Value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: 'StabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. StabilizationWindowSeconds + must be greater than or equal to zero and less than + or equal to 3600 (one hour). If not set, use the default + values: - For scale up: 0 (i.e. no stabilization is + done). - For scale down: 300 (i.e. the stabilization + window is 300 seconds long).' + format: int32 + type: integer + type: object + type: object + type: object config: description: Config is the raw JSON to be used as the collector's configuration. Refer to the OpenTelemetry Collector documentation diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index b2f0bf3d0c..88e8f28cfd 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -57,6 +57,130 @@ spec: description: Args is the set of arguments to pass to the OpenTelemetry Collector binary type: object + autoscaler: + description: Autoscaler specifies the pod autoscaling configuration + to use for the OpenTelemetryCollector workload. + properties: + behavior: + description: HorizontalPodAutoscalerBehavior configures the scaling + behavior of the target in both Up and Down directions (scaleUp + and scaleDown fields respectively). + properties: + scaleDown: + description: scaleDown is scaling policy for scaling Down. + If not set, the default value is to allow to scale down + to minReplicas pods, with a 300 second stabilization window + (i.e., the highest recommendation for the last 300sec is + used). + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: PeriodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: Type is used to specify the scaling + policy. + type: string + value: + description: Value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: 'StabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. StabilizationWindowSeconds + must be greater than or equal to zero and less than + or equal to 3600 (one hour). If not set, use the default + values: - For scale up: 0 (i.e. no stabilization is + done). - For scale down: 300 (i.e. the stabilization + window is 300 seconds long).' + format: int32 + type: integer + type: object + scaleUp: + description: 'scaleUp is scaling policy for scaling Up. If + not set, the default value is the higher of: * increase + no more than 4 pods per 60 seconds * double the number of + pods per 60 seconds No stabilization is used.' + properties: + policies: + description: policies is a list of potential scaling polices + which can be used during scaling. At least one policy + must be specified, otherwise the HPAScalingRules will + be discarded as invalid + items: + description: HPAScalingPolicy is a single policy which + must hold true for a specified past interval. + properties: + periodSeconds: + description: PeriodSeconds specifies the window + of time for which the policy should hold true. + PeriodSeconds must be greater than zero and less + than or equal to 1800 (30 min). + format: int32 + type: integer + type: + description: Type is used to specify the scaling + policy. + type: string + value: + description: Value contains the amount of change + which is permitted by the policy. It must be greater + than zero + format: int32 + type: integer + required: + - periodSeconds + - type + - value + type: object + type: array + x-kubernetes-list-type: atomic + selectPolicy: + description: selectPolicy is used to specify which policy + should be used. If not set, the default value Max is + used. + type: string + stabilizationWindowSeconds: + description: 'StabilizationWindowSeconds is the number + of seconds for which past recommendations should be + considered while scaling up or scaling down. StabilizationWindowSeconds + must be greater than or equal to zero and less than + or equal to 3600 (one hour). If not set, use the default + values: - For scale up: 0 (i.e. no stabilization is + done). - For scale down: 300 (i.e. the stabilization + window is 300 seconds long).' + format: int32 + type: integer + type: object + type: object + type: object config: description: Config is the raw JSON to be used as the collector's configuration. Refer to the OpenTelemetry Collector documentation diff --git a/docs/api.md b/docs/api.md index 6dcb8b56ec..97c0fba762 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1691,6 +1691,13 @@ OpenTelemetryCollectorSpec defines the desired state of OpenTelemetryCollector. Args is the set of arguments to pass to the OpenTelemetry Collector binary
false + + autoscaler + object + + Autoscaler specifies the pod autoscaling configuration to use for the OpenTelemetryCollector workload.
+ + false config string @@ -1866,6 +1873,243 @@ OpenTelemetryCollectorSpec defines the desired state of OpenTelemetryCollector. +### OpenTelemetryCollector.spec.autoscaler +[↩ Parent](#opentelemetrycollectorspec) + + + +Autoscaler specifies the pod autoscaling configuration to use for the OpenTelemetryCollector workload. + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
behaviorobject + HorizontalPodAutoscalerBehavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively).
+
false
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior +[↩ Parent](#opentelemetrycollectorspecautoscaler) + + + +HorizontalPodAutoscalerBehavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively). + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
scaleDownobject + scaleDown is scaling policy for scaling Down. If not set, the default value is to allow to scale down to minReplicas pods, with a 300 second stabilization window (i.e., the highest recommendation for the last 300sec is used).
+
false
scaleUpobject + scaleUp is scaling policy for scaling Up. If not set, the default value is the higher of: * increase no more than 4 pods per 60 seconds * double the number of pods per 60 seconds No stabilization is used.
+
false
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleDown +[↩ Parent](#opentelemetrycollectorspecautoscalerbehavior) + + + +scaleDown is scaling policy for scaling Down. If not set, the default value is to allow to scale down to minReplicas pods, with a 300 second stabilization window (i.e., the highest recommendation for the last 300sec is used). + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
policies[]object + policies is a list of potential scaling polices which can be used during scaling. At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid
+
false
selectPolicystring + selectPolicy is used to specify which policy should be used. If not set, the default value Max is used.
+
false
stabilizationWindowSecondsinteger + StabilizationWindowSeconds is the number of seconds for which past recommendations should be considered while scaling up or scaling down. StabilizationWindowSeconds must be greater than or equal to zero and less than or equal to 3600 (one hour). If not set, use the default values: - For scale up: 0 (i.e. no stabilization is done). - For scale down: 300 (i.e. the stabilization window is 300 seconds long).
+
+ Format: int32
+
false
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleDown.policies[index] +[↩ Parent](#opentelemetrycollectorspecautoscalerbehaviorscaledown) + + + +HPAScalingPolicy is a single policy which must hold true for a specified past interval. + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
periodSecondsinteger + PeriodSeconds specifies the window of time for which the policy should hold true. PeriodSeconds must be greater than zero and less than or equal to 1800 (30 min).
+
+ Format: int32
+
true
typestring + Type is used to specify the scaling policy.
+
true
valueinteger + Value contains the amount of change which is permitted by the policy. It must be greater than zero
+
+ Format: int32
+
true
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleUp +[↩ Parent](#opentelemetrycollectorspecautoscalerbehavior) + + + +scaleUp is scaling policy for scaling Up. If not set, the default value is the higher of: * increase no more than 4 pods per 60 seconds * double the number of pods per 60 seconds No stabilization is used. + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
policies[]object + policies is a list of potential scaling polices which can be used during scaling. At least one policy must be specified, otherwise the HPAScalingRules will be discarded as invalid
+
false
selectPolicystring + selectPolicy is used to specify which policy should be used. If not set, the default value Max is used.
+
false
stabilizationWindowSecondsinteger + StabilizationWindowSeconds is the number of seconds for which past recommendations should be considered while scaling up or scaling down. StabilizationWindowSeconds must be greater than or equal to zero and less than or equal to 3600 (one hour). If not set, use the default values: - For scale up: 0 (i.e. no stabilization is done). - For scale down: 300 (i.e. the stabilization window is 300 seconds long).
+
+ Format: int32
+
false
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleUp.policies[index] +[↩ Parent](#opentelemetrycollectorspecautoscalerbehaviorscaleup) + + + +HPAScalingPolicy is a single policy which must hold true for a specified past interval. + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
periodSecondsinteger + PeriodSeconds specifies the window of time for which the policy should hold true. PeriodSeconds must be greater than zero and less than or equal to 1800 (30 min).
+
+ Format: int32
+
true
typestring + Type is used to specify the scaling policy.
+
true
valueinteger + Value contains the amount of change which is permitted by the policy. It must be greater than zero
+
+ Format: int32
+
true
+ + ### OpenTelemetryCollector.spec.env[index] [↩ Parent](#opentelemetrycollectorspec) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index 0cdd3dca20..25265a3d70 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -73,6 +73,12 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Metrics: metrics, }, } + + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { + behavior := ConvertToV2beta2Behavior(*otelcol.Spec.Autoscaler.Behavior) + autoscaler.Spec.Behavior = &behavior + } + result = &autoscaler } else { targetCPUUtilization := autoscalingv2.MetricSpec{ @@ -100,8 +106,93 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Metrics: metrics, }, } + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { + autoscaler.Spec.Behavior = otelcol.Spec.Autoscaler.Behavior + } result = &autoscaler } return result } + +// Create a v2beta2 HorizontalPodAutoscalerBehavior from a v2 instance. +func ConvertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBehavior) autoscalingv2beta2.HorizontalPodAutoscalerBehavior { + behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{} + + if v2behavior.ScaleUp != nil { + scaleUpRules := &autoscalingv2beta2.HPAScalingRules{} + scaleUpTime := *v2behavior.ScaleUp.StabilizationWindowSeconds + scaleUpRules.StabilizationWindowSeconds = &scaleUpTime + + if v2behavior.ScaleUp.SelectPolicy != nil { + scaleUpSelectPolicy := ConvertToV2Beta2SelectPolicy(*v2behavior.ScaleUp.SelectPolicy) + scaleUpRules.SelectPolicy = &scaleUpSelectPolicy + } + if v2behavior.ScaleUp.Policies != nil { + scaleUpPolicies := []autoscalingv2beta2.HPAScalingPolicy{} + for _, policy := range v2behavior.ScaleUp.Policies { + v2beta2policy := ConvertToV2Beta2HPAScalingPolicy(policy) + scaleUpPolicies = append(scaleUpPolicies, v2beta2policy) + } + scaleUpRules.Policies = scaleUpPolicies + } + + behavior.ScaleUp = scaleUpRules + } + + if v2behavior.ScaleDown != nil { + scaleDownRules := &autoscalingv2beta2.HPAScalingRules{} + scaleDownTime := *v2behavior.ScaleDown.StabilizationWindowSeconds + scaleDownRules.StabilizationWindowSeconds = &scaleDownTime + + if v2behavior.ScaleDown.SelectPolicy != nil { + scaleDownSelectPolicy := ConvertToV2Beta2SelectPolicy(*v2behavior.ScaleDown.SelectPolicy) + scaleDownRules.SelectPolicy = &scaleDownSelectPolicy + } + if v2behavior.ScaleDown.Policies != nil { + ScaleDownPolicies := []autoscalingv2beta2.HPAScalingPolicy{} + for _, policy := range v2behavior.ScaleDown.Policies { + v2beta2policy := ConvertToV2Beta2HPAScalingPolicy(policy) + ScaleDownPolicies = append(ScaleDownPolicies, v2beta2policy) + } + scaleDownRules.Policies = ScaleDownPolicies + } + + behavior.ScaleDown = scaleDownRules + } + + return *behavior +} + +func ConvertToV2Beta2HPAScalingPolicy(v2policy autoscalingv2.HPAScalingPolicy) autoscalingv2beta2.HPAScalingPolicy { + v2beta2Policy := &autoscalingv2beta2.HPAScalingPolicy{ + Value: v2policy.Value, + PeriodSeconds: v2policy.PeriodSeconds, + } + + switch v2policy.Type { + case autoscalingv2.PodsScalingPolicy: + v2beta2Policy.Type = autoscalingv2beta2.PodsScalingPolicy + case autoscalingv2.PercentScalingPolicy: + v2beta2Policy.Type = autoscalingv2beta2.PercentScalingPolicy + } + + return *v2beta2Policy +} + +func ConvertToV2Beta2SelectPolicy(scalingPolicy autoscalingv2.ScalingPolicySelect) autoscalingv2beta2.ScalingPolicySelect { + max := autoscalingv2beta2.MaxPolicySelect + min := autoscalingv2beta2.MinPolicySelect + disabled := autoscalingv2beta2.DisabledPolicySelect + + switch scalingPolicy { + case autoscalingv2.MaxChangePolicySelect: + return max + case autoscalingv2.MinChangePolicySelect: + return min + case autoscalingv2.DisabledPolicySelect: + return disabled + } + + return disabled +} diff --git a/pkg/collector/horizontalpodautoscaler_test.go b/pkg/collector/horizontalpodautoscaler_test.go index 6aaa71ca5c..c8f076248b 100644 --- a/pkg/collector/horizontalpodautoscaler_test.go +++ b/pkg/collector/horizontalpodautoscaler_test.go @@ -91,6 +91,59 @@ func TestHPA(t *testing.T) { } } +func TestConvertToV2beta2Behavior(t *testing.T) { + ten := int32(10) + thirty := int32(30) + max := autoscalingv2.MaxChangePolicySelect + min := autoscalingv2.MinChangePolicySelect + + v2ScaleUp := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &thirty, + SelectPolicy: &max, + } + + v2ScaleDown := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &ten, + SelectPolicy: &min, + } + + v2Behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{ + ScaleUp: v2ScaleUp, + ScaleDown: v2ScaleDown, + } + + v2Beta2Behavior := ConvertToV2beta2Behavior(*v2Behavior) + + assert.Equal(t, thirty, *v2Beta2Behavior.ScaleUp.StabilizationWindowSeconds) + assert.Equal(t, ten, *v2Beta2Behavior.ScaleDown.StabilizationWindowSeconds) + assert.Equal(t, autoscalingv2beta2.MaxPolicySelect, *v2Beta2Behavior.ScaleUp.SelectPolicy) + assert.EqualValues(t, autoscalingv2beta2.MinPolicySelect, *v2Beta2Behavior.ScaleDown.SelectPolicy) +} + +func TestConvertToV2Beta2HPAScalingPolicy(t *testing.T) { + v2Policy := autoscalingv2.HPAScalingPolicy{ + Type: autoscalingv2.PodsScalingPolicy, + Value: 5, + PeriodSeconds: 10, + } + + v2Beta2Policy := ConvertToV2Beta2HPAScalingPolicy(v2Policy) + assert.Equal(t, autoscalingv2beta2.PodsScalingPolicy, v2Beta2Policy.Type) + assert.Equal(t, int32(5), v2Beta2Policy.Value) + assert.Equal(t, int32(10), v2Beta2Policy.PeriodSeconds) + +} + +func TestConvertToV2Beta2SelectPolicy(t *testing.T) { + min := autoscalingv2.MinChangePolicySelect + max := autoscalingv2.MaxChangePolicySelect + disabled := autoscalingv2.DisabledPolicySelect + + assert.Equal(t, autoscalingv2beta2.MinPolicySelect, ConvertToV2Beta2SelectPolicy(min)) + assert.Equal(t, autoscalingv2beta2.MaxPolicySelect, ConvertToV2Beta2SelectPolicy(max)) + assert.Equal(t, autoscalingv2beta2.DisabledPolicySelect, ConvertToV2Beta2SelectPolicy(disabled)) +} + var _ autodetect.AutoDetect = (*mockAutoDetect)(nil) type mockAutoDetect struct { diff --git a/tests/e2e/autoscale/00-assert.yaml b/tests/e2e/autoscale/00-assert.yaml index ef4b828699..aaacc816cd 100644 --- a/tests/e2e/autoscale/00-assert.yaml +++ b/tests/e2e/autoscale/00-assert.yaml @@ -13,4 +13,7 @@ metadata: spec: minReplicas: 1 maxReplicas: 2 +# This is not neccesarily exact. We really just want to wait until this is no longer +status: + currentCPUUtilizationPercentage: 20 diff --git a/tests/e2e/autoscale/00-install.yaml b/tests/e2e/autoscale/00-install.yaml index e2ba8d5a54..8645bb919a 100644 --- a/tests/e2e/autoscale/00-install.yaml +++ b/tests/e2e/autoscale/00-install.yaml @@ -5,6 +5,12 @@ metadata: spec: minReplicas: 1 maxReplicas: 2 + autoscaler: + behavior: + scaleUp: + stabilizationWindowSeconds: 10 + scaleDown: + stabilizationWindowSeconds: 15 resources: limits: cpu: 500m diff --git a/tests/e2e/autoscale/02-assert.yaml b/tests/e2e/autoscale/02-assert.yaml new file mode 100644 index 0000000000..fb4e052f2b --- /dev/null +++ b/tests/e2e/autoscale/02-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: opentelemetry.io/v1alpha1 +kind: OpenTelemetryCollector + +metadata: + name: simplest +status: + scale: + replicas: 1