diff --git a/CHANGELOG.md b/CHANGELOG.md index 2043381472b..a4119965aa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,12 +53,13 @@ To learn more about our roadmap, we recommend reading [this document](ROADMAP.md - **General:** Use more readable timestamps in KEDA Operator logs ([#3066](https://github.com/kedacore/keda/issue/3066)) - **AWS SQS Queue Scaler:** Support for scaling to include in-flight messages. ([#3133](https://github.com/kedacore/keda/issues/3133)) - **Azure Pipelines Scaler:** Add support for Azure Pipelines to support demands (capabilities) ([#2328](https://github.com/kedacore/keda/issues/2328)) +- **CPU/Memory Scaler:** Added support for targeting specific container in a pod ([#1378](https://github.com/kedacore/keda/issues/1378)) - **GCP Stackdriver Scaler:** Added aggregation parameters ([#3008](https://github.com/kedacore/keda/issues/3008)) - **Kafka Scaler:** Handle Sarama errors properly ([#3056](https://github.com/kedacore/keda/issues/3056)) - **Kafka Scaler:** Support of passphrase encrypted PKCS #\8 private key ([3449](https://github.com/kedacore/keda/issues/3449)) - **Prometheus Scaler:** Add ignoreNullValues to return error when prometheus return null in values ([#3065](https://github.com/kedacore/keda/issues/3065)) - **Selenium Grid Scaler:** Edge active sessions not being properly counted ([#2709](https://github.com/kedacore/keda/issues/2709)) -- **Selenium Grid Scaler:** Max Sessions implementation issue ([#3061](https://github.com/kedacore/keda/issues/3061)) +- **Selenium Grid Scaler:** Max Sessions implementation issue ([#3061](https://github.c>>>>>>> mainom/kedacore/keda/issues/3061)) ### Fixes diff --git a/pkg/scalers/cpu_memory_scaler.go b/pkg/scalers/cpu_memory_scaler.go index edaa2af48ea..7ad53a6e365 100644 --- a/pkg/scalers/cpu_memory_scaler.go +++ b/pkg/scalers/cpu_memory_scaler.go @@ -22,6 +22,7 @@ type cpuMemoryMetadata struct { Type v2beta2.MetricTargetType AverageValue *resource.Quantity AverageUtilization *int32 + ContainerName string } // NewCPUMemoryScaler creates a new cpuMemoryScaler @@ -73,6 +74,11 @@ func parseResourceMetadata(config *ScalerConfig, logger logr.Logger) (*cpuMemory default: return nil, fmt.Errorf("unsupported metric type, allowed values are 'Utilization' or 'AverageValue'") } + + if value, ok = config.TriggerMetadata["containerName"]; ok && value != "" { + meta.ContainerName = value + } + return meta, nil } @@ -88,15 +94,31 @@ func (s *cpuMemoryScaler) Close(context.Context) error { // GetMetricSpecForScaling returns the metric spec for the HPA func (s *cpuMemoryScaler) GetMetricSpecForScaling(context.Context) []v2beta2.MetricSpec { - cpuMemoryMetric := &v2beta2.ResourceMetricSource{ - Name: s.resourceName, - Target: v2beta2.MetricTarget{ - Type: s.metadata.Type, - AverageUtilization: s.metadata.AverageUtilization, - AverageValue: s.metadata.AverageValue, - }, + var metricSpec v2beta2.MetricSpec + + if s.metadata.ContainerName != "" { + containerCPUMemoryMetric := &v2beta2.ContainerResourceMetricSource{ + Name: s.resourceName, + Target: v2beta2.MetricTarget{ + Type: s.metadata.Type, + AverageUtilization: s.metadata.AverageUtilization, + AverageValue: s.metadata.AverageValue, + }, + Container: s.metadata.ContainerName, + } + metricSpec = v2beta2.MetricSpec{ContainerResource: containerCPUMemoryMetric, Type: v2beta2.ContainerResourceMetricSourceType} + } else { + cpuMemoryMetric := &v2beta2.ResourceMetricSource{ + Name: s.resourceName, + Target: v2beta2.MetricTarget{ + Type: s.metadata.Type, + AverageUtilization: s.metadata.AverageUtilization, + AverageValue: s.metadata.AverageValue, + }, + } + metricSpec = v2beta2.MetricSpec{Resource: cpuMemoryMetric, Type: v2beta2.ResourceMetricSourceType} } - metricSpec := v2beta2.MetricSpec{Resource: cpuMemoryMetric, Type: v2beta2.ResourceMetricSourceType} + return []v2beta2.MetricSpec{metricSpec} } diff --git a/pkg/scalers/cpu_memory_scaler_test.go b/pkg/scalers/cpu_memory_scaler_test.go index b1922d5c0d7..3d924146fb2 100644 --- a/pkg/scalers/cpu_memory_scaler_test.go +++ b/pkg/scalers/cpu_memory_scaler_test.go @@ -21,10 +21,16 @@ var validCPUMemoryMetadata = map[string]string{ "type": "Utilization", "value": "50", } +var validContainerCPUMemoryMetadata = map[string]string{ + "type": "Utilization", + "value": "50", + "containerName": "foo", +} var testCPUMemoryMetadata = []parseCPUMemoryMetadataTestData{ {"", map[string]string{}, true}, {"", validCPUMemoryMetadata, false}, + {"", validContainerCPUMemoryMetadata, false}, {"", map[string]string{"type": "Utilization", "value": "50"}, false}, {v2beta2.UtilizationMetricType, map[string]string{"value": "50"}, false}, {"", map[string]string{"type": "AverageValue", "value": "50"}, false}, @@ -75,3 +81,30 @@ func TestGetMetricSpecForScaling(t *testing.T) { assert.Equal(t, metricSpec[0].Resource.Name, v1.ResourceCPU) assert.Equal(t, metricSpec[0].Resource.Target.Type, v2beta2.UtilizationMetricType) } + +func TestGetContainerMetricSpecForScaling(t *testing.T) { + // Using trigger.metadata.type field for type + config := &ScalerConfig{ + TriggerMetadata: validContainerCPUMemoryMetadata, + } + scaler, _ := NewCPUMemoryScaler(v1.ResourceCPU, config) + metricSpec := scaler.GetMetricSpecForScaling(context.Background()) + + assert.Equal(t, metricSpec[0].Type, v2beta2.ContainerResourceMetricSourceType) + assert.Equal(t, metricSpec[0].ContainerResource.Name, v1.ResourceCPU) + assert.Equal(t, metricSpec[0].ContainerResource.Target.Type, v2beta2.UtilizationMetricType) + assert.Equal(t, metricSpec[0].ContainerResource.Container, validContainerCPUMemoryMetadata["containerName"]) + + // Using trigger.metricType field for type + config = &ScalerConfig{ + TriggerMetadata: map[string]string{"value": "50", "containerName": "bar"}, + MetricType: v2beta2.UtilizationMetricType, + } + scaler, _ = NewCPUMemoryScaler(v1.ResourceCPU, config) + metricSpec = scaler.GetMetricSpecForScaling(context.Background()) + + assert.Equal(t, metricSpec[0].Type, v2beta2.ContainerResourceMetricSourceType) + assert.Equal(t, metricSpec[0].ContainerResource.Name, v1.ResourceCPU) + assert.Equal(t, metricSpec[0].ContainerResource.Target.Type, v2beta2.UtilizationMetricType) + assert.Equal(t, metricSpec[0].ContainerResource.Container, "bar") +}