Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio
- **General**: Correct error message when awsSecretAccessKey is missing in credential-based authentication ([#7265](https://github.com/kedacore/keda/pull/7265))
- **AWS CloudWatch Scaler**: Add cross-account observability support ([#7189](https://github.com/kedacore/keda/issues/7189))
- **Dynamodb Scaler**: Add FilterExpression support ([#7102](https://github.com/kedacore/keda/issues/7102))
- **Gerneral**: Add cooldownOnlyAfterHpaMinReplica bool to control cooldown behavior ([#7204](https://github.com/kedacore/keda/issues/7204))

### Fixes

Expand Down
4 changes: 4 additions & 0 deletions apis/keda/v1alpha1/scaledobject_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ type AdvancedConfig struct {
RestoreToOriginalReplicaCount bool `json:"restoreToOriginalReplicaCount,omitempty"`
// +optional
ScalingModifiers ScalingModifiers `json:"scalingModifiers,omitempty"`
// +optional
CooldownOnlyAfterHpaMinReplica bool `json:"cooldownOnlyAfterHpaMinReplica,omitempty"`
}

// ScalingModifiers describes advanced scaling logic options like formula
Expand Down Expand Up @@ -177,6 +179,8 @@ type ScaledObjectStatus struct {
// +optional
LastActiveTime *metav1.Time `json:"lastActiveTime,omitempty"`
// +optional
HpaMinReplicaSinceTime *metav1.Time `json:"hpaMinReplicaSinceTime,omitempty"`
// +optional
ExternalMetricNames []string `json:"externalMetricNames,omitempty"`
// +optional
ResourceMetricNames []string `json:"resourceMetricNames,omitempty"`
Expand Down
4 changes: 4 additions & 0 deletions apis/keda/v1alpha1/zz_generated.deepcopy.go

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

5 changes: 5 additions & 0 deletions config/crd/bases/keda.sh_scaledobjects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ spec:
advanced:
description: AdvancedConfig specifies advance scaling options
properties:
cooldownOnlyAfterHpaMinReplica:
type: boolean
horizontalPodAutoscalerConfig:
description: HorizontalPodAutoscalerConfig specifies horizontal
scale config
Expand Down Expand Up @@ -405,6 +407,9 @@ spec:
type: string
type: object
type: object
hpaMinReplicaSinceTime:
format: date-time
type: string
hpaName:
type: string
lastActiveTime:
Expand Down
2 changes: 1 addition & 1 deletion config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: ghcr.io/kedacore/keda
newName: ghcr.io/kedacore/keda
newName: docker.io/rlanhellas/keda
newTag: main
2 changes: 1 addition & 1 deletion config/metrics-server/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: ghcr.io/kedacore/keda-metrics-apiserver
newName: ghcr.io/kedacore/keda-metrics-apiserver
newName: docker.io/rlanhellas/keda-metrics-apiserver
newTag: main
2 changes: 1 addition & 1 deletion config/webhooks/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: ghcr.io/kedacore/keda-admission-webhooks
newName: ghcr.io/kedacore/keda-admission-webhooks
newName: docker.io/rlanhellas/keda-admission-webhooks
newTag: main
11 changes: 5 additions & 6 deletions pkg/metricsservice/api/metrics.pb.go

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

17 changes: 8 additions & 9 deletions pkg/metricsservice/api/metrics_grpc.pb.go

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

3 changes: 1 addition & 2 deletions pkg/mock/mock_scaling/mock_executor/mock_interface.go

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

9 changes: 4 additions & 5 deletions pkg/scalers/externalscaler/externalscaler.pb.go

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

15 changes: 7 additions & 8 deletions pkg/scalers/externalscaler/externalscaler_grpc.pb.go

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

11 changes: 5 additions & 6 deletions pkg/scalers/liiklus/LiiklusService.pb.go

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

19 changes: 9 additions & 10 deletions pkg/scalers/liiklus/LiiklusService_grpc.pb.go

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

43 changes: 41 additions & 2 deletions pkg/scaling/executor/scale_scaledobjects.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ func (e *scaleExecutor) RequestScale(ctx context.Context, scaledObject *kedav1al
logger.Error(err, "Error getting information on the current Scale")
return
}

// only manage HpaMinReplicaSinceTime field if the feature CooldownOnlyAfterHpaMinReplica is enabled
if scaledObject.Spec.Advanced != nil && scaledObject.Spec.Advanced.CooldownOnlyAfterHpaMinReplica {
hpaMinReplicas := scaledObject.GetHPAMinReplicas()
if currentReplicas <= *hpaMinReplicas && scaledObject.Status.HpaMinReplicaSinceTime == nil {
status := scaledObject.Status.DeepCopy()
status.HpaMinReplicaSinceTime = &metav1.Time{Time: time.Now()}
err = kedastatus.UpdateScaledObjectStatus(ctx, e.client, logger, scaledObject, status)
if err != nil {
logger.Error(err, "Error updating HPA min replica since time")
return
}
} else if currentReplicas > *hpaMinReplicas && scaledObject.Status.HpaMinReplicaSinceTime != nil {
status := scaledObject.Status.DeepCopy()
status.HpaMinReplicaSinceTime = nil
err = kedastatus.UpdateScaledObjectStatus(ctx, e.client, logger, scaledObject, status)
if err != nil {
logger.Error(err, "Error updating HPA min replica since time")
return
}
}
}

// if the ScaledObject's triggers aren't in the error state,
// but ScaledObject.Status.ReadyCondition is set not set to 'true' -> set it back to 'true'
readyCondition := scaledObject.Status.Conditions.GetReadyCondition()
Expand Down Expand Up @@ -243,10 +266,26 @@ func (e *scaleExecutor) scaleToZeroOrIdle(ctx context.Context, logger logr.Logge
scaledObject.CreationTimestamp = metav1.NewTime(time.Now())
}

if scale == nil {
var err error
scale, err = e.getScaleTargetScale(ctx, scaledObject)
if err != nil {
logger.Error(err, "Error in getting scale object")
return
}
}

cooldownOnlyAfterHpaMinReplica := false
if scaledObject.Spec.Advanced != nil {
cooldownOnlyAfterHpaMinReplica = scaledObject.Spec.Advanced.CooldownOnlyAfterHpaMinReplica
}

// LastActiveTime can be nil if the ScaleTarget was scaled outside of KEDA.
// In this case we will ignore the cooldown period and scale it down
if (scaledObject.Status.LastActiveTime == nil && scaledObject.CreationTimestamp.Add(initialCooldownPeriod).Before(time.Now())) || (scaledObject.Status.LastActiveTime != nil &&
scaledObject.Status.LastActiveTime.Add(cooldownPeriod).Before(time.Now())) {
if (scaledObject.Status.LastActiveTime == nil && scaledObject.CreationTimestamp.Add(initialCooldownPeriod).Before(time.Now())) ||
(!cooldownOnlyAfterHpaMinReplica && scaledObject.Status.LastActiveTime != nil && scaledObject.Status.LastActiveTime.Add(cooldownPeriod).Before(time.Now())) ||
(cooldownOnlyAfterHpaMinReplica && scaledObject.Status.HpaMinReplicaSinceTime != nil && scaledObject.Status.HpaMinReplicaSinceTime.Add(cooldownPeriod).Before(time.Now()) &&
scale.Spec.Replicas <= *scaledObject.GetHPAMinReplicas()) {
// or last time a trigger was active was > cooldown period, so scale in.
idleValue, scaleToReplicas := getIdleOrMinimumReplicaCount(scaledObject)

Expand Down
Loading
Loading