diff --git a/controllers/function_controller_test.go b/controllers/function_controller_test.go index 8f9c023f..d995fe95 100644 --- a/controllers/function_controller_test.go +++ b/controllers/function_controller_test.go @@ -286,7 +286,7 @@ func createFunction(function *v1alpha1.Function) { if len(function.Spec.Pod.BuiltinAutoscaler) > 0 { Expect(len(hpa.Spec.Metrics)).Should(Equal(len(function.Spec.Pod.BuiltinAutoscaler))) for _, rule := range function.Spec.Pod.BuiltinAutoscaler { - autoscaler, _ := spec.GetBuiltinAutoScaler(rule) + autoscaler, _ := spec.GetBuiltinAutoScaler(rule, function.Spec.Resources) Expect(autoscaler).Should(Not(BeNil())) Expect(hpa.Spec.Metrics).Should(ContainElement(autoscaler.Metrics()[0])) } diff --git a/controllers/spec/function.go b/controllers/spec/function.go index 738dd302..1fb7fd77 100644 --- a/controllers/spec/function.go +++ b/controllers/spec/function.go @@ -43,7 +43,7 @@ func MakeFunctionHPA(function *v1alpha1.Function) *autov2.HorizontalPodAutoscale Name: function.Name, APIVersion: function.APIVersion, } - return MakeHPA(objectMeta, targetRef, function.Spec.MinReplicas, function.Spec.MaxReplicas, function.Spec.Pod) + return MakeHPA(objectMeta, targetRef, function.Spec.MinReplicas, function.Spec.MaxReplicas, function.Spec.Pod, function.Spec.Resources) } func MakeFunctionService(function *v1alpha1.Function) *corev1.Service { diff --git a/controllers/spec/hpa.go b/controllers/spec/hpa.go index a3144cea..2e9ca8d3 100644 --- a/controllers/spec/hpa.go +++ b/controllers/spec/hpa.go @@ -86,31 +86,31 @@ func NewHPARuleAverageUtilizationMemoryPercent(memoryPercentage int32) BuiltinAu } } -func GetBuiltinAutoScaler(builtinRule v1alpha1.BuiltinHPARule) (BuiltinAutoScaler, int) { +func GetBuiltinAutoScaler(builtinRule v1alpha1.BuiltinHPARule, res corev1.ResourceRequirements) (BuiltinAutoScaler, int) { switch builtinRule { case v1alpha1.AverageUtilizationCPUPercent80: - return NewHPARuleAverageUtilizationCPUPercent(80), cpuRuleIdx + return NewHPARuleAverageUtilizationCPUPercent(getUtilizationPercentage(80, getResourceCpuFactor(res))), cpuRuleIdx case v1alpha1.AverageUtilizationCPUPercent50: - return NewHPARuleAverageUtilizationCPUPercent(50), cpuRuleIdx + return NewHPARuleAverageUtilizationCPUPercent(getUtilizationPercentage(50, getResourceCpuFactor(res))), cpuRuleIdx case v1alpha1.AverageUtilizationCPUPercent20: - return NewHPARuleAverageUtilizationCPUPercent(20), cpuRuleIdx + return NewHPARuleAverageUtilizationCPUPercent(getUtilizationPercentage(20, getResourceCpuFactor(res))), cpuRuleIdx case v1alpha1.AverageUtilizationMemoryPercent80: - return NewHPARuleAverageUtilizationMemoryPercent(80), memoryRuleIdx + return NewHPARuleAverageUtilizationMemoryPercent(getUtilizationPercentage(80, getResourceMemoryFactor(res))), memoryRuleIdx case v1alpha1.AverageUtilizationMemoryPercent50: - return NewHPARuleAverageUtilizationMemoryPercent(50), memoryRuleIdx + return NewHPARuleAverageUtilizationMemoryPercent(getUtilizationPercentage(50, getResourceMemoryFactor(res))), memoryRuleIdx case v1alpha1.AverageUtilizationMemoryPercent20: - return NewHPARuleAverageUtilizationMemoryPercent(20), memoryRuleIdx + return NewHPARuleAverageUtilizationMemoryPercent(getUtilizationPercentage(20, getResourceMemoryFactor(res))), memoryRuleIdx default: return nil, 2 } } // defaultHPAMetrics generates a default HPA Metrics settings based on CPU usage and utilized on 80%. -func defaultHPAMetrics() []autov2.MetricSpec { - return NewHPARuleAverageUtilizationCPUPercent(80).Metrics() +func defaultHPAMetrics(res corev1.ResourceRequirements) []autov2.MetricSpec { + return NewHPARuleAverageUtilizationCPUPercent(getUtilizationPercentage(80, getResourceCpuFactor(res))).Metrics() } -func makeDefaultHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int32, targetRef autov2.CrossVersionObjectReference) *autov2.HorizontalPodAutoscaler { +func makeDefaultHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int32, targetRef autov2.CrossVersionObjectReference, res corev1.ResourceRequirements) *autov2.HorizontalPodAutoscaler { return &autov2.HorizontalPodAutoscaler{ TypeMeta: metav1.TypeMeta{ APIVersion: "autoscaling/v2", @@ -121,7 +121,7 @@ func makeDefaultHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int3 ScaleTargetRef: targetRef, MinReplicas: &minReplicas, MaxReplicas: maxReplicas, - Metrics: defaultHPAMetrics(), + Metrics: defaultHPAMetrics(res), }, } } @@ -131,11 +131,11 @@ const ( memoryRuleIdx ) -func MakeMetricsFromBuiltinHPARules(builtinRules []v1alpha1.BuiltinHPARule) []autov2.MetricSpec { +func MakeMetricsFromBuiltinHPARules(builtinRules []v1alpha1.BuiltinHPARule, res corev1.ResourceRequirements) []autov2.MetricSpec { isRuleExists := map[int]bool{} metrics := []autov2.MetricSpec{} for _, r := range builtinRules { - s, idx := GetBuiltinAutoScaler(r) + s, idx := GetBuiltinAutoScaler(r, res) if s != nil { if isRuleExists[idx] { continue @@ -147,8 +147,8 @@ func MakeMetricsFromBuiltinHPARules(builtinRules []v1alpha1.BuiltinHPARule) []au return metrics } -func makeBuiltinHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int32, targetRef autov2.CrossVersionObjectReference, builtinRules []v1alpha1.BuiltinHPARule) *autov2.HorizontalPodAutoscaler { - metrics := MakeMetricsFromBuiltinHPARules(builtinRules) +func makeBuiltinHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int32, targetRef autov2.CrossVersionObjectReference, builtinRules []v1alpha1.BuiltinHPARule, res corev1.ResourceRequirements) *autov2.HorizontalPodAutoscaler { + metrics := MakeMetricsFromBuiltinHPARules(builtinRules, res) return &autov2.HorizontalPodAutoscaler{ TypeMeta: metav1.TypeMeta{ APIVersion: "autoscaling/v2", @@ -182,11 +182,33 @@ func makeHPA(objectMeta *metav1.ObjectMeta, minReplicas, maxReplicas int32, podP } } -func MakeHPA(objectMeta *metav1.ObjectMeta, targetRef autov2.CrossVersionObjectReference, minReplicas, maxReplicas *int32, policy v1alpha1.PodPolicy) *autov2.HorizontalPodAutoscaler { +func MakeHPA(objectMeta *metav1.ObjectMeta, targetRef autov2.CrossVersionObjectReference, minReplicas, maxReplicas *int32, policy v1alpha1.PodPolicy, res corev1.ResourceRequirements) *autov2.HorizontalPodAutoscaler { if isBuiltinHPAEnabled(minReplicas, maxReplicas, policy) { - return makeBuiltinHPA(objectMeta, *minReplicas, *maxReplicas, targetRef, policy.BuiltinAutoscaler) + return makeBuiltinHPA(objectMeta, *minReplicas, *maxReplicas, targetRef, policy.BuiltinAutoscaler, res) } else if !isDefaultHPAEnabled(minReplicas, maxReplicas, policy) { return makeHPA(objectMeta, *minReplicas, *maxReplicas, policy, targetRef) } - return makeDefaultHPA(objectMeta, *minReplicas, *maxReplicas, targetRef) + return makeDefaultHPA(objectMeta, *minReplicas, *maxReplicas, targetRef, res) +} + +func getResourceCpuFactor(res corev1.ResourceRequirements) float64 { + if res.Requests.Cpu() != nil && res.Limits.Cpu() != nil { + if !res.Requests.Cpu().IsZero() && !res.Limits.Cpu().IsZero() { + return float64(res.Limits.Cpu().MilliValue()) / float64(res.Requests.Cpu().MilliValue()) + } + } + return 1.0 +} + +func getResourceMemoryFactor(res corev1.ResourceRequirements) float64 { + if res.Requests.Memory() != nil && res.Limits.Memory() != nil { + if !res.Requests.Memory().IsZero() && !res.Limits.Memory().IsZero() { + return float64(res.Limits.Memory().Value()) / float64(res.Requests.Memory().Value()) + } + } + return 1.0 +} + +func getUtilizationPercentage(val int32, factor float64) int32 { + return int32(float64(val) * factor) } diff --git a/controllers/spec/sink.go b/controllers/spec/sink.go index 81e37d5e..1735442c 100644 --- a/controllers/spec/sink.go +++ b/controllers/spec/sink.go @@ -40,7 +40,7 @@ func MakeSinkHPA(sink *v1alpha1.Sink) *autov2.HorizontalPodAutoscaler { Name: sink.Name, APIVersion: sink.APIVersion, } - return MakeHPA(objectMeta, targetRef, sink.Spec.MinReplicas, sink.Spec.MaxReplicas, sink.Spec.Pod) + return MakeHPA(objectMeta, targetRef, sink.Spec.MinReplicas, sink.Spec.MaxReplicas, sink.Spec.Pod, sink.Spec.Resources) } func MakeSinkService(sink *v1alpha1.Sink) *corev1.Service { diff --git a/controllers/spec/source.go b/controllers/spec/source.go index b10e140a..2b38a24b 100644 --- a/controllers/spec/source.go +++ b/controllers/spec/source.go @@ -41,7 +41,7 @@ func MakeSourceHPA(source *v1alpha1.Source) *autov2.HorizontalPodAutoscaler { Name: source.Name, APIVersion: source.APIVersion, } - return MakeHPA(objectMeta, targetRef, source.Spec.MinReplicas, source.Spec.MaxReplicas, source.Spec.Pod) + return MakeHPA(objectMeta, targetRef, source.Spec.MinReplicas, source.Spec.MaxReplicas, source.Spec.Pod, source.Spec.Resources) } func MakeSourceService(source *v1alpha1.Source) *corev1.Service {