Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TargetMemoryUtilization metric for AutoScaling #1223

Merged
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1401868
Add TargetMemoryUtilization metric for AutoScaling
kevinearls Nov 4, 2022
c76eda2
Add changes to v2beta2 as there is no way to un e2e tests just for on…
kevinearls Nov 4, 2022
5f1130f
See if we just have a race condition
kevinearls Nov 4, 2022
f2d5652
Reset kuttl timeout
kevinearls Nov 7, 2022
de45a09
Add some debugging code to help analyze failures on github
kevinearls Nov 7, 2022
06c9d4c
Try to appease the linter
kevinearls Nov 7, 2022
80a1ce1
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 8, 2022
7d3eede
Restore autoscale tests
kevinearls Nov 8, 2022
f80f9f4
Cleanup
kevinearls Nov 8, 2022
04402d3
More cleanup
kevinearls Nov 8, 2022
6f96d55
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 14, 2022
52efcce
Respond to comments
kevinearls Nov 14, 2022
bc6ecb0
Cleanup whitespace so linter will rerun
kevinearls Nov 14, 2022
a7cfe40
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 16, 2022
db1a05d
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 18, 2022
df93b23
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 22, 2022
6e87294
Don't set TargetCPUUtilization to default if another metric is set
kevinearls Nov 23, 2022
e8e489b
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 30, 2022
0a7f5fe
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 30, 2022
def0cc9
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 30, 2022
76b9d46
Merge branch 'main' into add-memory-utilization-metric
kevinearls Nov 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apis/v1alpha1/opentelemetrycollector_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ type AutoscalerSpec struct {
// If average CPU exceeds this value, the HPA will scale up. Defaults to 90 percent.
// +optional
TargetCPUUtilization *int32 `json:"targetCPUUtilization,omitempty"`
// +optional
// TargetMemoryUtilization sets the target average memory utilization across all replicas
TargetMemoryUtilization *int32 `json:"targetMemoryUtilization,omitempty"`
}

func init() {
Expand Down
14 changes: 9 additions & 5 deletions apis/v1alpha1/opentelemetrycollector_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ func (r *OpenTelemetryCollector) Default() {
r.Spec.TargetAllocator.Replicas = &one
}

// Set default targetCPUUtilization for autoscaler
if r.Spec.MaxReplicas != nil && (r.Spec.Autoscaler == nil || r.Spec.Autoscaler.TargetCPUUtilization == nil) {
defaultCPUTarget := int32(90)
if r.Spec.MaxReplicas != nil {
if r.Spec.Autoscaler == nil {
r.Spec.Autoscaler = &AutoscalerSpec{}
}
r.Spec.Autoscaler.TargetCPUUtilization = &defaultCPUTarget

if r.Spec.Autoscaler.TargetMemoryUtilization == nil && r.Spec.Autoscaler.TargetCPUUtilization == nil {
defaultCPUTarget := int32(90)
r.Spec.Autoscaler.TargetCPUUtilization = &defaultCPUTarget
}
}
}

Expand Down Expand Up @@ -176,7 +178,9 @@ func (r *OpenTelemetryCollector) validateCRDSpec() error {
if r.Spec.Autoscaler != nil && r.Spec.Autoscaler.TargetCPUUtilization != nil && (*r.Spec.Autoscaler.TargetCPUUtilization < int32(1) || *r.Spec.Autoscaler.TargetCPUUtilization > int32(99)) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, targetCPUUtilization should be greater than 0 and less than 100")
}

if r.Spec.Autoscaler != nil && r.Spec.Autoscaler.TargetMemoryUtilization != nil && (*r.Spec.Autoscaler.TargetMemoryUtilization < int32(1) || *r.Spec.Autoscaler.TargetMemoryUtilization > int32(99)) {
return fmt.Errorf("the OpenTelemetry Spec autoscale configuration is incorrect, targetMemoryUtilization should be greater than 0 and less than 100")
}
}

