diff --git a/.gitignore b/.gitignore index b873546..b95c042 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ vendor bin +.idea diff --git a/pkg/apis/scaling/v1alpha1/types.go b/pkg/apis/scaling/v1alpha1/types.go index 8cf9a49..923c671 100644 --- a/pkg/apis/scaling/v1alpha1/types.go +++ b/pkg/apis/scaling/v1alpha1/types.go @@ -36,11 +36,12 @@ type ScheduledScalerTarget struct { } type ScheduledScalerStep struct { - Runat string `json:"runat"` - Mode string `json:"mode"` - MinReplicas *int32 `json:"minReplicas"` - MaxReplicas *int32 `json:"maxReplicas"` - Replicas *int32 `json:"replicas"` + Runat string `json:"runat"` + Mode string `json:"mode"` + MinReplicas *int32 `json:"minReplicas"` + MaxReplicas *int32 `json:"maxReplicas"` + Replicas *int32 `json:"replicas"` + TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"` } type ScheduledScalerSpec struct { @@ -49,11 +50,12 @@ type ScheduledScalerSpec struct { TimeZone string `json:"timeZone"` } -// FooStatus is the status for a Foo resource +// ScheduledScalerStatus is the status for a ScheduledScaler resource type ScheduledScalerStatus struct { - Mode string `json:"mode"` - MinReplicas int32 `json:"minReplicas"` - MaxReplicas int32 `json:"maxReplicas"` + Mode string `json:"mode"` + MinReplicas int32 `json:"minReplicas"` + MaxReplicas int32 `json:"maxReplicas"` + TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/services/scaling/step/parser.go b/pkg/services/scaling/step/parser.go index c8126c5..3fcbc61 100644 --- a/pkg/services/scaling/step/parser.go +++ b/pkg/services/scaling/step/parser.go @@ -2,15 +2,17 @@ package step import scalingv1alpha1 "k8s.restdev.com/operators/pkg/apis/scaling/v1alpha1" -func Parse(step scalingv1alpha1.ScheduledScalerStep) (min, max *int32) { +func Parse(step scalingv1alpha1.ScheduledScalerStep) (min, max, cpuTarget *int32) { if step.Mode == "range" { min = step.MinReplicas max = step.MaxReplicas + cpuTarget = step.TargetCPUUtilizationPercentage } if step.Mode == "fixed" { min = step.Replicas max = step.Replicas + cpuTarget = step.TargetCPUUtilizationPercentage } return diff --git a/scaling-controller.go b/scaling-controller.go index ff41503..c07e5fe 100644 --- a/scaling-controller.go +++ b/scaling-controller.go @@ -146,7 +146,7 @@ func (c *ScheduledScalerController) scheduledScalerHpaCronAdd(scheduledScaler *s var mutex sync.Mutex for key := range ssCopy.Spec.Steps { step := scheduledScaler.Spec.Steps[key] - min, max := scalingstep.Parse(step) + min, max, cpuTarget := scalingstep.Parse(step) c.cronProxy.Push(stepsCron, step.Runat, func() { // If this scheduled scaler retries, don't let the "next" one get overwritten by its retry. mutex.Lock() @@ -167,6 +167,9 @@ func (c *ScheduledScalerController) scheduledScalerHpaCronAdd(scheduledScaler *s } hpa.Spec.MinReplicas = min hpa.Spec.MaxReplicas = *max + if cpuTarget != nil { + hpa.Spec.TargetCPUUtilizationPercentage = cpuTarget + } _, err = hpaClient.Update(hpa) if apierr.IsConflict(err) { glog.Infof("FAILED TO UPDATE HPA: %s - %v; retrying", scheduledScaler.Spec.Target.Name, err) @@ -194,6 +197,7 @@ func (c *ScheduledScalerController) scheduledScalerHpaCronAdd(scheduledScaler *s ss.Status.Mode = step.Mode ss.Status.MinReplicas = *min ss.Status.MaxReplicas = *max + ss.Status.TargetCPUUtilizationPercentage = cpuTarget _, err = ssClient.Update(ss) if apierr.IsConflict(err) { glog.Infof("FAILED TO UPDATE SCHEDULED SCALER STATUS: %s - %v; retrying", scheduledScaler.Name, err) @@ -248,11 +252,19 @@ func (c *ScheduledScalerController) scheduledScalerIgCronAdd(scheduledScaler *sc } for key := range scheduledScaler.Spec.Steps { step := scheduledScaler.Spec.Steps[key] - min, max := scalingstep.Parse(step) + min, max, cpuTarget := scalingstep.Parse(step) c.cronProxy.Push(stepsCron, step.Runat, func() { autoscaler, err = computeService.Autoscalers.Get(projectId, zone, scheduledScaler.Spec.Target.Name).Do() autoscaler.AutoscalingPolicy.MaxNumReplicas = int64(*max) autoscaler.AutoscalingPolicy.MinNumReplicas = int64(*min) + if cpuTarget != nil { + if autoscaler.AutoscalingPolicy.CpuUtilization == nil { + utilruntime.HandleError(fmt.Errorf( + "%s - IG autoscaler doesn't use CpuUtilization Policys", scheduledScaler.Spec.Target.Name)) + return + } + autoscaler.AutoscalingPolicy.CpuUtilization.UtilizationTarget = float64(*cpuTarget / 100.) + } _, err := computeService.Autoscalers.Update(projectId, zone, autoscaler).Do() if err != nil { utilruntime.HandleError(fmt.Errorf(