From f4abf289686259db26bdd57846cc7e038d78e42a Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 11:37:06 +0200 Subject: [PATCH 01/14] Add scaledown test for autoscaling Signed-off-by: Kevin Earls --- apis/v1alpha1/opentelemetrycollector_types.go | 21 +++++++++ .../opentelemetrycollector_webhook.go | 9 ++++ apis/v1alpha1/zz_generated.deepcopy.go | 30 ++++++++++++ ...ntelemetry.io_opentelemetrycollectors.yaml | 17 +++++++ ...ntelemetry.io_opentelemetrycollectors.yaml | 19 +++++++- config/manager/kustomization.yaml | 8 +++- docs/api.md | 47 +++++++++++++++++++ pkg/collector/horizontalpodautoscaler.go | 39 +++++++++++++++ tests/e2e/autoscale/00-install.yaml | 3 ++ 9 files changed, 191 insertions(+), 2 deletions(-) diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index 747736361f..f27e182caa 100644 --- a/apis/v1alpha1/opentelemetrycollector_types.go +++ b/apis/v1alpha1/opentelemetrycollector_types.go @@ -104,6 +104,12 @@ type OpenTelemetryCollectorSpec struct { // HostNetwork indicates if the pod should run in the host networking namespace. // +optional HostNetwork bool `json:"hostNetwork,omitempty"` + + // Autoscaler specifies the pod autoscaling configuration to use + // for the OpenTelemetryCollector workload. + // + // +optional + Autoscaler *AutoscalerSpec `json:"autoscaler,omitempty"` } // OpenTelemetryTargetAllocator defines the configurations for the Prometheus target allocator. @@ -195,6 +201,21 @@ type OpenTelemetryCollectorList struct { Items []OpenTelemetryCollector `json:"items"` } +// AutoscalerSpec defines the OpenTelemetryCollector's pod autoscaling specification. +type AutoscalerSpec struct { + // ScaleUp is the minimum number of seconds to wait before scaling up + // + // +optional + // +kubebuilder:validation:Minimum=0 + ScaleUp *int32 `json:"scaleUp,omitempty"` + + // ScaleDown is the minimum number of seconds to wait before scaling down + // + // +optional + // +kubebuilder:validation:Minimum=0 + ScaleDown *int32 `json:"scaleDown,omitempty"` +} + func init() { SchemeBuilder.Register(&OpenTelemetryCollector{}, &OpenTelemetryCollectorList{}) } diff --git a/apis/v1alpha1/opentelemetrycollector_webhook.go b/apis/v1alpha1/opentelemetrycollector_webhook.go index 6a4b1e936f..1741dd19d5 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 { + if *r.Spec.Autoscaler.ScaleDown < int32(1) { + return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleDown should be one or more") + } + + if *r.Spec.Autoscaler.ScaleUp < 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 cba3b24b99..f05dacb05f 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -24,6 +24,31 @@ import ( "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.ScaleUp != nil { + in, out := &in.ScaleUp, &out.ScaleUp + *out = new(int32) + **out = **in + } + if in.ScaleDown != nil { + in, out := &in.ScaleDown, &out.ScaleDown + *out = new(int32) + **out = **in + } +} + +// 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 @@ -372,6 +397,11 @@ func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSp (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Autoscaler != nil { + in, out := &in.Autoscaler, &out.Autoscaler + *out = new(AutoscalerSpec) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryCollectorSpec. diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index da91c7ce09..9801ebabff 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -59,6 +59,23 @@ 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: + scaleDown: + description: ScaleDown is the minimum number of seconds to wait + before scaling down + format: int32 + minimum: 0 + type: integer + scaleUp: + description: ScaleUp is the minimum number of seconds to wait + before scaling up + format: int32 + minimum: 0 + type: integer + 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 e5a0084416..e0be9f45c2 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.9.2 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: opentelemetrycollectors.opentelemetry.io spec: @@ -57,6 +57,23 @@ 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: + scaleDown: + description: ScaleDown is the minimum number of seconds to wait + before scaling down + format: int32 + minimum: 0 + type: integer + scaleUp: + description: ScaleUp is the minimum number of seconds to wait + before scaling up + format: int32 + minimum: 0 + type: integer + 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/manager/kustomization.yaml b/config/manager/kustomization.yaml index 2e6cc79764..87e56154c9 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,2 +1,8 @@ resources: -- manager.yaml \ No newline at end of file +- manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: ghcr.io/kearls/opentelemetry-operator/opentelemetry-operator + newTag: 0.59.0-3-gb708157 diff --git a/docs/api.md b/docs/api.md index 57b8d78a9a..23d2c35007 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,46 @@ 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
scaleDowninteger + ScaleDown is the minimum number of seconds to wait before scaling down
+
+ Format: int32
+ Minimum: 0
+
false
scaleUpinteger + ScaleUp is the minimum number of seconds to wait before scaling up
+
+ Format: int32
+ Minimum: 0
+
false
+ + ### OpenTelemetryCollector.spec.env[index] [↩ Parent](#opentelemetrycollectorspec) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index 0cdd3dca20..cc3ead6f4a 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -29,6 +29,8 @@ import ( ) const defaultCPUTarget int32 = 90 +const defaultScaleUpTime int32 = 60 +const defaultScaleDownTime int32 = 300 func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector) client.Object { autoscalingVersion := cfg.AutoscalingVersion() @@ -47,6 +49,15 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Annotations: annotations, } + scaleUpTime := defaultScaleUpTime + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { + scaleUpTime = *otelcol.Spec.Autoscaler.ScaleUp + } + scaleDownTime := defaultScaleDownTime + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { + scaleDownTime = *otelcol.Spec.Autoscaler.ScaleDown + } + if autoscalingVersion == autodetect.AutoscalingVersionV2Beta2 { targetCPUUtilization := autoscalingv2beta2.MetricSpec{ Type: autoscalingv2beta2.ResourceMetricSourceType, @@ -73,6 +84,20 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Metrics: metrics, }, } + + if otelcol.Spec.Autoscaler != nil { + scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, + } + scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, + } + behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{ + ScaleUp: scaleUpRules, + ScaleDown: scaleDownRules, + } + autoscaler.Spec.Behavior = behavior + } result = &autoscaler } else { targetCPUUtilization := autoscalingv2.MetricSpec{ @@ -100,6 +125,20 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Metrics: metrics, }, } + + if otelcol.Spec.Autoscaler != nil { + scaleUpRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, + } + scaleDownRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, + } + behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{ + ScaleUp: scaleUpRules, + ScaleDown: scaleDownRules, + } + autoscaler.Spec.Behavior = behavior + } result = &autoscaler } diff --git a/tests/e2e/autoscale/00-install.yaml b/tests/e2e/autoscale/00-install.yaml index e2ba8d5a54..eb43ae1cd0 100644 --- a/tests/e2e/autoscale/00-install.yaml +++ b/tests/e2e/autoscale/00-install.yaml @@ -5,6 +5,9 @@ metadata: spec: minReplicas: 1 maxReplicas: 2 + autoscaler: + scaleUp: 30 + scaleDown: 15 resources: limits: cpu: 500m From 7b51feead1359adc0f532a91344d7a51d7511314 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 11:40:19 +0200 Subject: [PATCH 02/14] Fix nits Signed-off-by: Kevin Earls --- .../bases/opentelemetry.io_opentelemetrycollectors.yaml | 2 +- config/manager/kustomization.yaml | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index e0be9f45c2..ab57131ff7 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.2 creationTimestamp: null name: opentelemetrycollectors.opentelemetry.io spec: diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 87e56154c9..2e6cc79764 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -1,8 +1,2 @@ resources: -- manager.yaml -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -images: -- name: controller - newName: ghcr.io/kearls/opentelemetry-operator/opentelemetry-operator - newTag: 0.59.0-3-gb708157 +- manager.yaml \ No newline at end of file From 43710b9ddc927a2f91114772679e6f2a7b9bf2d4 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 11:53:35 +0200 Subject: [PATCH 03/14] Appease the linter Signed-off-by: Kevin Earls --- apis/v1alpha1/opentelemetrycollector_types.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index f27e182caa..32231b6411 100644 --- a/apis/v1alpha1/opentelemetrycollector_types.go +++ b/apis/v1alpha1/opentelemetrycollector_types.go @@ -40,6 +40,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"` @@ -104,12 +111,6 @@ type OpenTelemetryCollectorSpec struct { // HostNetwork indicates if the pod should run in the host networking namespace. // +optional HostNetwork bool `json:"hostNetwork,omitempty"` - - // Autoscaler specifies the pod autoscaling configuration to use - // for the OpenTelemetryCollector workload. - // - // +optional - Autoscaler *AutoscalerSpec `json:"autoscaler,omitempty"` } // OpenTelemetryTargetAllocator defines the configurations for the Prometheus target allocator. From 7070f4b64881624ba0ac9ebefe9425f04fed6b95 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 14:47:20 +0200 Subject: [PATCH 04/14] Don't use a default, only set scaleUp/scaleDown if they are in the CR Signed-off-by: Kevin Earls --- pkg/collector/horizontalpodautoscaler.go | 48 ++++++++++++++---------- tests/e2e/autoscale/00-install.yaml | 1 - 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index cc3ead6f4a..0783b80132 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -29,8 +29,9 @@ import ( ) const defaultCPUTarget int32 = 90 -const defaultScaleUpTime int32 = 60 -const defaultScaleDownTime int32 = 300 + +//const defaultScaleUpTime int32 = 60 +//const defaultScaleDownTime int32 = 300 func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector) client.Object { autoscalingVersion := cfg.AutoscalingVersion() @@ -49,11 +50,12 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Annotations: annotations, } - scaleUpTime := defaultScaleUpTime + //scaleUpTime := defaultScaleUpTime + var scaleUpTime int32 if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { scaleUpTime = *otelcol.Spec.Autoscaler.ScaleUp } - scaleDownTime := defaultScaleDownTime + var scaleDownTime int32 if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { scaleDownTime = *otelcol.Spec.Autoscaler.ScaleDown } @@ -86,15 +88,18 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } if otelcol.Spec.Autoscaler != nil { - scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, + behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{} + if scaleUpTime != 0 { + scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, + } + behavior.ScaleUp = scaleUpRules } - behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{ - ScaleUp: scaleUpRules, - ScaleDown: scaleDownRules, + if scaleDownTime != 0 { + scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, + } + behavior.ScaleDown = scaleDownRules } autoscaler.Spec.Behavior = behavior } @@ -127,15 +132,18 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } if otelcol.Spec.Autoscaler != nil { - scaleUpRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - scaleDownRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, + behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{} + if scaleUpTime != 0 { + scaleUpRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, + } + behavior.ScaleUp = scaleUpRules } - behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{ - ScaleUp: scaleUpRules, - ScaleDown: scaleDownRules, + if scaleDownTime != 0 { + scaleDownRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, + } + behavior.ScaleDown = scaleDownRules } autoscaler.Spec.Behavior = behavior } diff --git a/tests/e2e/autoscale/00-install.yaml b/tests/e2e/autoscale/00-install.yaml index eb43ae1cd0..f7ae6fd80e 100644 --- a/tests/e2e/autoscale/00-install.yaml +++ b/tests/e2e/autoscale/00-install.yaml @@ -6,7 +6,6 @@ spec: minReplicas: 1 maxReplicas: 2 autoscaler: - scaleUp: 30 scaleDown: 15 resources: limits: From ae832640bea3761a7ecf2398e4ae5c528cc166fc Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 15:35:38 +0200 Subject: [PATCH 05/14] Removed commented out code Signed-off-by: Kevin Earls --- pkg/collector/horizontalpodautoscaler.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index 0783b80132..4fe55bc033 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -30,9 +30,6 @@ import ( const defaultCPUTarget int32 = 90 -//const defaultScaleUpTime int32 = 60 -//const defaultScaleDownTime int32 = 300 - func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector) client.Object { autoscalingVersion := cfg.AutoscalingVersion() @@ -50,7 +47,6 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Annotations: annotations, } - //scaleUpTime := defaultScaleUpTime var scaleUpTime int32 if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { scaleUpTime = *otelcol.Spec.Autoscaler.ScaleUp From 19154beb032ab26e6266a2cc5240cc71273a3156 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Tue, 6 Sep 2022 17:20:18 +0200 Subject: [PATCH 06/14] Change defaults for scaleUp/scaleDown Signed-off-by: Kevin Earls --- .../opentelemetrycollector_webhook.go | 4 +- pkg/collector/horizontalpodautoscaler.go | 44 +++++++++---------- tests/e2e/autoscale/00-install.yaml | 1 + 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/apis/v1alpha1/opentelemetrycollector_webhook.go b/apis/v1alpha1/opentelemetrycollector_webhook.go index 1741dd19d5..5a39d6aca4 100644 --- a/apis/v1alpha1/opentelemetrycollector_webhook.go +++ b/apis/v1alpha1/opentelemetrycollector_webhook.go @@ -130,11 +130,11 @@ func (r *OpenTelemetryCollector) validateCRDSpec() error { } if r.Spec.Autoscaler != nil { - if *r.Spec.Autoscaler.ScaleDown < int32(1) { + if r.Spec.Autoscaler.ScaleDown != nil && *r.Spec.Autoscaler.ScaleDown < int32(1) { return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleDown should be one or more") } - if *r.Spec.Autoscaler.ScaleUp < int32(1) { + if r.Spec.Autoscaler.ScaleUp != nil && *r.Spec.Autoscaler.ScaleUp < int32(1) { return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, scaleUp should be one or more") } } diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index 4fe55bc033..cc3ead6f4a 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -29,6 +29,8 @@ import ( ) const defaultCPUTarget int32 = 90 +const defaultScaleUpTime int32 = 60 +const defaultScaleDownTime int32 = 300 func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector) client.Object { autoscalingVersion := cfg.AutoscalingVersion() @@ -47,11 +49,11 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Annotations: annotations, } - var scaleUpTime int32 + scaleUpTime := defaultScaleUpTime if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { scaleUpTime = *otelcol.Spec.Autoscaler.ScaleUp } - var scaleDownTime int32 + scaleDownTime := defaultScaleDownTime if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { scaleDownTime = *otelcol.Spec.Autoscaler.ScaleDown } @@ -84,18 +86,15 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } if otelcol.Spec.Autoscaler != nil { - behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{} - if scaleUpTime != 0 { - scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - behavior.ScaleUp = scaleUpRules + scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, } - if scaleDownTime != 0 { - scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, - } - behavior.ScaleDown = scaleDownRules + scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, + } + behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{ + ScaleUp: scaleUpRules, + ScaleDown: scaleDownRules, } autoscaler.Spec.Behavior = behavior } @@ -128,18 +127,15 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } if otelcol.Spec.Autoscaler != nil { - behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{} - if scaleUpTime != 0 { - scaleUpRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - behavior.ScaleUp = scaleUpRules + scaleUpRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleUpTime, + } + scaleDownRules := &autoscalingv2.HPAScalingRules{ + StabilizationWindowSeconds: &scaleDownTime, } - if scaleDownTime != 0 { - scaleDownRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, - } - behavior.ScaleDown = scaleDownRules + behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{ + ScaleUp: scaleUpRules, + ScaleDown: scaleDownRules, } autoscaler.Spec.Behavior = behavior } diff --git a/tests/e2e/autoscale/00-install.yaml b/tests/e2e/autoscale/00-install.yaml index f7ae6fd80e..aaee6bc61b 100644 --- a/tests/e2e/autoscale/00-install.yaml +++ b/tests/e2e/autoscale/00-install.yaml @@ -6,6 +6,7 @@ spec: minReplicas: 1 maxReplicas: 2 autoscaler: + scaleUp: 10 scaleDown: 15 resources: limits: From 108d0f1c15166c0e4b176bbff4df9e1a6601cce9 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 8 Sep 2022 18:19:56 +0200 Subject: [PATCH 07/14] Update autoscaling scaleup/scaledown Signed-off-by: Kevin Earls --- apis/v1alpha1/opentelemetrycollector_types.go | 22 +++-- .../opentelemetrycollector_webhook.go | 6 +- apis/v1alpha1/zz_generated.deepcopy.go | 60 ++++++++++-- ...ntelemetry.io_opentelemetrycollectors.yaml | 33 ++++--- ...ntelemetry.io_opentelemetrycollectors.yaml | 33 ++++--- docs/api.md | 91 ++++++++++++++++++- pkg/collector/horizontalpodautoscaler.go | 17 ++-- tests/e2e/autoscale/00-assert.yaml | 3 + tests/e2e/autoscale/00-install.yaml | 7 +- 9 files changed, 215 insertions(+), 57 deletions(-) diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index 32231b6411..1119e8a3cb 100644 --- a/apis/v1alpha1/opentelemetrycollector_types.go +++ b/apis/v1alpha1/opentelemetrycollector_types.go @@ -204,17 +204,27 @@ type OpenTelemetryCollectorList struct { // AutoscalerSpec defines the OpenTelemetryCollector's pod autoscaling specification. type AutoscalerSpec struct { - // ScaleUp is the minimum number of seconds to wait before scaling up - // // +optional - // +kubebuilder:validation:Minimum=0 - ScaleUp *int32 `json:"scaleUp,omitempty"` + Behavior *AutoscalerBehaviorSpec `json:"behavior,omitempty"` +} + +// AutoscalerBehaviorSpec configures the scaling behavior of the target. +type AutoscalerBehaviorSpec struct { + // ScaleUp is the policy for scaling up + // +optional + ScaleUp *AutoScalerRules `json:"scaleUp,omitempty"` - // ScaleDown is the minimum number of seconds to wait before scaling down + // ScaleDown is policy for scaling down // + // +optional + ScaleDown *AutoScalerRules `json:"scaleDown,omitempty"` +} + +// AutoScalerRules configures the scaling behavior for one direction. +type AutoScalerRules struct { // +optional // +kubebuilder:validation:Minimum=0 - ScaleDown *int32 `json:"scaleDown,omitempty"` + StabilizationWindowSeconds *int32 `json:"stabilizationWindowSeconds,omitempty"` } func init() { diff --git a/apis/v1alpha1/opentelemetrycollector_webhook.go b/apis/v1alpha1/opentelemetrycollector_webhook.go index 5a39d6aca4..b8df65c956 100644 --- a/apis/v1alpha1/opentelemetrycollector_webhook.go +++ b/apis/v1alpha1/opentelemetrycollector_webhook.go @@ -129,12 +129,12 @@ 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 { - if r.Spec.Autoscaler.ScaleDown != nil && *r.Spec.Autoscaler.ScaleDown < int32(1) { + 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.ScaleUp != nil && *r.Spec.Autoscaler.ScaleUp < int32(1) { + 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") } } diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index f05dacb05f..212a7093ab 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -25,17 +25,57 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AutoscalerSpec) DeepCopyInto(out *AutoscalerSpec) { +func (in *AutoScalerRules) DeepCopyInto(out *AutoScalerRules) { *out = *in - if in.ScaleUp != nil { - in, out := &in.ScaleUp, &out.ScaleUp + if in.StabilizationWindowSeconds != nil { + in, out := &in.StabilizationWindowSeconds, &out.StabilizationWindowSeconds *out = new(int32) **out = **in } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoScalerRules. +func (in *AutoScalerRules) DeepCopy() *AutoScalerRules { + if in == nil { + return nil + } + out := new(AutoScalerRules) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoscalerBehaviorSpec) DeepCopyInto(out *AutoscalerBehaviorSpec) { + *out = *in + if in.ScaleUp != nil { + in, out := &in.ScaleUp, &out.ScaleUp + *out = new(AutoScalerRules) + (*in).DeepCopyInto(*out) + } if in.ScaleDown != nil { in, out := &in.ScaleDown, &out.ScaleDown - *out = new(int32) - **out = **in + *out = new(AutoScalerRules) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerBehaviorSpec. +func (in *AutoscalerBehaviorSpec) DeepCopy() *AutoscalerBehaviorSpec { + if in == nil { + return nil + } + out := new(AutoscalerBehaviorSpec) + in.DeepCopyInto(out) + return out +} + +// 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(AutoscalerBehaviorSpec) + (*in).DeepCopyInto(*out) } } @@ -330,6 +370,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) @@ -397,11 +442,6 @@ func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSp (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Autoscaler != nil { - in, out := &in.Autoscaler, &out.Autoscaler - *out = new(AutoscalerSpec) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenTelemetryCollectorSpec. diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index 9801ebabff..3299d356d5 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -63,18 +63,27 @@ spec: description: Autoscaler specifies the pod autoscaling configuration to use for the OpenTelemetryCollector workload. properties: - scaleDown: - description: ScaleDown is the minimum number of seconds to wait - before scaling down - format: int32 - minimum: 0 - type: integer - scaleUp: - description: ScaleUp is the minimum number of seconds to wait - before scaling up - format: int32 - minimum: 0 - type: integer + behavior: + description: AutoscalerBehaviorSpec configures the scaling behavior + of the target + properties: + scaleDown: + description: ScaleDown is policy for scaling down + properties: + stabilizationWindowSeconds: + format: int32 + minimum: 0 + type: integer + type: object + scaleUp: + description: ScaleUp is the policy for scaling up + properties: + stabilizationWindowSeconds: + format: int32 + minimum: 0 + type: integer + type: object + type: object type: object config: description: Config is the raw JSON to be used as the collector's diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index ab57131ff7..880570a417 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -61,18 +61,27 @@ spec: description: Autoscaler specifies the pod autoscaling configuration to use for the OpenTelemetryCollector workload. properties: - scaleDown: - description: ScaleDown is the minimum number of seconds to wait - before scaling down - format: int32 - minimum: 0 - type: integer - scaleUp: - description: ScaleUp is the minimum number of seconds to wait - before scaling up - format: int32 - minimum: 0 - type: integer + behavior: + description: AutoscalerBehaviorSpec configures the scaling behavior + of the target + properties: + scaleDown: + description: ScaleDown is policy for scaling down + properties: + stabilizationWindowSeconds: + format: int32 + minimum: 0 + type: integer + type: object + scaleUp: + description: ScaleUp is the policy for scaling up + properties: + stabilizationWindowSeconds: + format: int32 + minimum: 0 + type: integer + type: object + type: object type: object config: description: Config is the raw JSON to be used as the collector's diff --git a/docs/api.md b/docs/api.md index 23d2c35007..09f42d359a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1890,20 +1890,101 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme - scaleDown + behavior + object + + AutoscalerBehaviorSpec configures the scaling behavior of the target
+ + false + + + + +### OpenTelemetryCollector.spec.autoscaler.behavior +[↩ Parent](#opentelemetrycollectorspecautoscaler) + + + +AutoscalerBehaviorSpec configures the scaling behavior of the target + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
scaleDownobject + ScaleDown is policy for scaling down
+
false
scaleUpobject + ScaleUp is the policy for scaling up
+
false
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleDown +[↩ Parent](#opentelemetrycollectorspecautoscalerbehavior) + + + +ScaleDown is policy for scaling down + + + + + + + + + + + + - - + +
NameTypeDescriptionRequired
stabilizationWindowSeconds integer - ScaleDown is the minimum number of seconds to wait before scaling down
+

Format: int32
Minimum: 0
false
scaleUp
+ + +### OpenTelemetryCollector.spec.autoscaler.behavior.scaleUp +[↩ Parent](#opentelemetrycollectorspecautoscalerbehavior) + + + +ScaleUp is the policy for scaling up + + + + + + + + + + + + @@ -1905,7 +1905,7 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme -AutoscalerBehaviorSpec configures the scaling behavior of the target +AutoscalerBehaviorSpec configures the scaling behavior of the target.
NameTypeDescriptionRequired
stabilizationWindowSeconds integer - ScaleUp is the minimum number of seconds to wait before scaling up
+

Format: int32
Minimum: 0
diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index cc3ead6f4a..1d56304b51 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -50,12 +50,15 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } scaleUpTime := defaultScaleUpTime - if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { - scaleUpTime = *otelcol.Spec.Autoscaler.ScaleUp - } scaleDownTime := defaultScaleDownTime - if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.ScaleDown != nil { - scaleDownTime = *otelcol.Spec.Autoscaler.ScaleDown + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { + if otelcol.Spec.Autoscaler.Behavior.ScaleUp != nil { + scaleUpTime = *otelcol.Spec.Autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds + } + + if otelcol.Spec.Autoscaler.Behavior.ScaleDown != nil { + scaleDownTime = *otelcol.Spec.Autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds + } } if autoscalingVersion == autodetect.AutoscalingVersionV2Beta2 { @@ -85,7 +88,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al }, } - if otelcol.Spec.Autoscaler != nil { + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ StabilizationWindowSeconds: &scaleUpTime, } @@ -126,7 +129,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al }, } - if otelcol.Spec.Autoscaler != nil { + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { scaleUpRules := &autoscalingv2.HPAScalingRules{ StabilizationWindowSeconds: &scaleUpTime, } 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 aaee6bc61b..8645bb919a 100644 --- a/tests/e2e/autoscale/00-install.yaml +++ b/tests/e2e/autoscale/00-install.yaml @@ -6,8 +6,11 @@ spec: minReplicas: 1 maxReplicas: 2 autoscaler: - scaleUp: 10 - scaleDown: 15 + behavior: + scaleUp: + stabilizationWindowSeconds: 10 + scaleDown: + stabilizationWindowSeconds: 15 resources: limits: cpu: 500m From 037aa23ba8c2702dcec667d655f6487fd74bf858 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 8 Sep 2022 18:49:19 +0200 Subject: [PATCH 08/14] Run generate Signed-off-by: Kevin Earls --- bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml | 2 +- config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index 3299d356d5..d13265b893 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -65,7 +65,7 @@ spec: properties: behavior: description: AutoscalerBehaviorSpec configures the scaling behavior - of the target + of the target. properties: scaleDown: description: ScaleDown is policy for scaling down diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index 880570a417..e7b0f5cabd 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -63,7 +63,7 @@ spec: properties: behavior: description: AutoscalerBehaviorSpec configures the scaling behavior - of the target + of the target. properties: scaleDown: description: ScaleDown is policy for scaling down From bdc6eb3b2760e3cee8cf8aaebcabf21ec616f4d4 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 8 Sep 2022 19:06:01 +0200 Subject: [PATCH 09/14] Ran make api-docs Signed-off-by: Kevin Earls --- docs/api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api.md b/docs/api.md index 09f42d359a..3378309e63 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1893,7 +1893,7 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme
behavior object - AutoscalerBehaviorSpec configures the scaling behavior of the target
+ AutoscalerBehaviorSpec configures the scaling behavior of the target.
false
From 60cdfe700607600a24acc472720bccb5dfed54d6 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 09:59:09 +0200 Subject: [PATCH 10/14] Update HPA implementation to embed HorizontalPodAutoscalerBehavior Signed-off-by: Kevin Earls --- apis/v1alpha1/opentelemetrycollector_types.go | 22 +-- apis/v1alpha1/zz_generated.deepcopy.go | 48 +------ ...ntelemetry.io_opentelemetrycollectors.yaml | 110 +++++++++++++- ...ntelemetry.io_opentelemetrycollectors.yaml | 110 +++++++++++++- docs/api.md | 136 ++++++++++++++++-- pkg/collector/horizontalpodautoscaler.go | 122 +++++++++++----- 6 files changed, 421 insertions(+), 127 deletions(-) diff --git a/apis/v1alpha1/opentelemetrycollector_types.go b/apis/v1alpha1/opentelemetrycollector_types.go index 1119e8a3cb..0c6b095457 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" ) @@ -205,26 +206,7 @@ type OpenTelemetryCollectorList struct { // AutoscalerSpec defines the OpenTelemetryCollector's pod autoscaling specification. type AutoscalerSpec struct { // +optional - Behavior *AutoscalerBehaviorSpec `json:"behavior,omitempty"` -} - -// AutoscalerBehaviorSpec configures the scaling behavior of the target. -type AutoscalerBehaviorSpec struct { - // ScaleUp is the policy for scaling up - // +optional - ScaleUp *AutoScalerRules `json:"scaleUp,omitempty"` - - // ScaleDown is policy for scaling down - // - // +optional - ScaleDown *AutoScalerRules `json:"scaleDown,omitempty"` -} - -// AutoScalerRules configures the scaling behavior for one direction. -type AutoScalerRules struct { - // +optional - // +kubebuilder:validation:Minimum=0 - StabilizationWindowSeconds *int32 `json:"stabilizationWindowSeconds,omitempty"` + Behavior *autoscalingv2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"` } func init() { diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 212a7093ab..0f81becc74 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -20,61 +20,17 @@ package v1alpha1 import ( + "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 *AutoScalerRules) DeepCopyInto(out *AutoScalerRules) { - *out = *in - if in.StabilizationWindowSeconds != nil { - in, out := &in.StabilizationWindowSeconds, &out.StabilizationWindowSeconds - *out = new(int32) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoScalerRules. -func (in *AutoScalerRules) DeepCopy() *AutoScalerRules { - if in == nil { - return nil - } - out := new(AutoScalerRules) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AutoscalerBehaviorSpec) DeepCopyInto(out *AutoscalerBehaviorSpec) { - *out = *in - if in.ScaleUp != nil { - in, out := &in.ScaleUp, &out.ScaleUp - *out = new(AutoScalerRules) - (*in).DeepCopyInto(*out) - } - if in.ScaleDown != nil { - in, out := &in.ScaleDown, &out.ScaleDown - *out = new(AutoScalerRules) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerBehaviorSpec. -func (in *AutoscalerBehaviorSpec) DeepCopy() *AutoscalerBehaviorSpec { - if in == nil { - return nil - } - out := new(AutoscalerBehaviorSpec) - in.DeepCopyInto(out) - return out -} - // 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(AutoscalerBehaviorSpec) + *out = new(v2.HorizontalPodAutoscalerBehavior) (*in).DeepCopyInto(*out) } } diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index d13265b893..e244cac357 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -64,23 +64,121 @@ spec: to use for the OpenTelemetryCollector workload. properties: behavior: - description: AutoscalerBehaviorSpec configures the scaling behavior - of the target. + 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 policy for scaling down + 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 - minimum: 0 type: integer type: object scaleUp: - description: ScaleUp is the policy for scaling up + 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 - minimum: 0 type: integer type: object type: object diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index e7b0f5cabd..77e15acee9 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -62,23 +62,121 @@ spec: to use for the OpenTelemetryCollector workload. properties: behavior: - description: AutoscalerBehaviorSpec configures the scaling behavior - of the target. + 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 policy for scaling down + 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 - minimum: 0 type: integer type: object scaleUp: - description: ScaleUp is the policy for scaling up + 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 - minimum: 0 type: integer type: object type: object diff --git a/docs/api.md b/docs/api.md index 3378309e63..3c07ad7654 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1893,7 +1893,7 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme @@ -1905,7 +1905,7 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme -AutoscalerBehaviorSpec configures the scaling behavior of the target. +HorizontalPodAutoscalerBehavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively).
behavior object - AutoscalerBehaviorSpec configures the scaling behavior of the target.
+ HorizontalPodAutoscalerBehavior configures the scaling behavior of the target in both Up and Down directions (scaleUp and scaleDown fields respectively).
false
@@ -1920,14 +1920,14 @@ AutoscalerBehaviorSpec configures the scaling behavior of the target. @@ -1939,7 +1939,7 @@ AutoscalerBehaviorSpec configures the scaling behavior of the target. -ScaleDown is policy for scaling down +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).
scaleDown object - ScaleDown is policy for scaling down
+ 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
scaleUp object - ScaleUp is the policy for scaling up
+ 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
@@ -1951,25 +1951,83 @@ ScaleDown is policy for scaling down + + + + + + + + + +
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
stabilizationWindowSeconds integer -
+ 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
- Minimum: 0
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 the policy for scaling up +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. @@ -1981,19 +2039,77 @@ ScaleUp is the policy for scaling up + + + + + + + + + +
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
stabilizationWindowSeconds integer -
+ 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
- Minimum: 0
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 1d56304b51..9b8cd4bbec 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -29,8 +29,6 @@ import ( ) const defaultCPUTarget int32 = 90 -const defaultScaleUpTime int32 = 60 -const defaultScaleDownTime int32 = 300 func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelemetryCollector) client.Object { autoscalingVersion := cfg.AutoscalingVersion() @@ -49,18 +47,6 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al Annotations: annotations, } - scaleUpTime := defaultScaleUpTime - scaleDownTime := defaultScaleDownTime - if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { - if otelcol.Spec.Autoscaler.Behavior.ScaleUp != nil { - scaleUpTime = *otelcol.Spec.Autoscaler.Behavior.ScaleUp.StabilizationWindowSeconds - } - - if otelcol.Spec.Autoscaler.Behavior.ScaleDown != nil { - scaleDownTime = *otelcol.Spec.Autoscaler.Behavior.ScaleDown.StabilizationWindowSeconds - } - } - if autoscalingVersion == autodetect.AutoscalingVersionV2Beta2 { targetCPUUtilization := autoscalingv2beta2.MetricSpec{ Type: autoscalingv2beta2.ResourceMetricSourceType, @@ -73,6 +59,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al }, } metrics := []autoscalingv2beta2.MetricSpec{targetCPUUtilization} + behavior := convertToV2beta2Behavior(*otelcol.Spec.Autoscaler.Behavior) autoscaler := autoscalingv2beta2.HorizontalPodAutoscaler{ ObjectMeta: objectMeta, @@ -85,22 +72,10 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al MinReplicas: otelcol.Spec.Replicas, MaxReplicas: *otelcol.Spec.MaxReplicas, Metrics: metrics, + Behavior: &behavior, }, } - if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { - scaleUpRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - scaleDownRules := &autoscalingv2beta2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, - } - behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{ - ScaleUp: scaleUpRules, - ScaleDown: scaleDownRules, - } - autoscaler.Spec.Behavior = behavior - } result = &autoscaler } else { targetCPUUtilization := autoscalingv2.MetricSpec{ @@ -126,24 +101,93 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al MinReplicas: otelcol.Spec.Replicas, MaxReplicas: *otelcol.Spec.MaxReplicas, Metrics: metrics, + Behavior: otelcol.Spec.Autoscaler.Behavior, }, } + result = &autoscaler + } - if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { - scaleUpRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleUpTime, - } - scaleDownRules := &autoscalingv2.HPAScalingRules{ - StabilizationWindowSeconds: &scaleDownTime, + 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) + scaleUpRules.SelectPolicy = &scaleUpSelectPolicy + } + if v2behavior.ScaleUp.Policies != nil { + scaleUpPolicies := []autoscalingv2beta2.HPAScalingPolicy{} + for _, policy := range v2behavior.ScaleUp.Policies { + v2beta2policy := convertToV2Beta2HPAScalingPolicy(policy) + scaleUpPolicies = append(scaleUpPolicies, v2beta2policy) } - behavior := &autoscalingv2.HorizontalPodAutoscalerBehavior{ - ScaleUp: scaleUpRules, - ScaleDown: scaleDownRules, + 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) + scaleDownRules.SelectPolicy = &scaleDownSelectPolicy + } + if v2behavior.ScaleDown.Policies != nil { + ScaleDownPolicies := []autoscalingv2beta2.HPAScalingPolicy{} + for _, policy := range v2behavior.ScaleDown.Policies { + v2beta2policy := convertToV2Beta2HPAScalingPolicy(policy) + ScaleDownPolicies = append(ScaleDownPolicies, v2beta2policy) } - autoscaler.Spec.Behavior = behavior + scaleDownRules.Policies = ScaleDownPolicies } - result = &autoscaler + + behavior.ScaleDown = scaleDownRules } - return result + 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(rules autoscalingv2.HPAScalingRules) autoscalingv2beta2.ScalingPolicySelect { + max := autoscalingv2beta2.MaxPolicySelect + min := autoscalingv2beta2.MinPolicySelect + disabled := autoscalingv2beta2.DisabledPolicySelect + + switch *rules.SelectPolicy { + case autoscalingv2.MaxChangePolicySelect: + return max + case autoscalingv2.MinChangePolicySelect: + return min + case autoscalingv2.DisabledPolicySelect: + return disabled + } + + return disabled } From bcf71e7242928ada4223c98b4265f274b313d933 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 10:21:07 +0200 Subject: [PATCH 11/14] Only set behavior if it exists in the collector CR Signed-off-by: Kevin Earls --- pkg/collector/horizontalpodautoscaler.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index 9b8cd4bbec..f8f2485edf 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -59,7 +59,6 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al }, } metrics := []autoscalingv2beta2.MetricSpec{targetCPUUtilization} - behavior := convertToV2beta2Behavior(*otelcol.Spec.Autoscaler.Behavior) autoscaler := autoscalingv2beta2.HorizontalPodAutoscaler{ ObjectMeta: objectMeta, @@ -72,10 +71,14 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al MinReplicas: otelcol.Spec.Replicas, MaxReplicas: *otelcol.Spec.MaxReplicas, Metrics: metrics, - Behavior: &behavior, }, } + 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{ @@ -101,9 +104,11 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al MinReplicas: otelcol.Spec.Replicas, MaxReplicas: *otelcol.Spec.MaxReplicas, Metrics: metrics, - Behavior: otelcol.Spec.Autoscaler.Behavior, }, } + if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { + autoscaler.Spec.Behavior = otelcol.Spec.Autoscaler.Behavior + } result = &autoscaler } From 0f8e029a082ca05b50f2aaf6d90c328eb153c73a Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 11:19:32 +0200 Subject: [PATCH 12/14] Aded some unit tests Signed-off-by: Kevin Earls --- pkg/collector/horizontalpodautoscaler.go | 18 +++---- pkg/collector/horizontalpodautoscaler_test.go | 52 +++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/pkg/collector/horizontalpodautoscaler.go b/pkg/collector/horizontalpodautoscaler.go index f8f2485edf..25265a3d70 100644 --- a/pkg/collector/horizontalpodautoscaler.go +++ b/pkg/collector/horizontalpodautoscaler.go @@ -75,7 +75,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil { - behavior := convertToV2beta2Behavior(*otelcol.Spec.Autoscaler.Behavior) + behavior := ConvertToV2beta2Behavior(*otelcol.Spec.Autoscaler.Behavior) autoscaler.Spec.Behavior = &behavior } @@ -116,7 +116,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al } // Create a v2beta2 HorizontalPodAutoscalerBehavior from a v2 instance. -func convertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBehavior) autoscalingv2beta2.HorizontalPodAutoscalerBehavior { +func ConvertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBehavior) autoscalingv2beta2.HorizontalPodAutoscalerBehavior { behavior := &autoscalingv2beta2.HorizontalPodAutoscalerBehavior{} if v2behavior.ScaleUp != nil { @@ -125,13 +125,13 @@ func convertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBe scaleUpRules.StabilizationWindowSeconds = &scaleUpTime if v2behavior.ScaleUp.SelectPolicy != nil { - scaleUpSelectPolicy := convertToV2Beta2SelectPolicy(*v2behavior.ScaleUp) + 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) + v2beta2policy := ConvertToV2Beta2HPAScalingPolicy(policy) scaleUpPolicies = append(scaleUpPolicies, v2beta2policy) } scaleUpRules.Policies = scaleUpPolicies @@ -146,13 +146,13 @@ func convertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBe scaleDownRules.StabilizationWindowSeconds = &scaleDownTime if v2behavior.ScaleDown.SelectPolicy != nil { - scaleDownSelectPolicy := convertToV2Beta2SelectPolicy(*v2behavior.ScaleDown) + 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) + v2beta2policy := ConvertToV2Beta2HPAScalingPolicy(policy) ScaleDownPolicies = append(ScaleDownPolicies, v2beta2policy) } scaleDownRules.Policies = ScaleDownPolicies @@ -164,7 +164,7 @@ func convertToV2beta2Behavior(v2behavior autoscalingv2.HorizontalPodAutoscalerBe return *behavior } -func convertToV2Beta2HPAScalingPolicy(v2policy autoscalingv2.HPAScalingPolicy) autoscalingv2beta2.HPAScalingPolicy { +func ConvertToV2Beta2HPAScalingPolicy(v2policy autoscalingv2.HPAScalingPolicy) autoscalingv2beta2.HPAScalingPolicy { v2beta2Policy := &autoscalingv2beta2.HPAScalingPolicy{ Value: v2policy.Value, PeriodSeconds: v2policy.PeriodSeconds, @@ -180,12 +180,12 @@ func convertToV2Beta2HPAScalingPolicy(v2policy autoscalingv2.HPAScalingPolicy) a return *v2beta2Policy } -func convertToV2Beta2SelectPolicy(rules autoscalingv2.HPAScalingRules) autoscalingv2beta2.ScalingPolicySelect { +func ConvertToV2Beta2SelectPolicy(scalingPolicy autoscalingv2.ScalingPolicySelect) autoscalingv2beta2.ScalingPolicySelect { max := autoscalingv2beta2.MaxPolicySelect min := autoscalingv2beta2.MinPolicySelect disabled := autoscalingv2beta2.DisabledPolicySelect - switch *rules.SelectPolicy { + switch scalingPolicy { case autoscalingv2.MaxChangePolicySelect: return max case autoscalingv2.MinChangePolicySelect: diff --git a/pkg/collector/horizontalpodautoscaler_test.go b/pkg/collector/horizontalpodautoscaler_test.go index 6aaa71ca5c..19b565f50c 100644 --- a/pkg/collector/horizontalpodautoscaler_test.go +++ b/pkg/collector/horizontalpodautoscaler_test.go @@ -91,6 +91,58 @@ 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 { From c14096d6be0c073d5b59a9f9a822946b52489a16 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 15:21:53 +0200 Subject: [PATCH 13/14] Add kuttl assertion that hpa scaled down Signed-off-by: Kevin Earls --- tests/e2e/autoscale/02-assert.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/e2e/autoscale/02-assert.yaml 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 From 89a2f48c19e8c9a607cd00ba8c45f540445fb6b8 Mon Sep 17 00:00:00 2001 From: Kevin Earls Date: Thu, 15 Sep 2022 16:03:43 +0200 Subject: [PATCH 14/14] added whitespace to rerun tests Signed-off-by: Kevin Earls --- pkg/collector/horizontalpodautoscaler_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/collector/horizontalpodautoscaler_test.go b/pkg/collector/horizontalpodautoscaler_test.go index 19b565f50c..c8f076248b 100644 --- a/pkg/collector/horizontalpodautoscaler_test.go +++ b/pkg/collector/horizontalpodautoscaler_test.go @@ -113,6 +113,7 @@ func TestConvertToV2beta2Behavior(t *testing.T) { } 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)