if r.Spec.Ingress.Type == IngressTypeNginx && r.Spec.Mode == ModeSidecar {
Expand Down
5 changes: 5 additions & 0 deletions apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1016,6 +1016,11 @@ spec:
the HPA will scale up. Defaults to 90 percent.
format: int32
type: integer
targetMemoryUtilization:
description: TargetMemoryUtilization sets the target average memory
utilization across all replicas
format: int32
type: integer
type: object
config:
description: Config is the raw JSON to be used as the collector's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,11 @@ spec:
the HPA will scale up. Defaults to 90 percent.
format: int32
type: integer
targetMemoryUtilization:
description: TargetMemoryUtilization sets the target average memory
utilization across all replicas
format: int32
type: integer
type: object
config:
description: Config is the raw JSON to be used as the collector's
Expand Down
9 changes: 9 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3228,6 +3228,15 @@ Autoscaler specifies the pod autoscaling configuration to use for the OpenTeleme
<i>Format</i>: int32<br/>
</td>
<td>false</td>
</tr><tr>
<td><b>targetMemoryUtilization</b></td>
<td>integer</td>
<td>
TargetMemoryUtilization sets the target average memory utilization across all replicas<br/>
<br/>
<i>Format</i>: int32<br/>
</td>
<td>false</td>
</tr></tbody>
</table>

Expand Down
58 changes: 45 additions & 13 deletions pkg/collector/horizontalpodautoscaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al

labels := Labels(otelcol, cfg.LabelsFilter())
labels["app.kubernetes.io/name"] = naming.Collector(otelcol)

annotations := Annotations(otelcol)

var result client.Object

objectMeta := metav1.ObjectMeta{
Expand All @@ -46,6 +44,22 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al
}

if autoscalingVersion == autodetect.AutoscalingVersionV2Beta2 {
metrics := []autoscalingv2beta2.MetricSpec{}

if otelcol.Spec.Autoscaler.TargetMemoryUtilization != nil {
utilizationTarget := autoscalingv2beta2.MetricSpec{
Type: autoscalingv2beta2.ResourceMetricSourceType,
Resource: &autoscalingv2beta2.ResourceMetricSource{
Name: corev1.ResourceMemory,
Target: autoscalingv2beta2.MetricTarget{
Type: autoscalingv2beta2.UtilizationMetricType,
AverageUtilization: otelcol.Spec.Autoscaler.TargetMemoryUtilization,
},
},
}
metrics = append(metrics, utilizationTarget)
}

targetCPUUtilization := autoscalingv2beta2.MetricSpec{
Type: autoscalingv2beta2.ResourceMetricSourceType,
Resource: &autoscalingv2beta2.ResourceMetricSource{
Expand All @@ -56,7 +70,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al
},
},
}
metrics := []autoscalingv2beta2.MetricSpec{targetCPUUtilization}
metrics = append(metrics, targetCPUUtilization)

autoscaler := autoscalingv2beta2.HorizontalPodAutoscaler{
ObjectMeta: objectMeta,
Expand All @@ -79,17 +93,35 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al

result = &autoscaler
} else {
targetCPUUtilization := autoscalingv2.MetricSpec{
Type: autoscalingv2.ResourceMetricSourceType,
Resource: &autoscalingv2.ResourceMetricSource{
Name: corev1.ResourceCPU,
Target: autoscalingv2.MetricTarget{
Type: autoscalingv2.UtilizationMetricType,
AverageUtilization: otelcol.Spec.Autoscaler.TargetCPUUtilization,
metrics := []autoscalingv2.MetricSpec{}

if otelcol.Spec.Autoscaler.TargetMemoryUtilization != nil {
utilizationTarget := autoscalingv2.MetricSpec{
Type: autoscalingv2.ResourceMetricSourceType,
Resource: &autoscalingv2.ResourceMetricSource{
Name: corev1.ResourceMemory,
Target: autoscalingv2.MetricTarget{
Type: autoscalingv2.UtilizationMetricType,
AverageUtilization: otelcol.Spec.Autoscaler.TargetMemoryUtilization,
},
},
},
}
metrics = append(metrics, utilizationTarget)
}

if otelcol.Spec.Autoscaler.TargetCPUUtilization != nil {
targetCPUUtilization := autoscalingv2.MetricSpec{
Type: autoscalingv2.ResourceMetricSourceType,
Resource: &autoscalingv2.ResourceMetricSource{
Name: corev1.ResourceCPU,
Target: autoscalingv2.MetricTarget{
Type: autoscalingv2.UtilizationMetricType,
AverageUtilization: otelcol.Spec.Autoscaler.TargetCPUUtilization,
},
},
}
metrics = append(metrics, targetCPUUtilization)
}
metrics := []autoscalingv2.MetricSpec{targetCPUUtilization}

autoscaler := autoscalingv2.HorizontalPodAutoscaler{
ObjectMeta: objectMeta,
Expand All @@ -104,7 +136,7 @@ func HorizontalPodAutoscaler(cfg config.Config, logger logr.Logger, otelcol v1al
Metrics: metrics,
},
}
if otelcol.Spec.Autoscaler != nil && otelcol.Spec.Autoscaler.Behavior != nil {
if otelcol.Spec.Autoscaler.Behavior != nil {
autoscaler.Spec.Behavior = otelcol.Spec.Autoscaler.Behavior
}
result = &autoscaler
Expand Down
28 changes: 20 additions & 8 deletions pkg/collector/horizontalpodautoscaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ func TestHPA(t *testing.T) {

var minReplicas int32 = 3
var maxReplicas int32 = 5
var cpuUtilization int32 = 90
var cpuUtilization int32 = 66
var memoryUtilization int32 = 77

otelcol := v1alpha1.OpenTelemetryCollector{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -51,7 +52,8 @@ func TestHPA(t *testing.T) {
Replicas: &minReplicas,
MaxReplicas: &maxReplicas,
Autoscaler: &v1alpha1.AutoscalerSpec{
TargetCPUUtilization: &cpuUtilization,
TargetCPUUtilization: &cpuUtilization,
TargetMemoryUtilization: &memoryUtilization,
},
},
}
Expand All @@ -76,9 +78,13 @@ func TestHPA(t *testing.T) {
assert.Equal(t, "my-instance-collector", hpa.Labels["app.kubernetes.io/name"])
assert.Equal(t, int32(3), *hpa.Spec.MinReplicas)
assert.Equal(t, int32(5), hpa.Spec.MaxReplicas)
assert.Equal(t, 1, len(hpa.Spec.Metrics))
assert.Equal(t, corev1.ResourceCPU, hpa.Spec.Metrics[0].Resource.Name)
assert.Equal(t, int32(90), *hpa.Spec.Metrics[0].Resource.Target.AverageUtilization)
for _, metric := range hpa.Spec.Metrics {
if metric.Resource.Name == corev1.ResourceCPU {
assert.Equal(t, cpuUtilization, *metric.Resource.Target.AverageUtilization)
} else if metric.Resource.Name == corev1.ResourceMemory {
assert.Equal(t, memoryUtilization, *metric.Resource.Target.AverageUtilization)
}
}
} else {
hpa := raw.(*autoscalingv2.HorizontalPodAutoscaler)

Expand All @@ -87,9 +93,15 @@ func TestHPA(t *testing.T) {
assert.Equal(t, "my-instance-collector", hpa.Labels["app.kubernetes.io/name"])
assert.Equal(t, int32(3), *hpa.Spec.MinReplicas)
assert.Equal(t, int32(5), hpa.Spec.MaxReplicas)
assert.Equal(t, 1, len(hpa.Spec.Metrics))
assert.Equal(t, corev1.ResourceCPU, hpa.Spec.Metrics[0].Resource.Name)
assert.Equal(t, int32(90), *hpa.Spec.Metrics[0].Resource.Target.AverageUtilization)
assert.Equal(t, 2, len(hpa.Spec.Metrics))

for _, metric := range hpa.Spec.Metrics {
if metric.Resource.Name == corev1.ResourceCPU {
assert.Equal(t, cpuUtilization, *metric.Resource.Target.AverageUtilization)
} else if metric.Resource.Name == corev1.ResourceMemory {
assert.Equal(t, memoryUtilization, *metric.Resource.Target.AverageUtilization)
}
}
}
})
}
Expand Down
11 changes: 10 additions & 1 deletion pkg/collector/reconcile/horizontalpodautoscaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

autoscalingv2 "k8s.io/api/autoscaling/v2"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -127,7 +128,15 @@ func setAutoscalerSpec(params Params, autoscalingVersion autodetect.AutoscalingV
} else {
updated.(*autoscalingv2.HorizontalPodAutoscaler).Spec.MinReplicas = &one
}
updated.(*autoscalingv2.HorizontalPodAutoscaler).Spec.Metrics[0].Resource.Target.AverageUtilization = params.Instance.Spec.Autoscaler.TargetCPUUtilization

// This will update memory and CPU usage for now, and can be used to update other metrics in the future
for _, metric := range updated.(*autoscalingv2.HorizontalPodAutoscaler).Spec.Metrics {
if metric.Resource.Name == corev1.ResourceCPU {
metric.Resource.Target.AverageUtilization = params.Instance.Spec.Autoscaler.TargetCPUUtilization
} else if metric.Resource.Name == corev1.ResourceMemory {
metric.Resource.Target.AverageUtilization = params.Instance.Spec.Autoscaler.TargetMemoryUtilization
}
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/e2e/autoscale/00-install.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This creates two different deployments. The first one will be used to see if we scale properly. (Note that we are
# only scaling up to 2 because of limitations of KUTTL). The second is to check the targetCPUUtilization option.
#
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/autoscale/01-assert.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Wait until tracegen has completed and the simplest deployment has scaled up to 2
apiVersion: batch/v1
kind: Job
metadata:
Expand Down
1 change: 1 addition & 0 deletions tests/e2e/autoscale/02-assert.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Wait for the collector to scale back down to 1
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector

Expand Down