Add support for custom metrics for HPA (#2423)

* Add support for custom metrics for HPA
* Cleanup TargetCPUPercent references from possible places
* HPA v2beta has 80% default  cpu limit if not set

Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
This commit is contained in:
Sanket Sudake
2022-05-09 17:16:34 +05:30
committed by GitHub
parent 925f817e42
commit 39dd65b224
13 changed files with 496 additions and 77 deletions
+19 -4
View File
@@ -17,6 +17,7 @@ limitations under the License.
package v1
import (
asv2beta2 "k8s.io/api/autoscaling/v2beta2"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -459,22 +460,36 @@ type (
// +optional
ExecutorType ExecutorType `json:"ExecutorType"`
// +optional
// This is only for newdeploy to set up minimum replicas of deployment.
// +optional
MinScale int `json:"MinScale"`
// +optional
// This is only for newdeploy to set up maximum replicas of deployment.
// +optional
MaxScale int `json:"MaxScale"`
// Deprecated: use hpaMetrics instead.
// This is only for executor type newdeploy and container to set up target CPU utilization of HPA.
// Applicable for executor type newdeploy and container.
// +optional
// This is only for newdeploy to set up target CPU utilization of HPA.
TargetCPUPercent int `json:"TargetCPUPercent"`
// +optional
// This is the timeout setting for executor to wait for pod specialization.
// +optional
SpecializationTimeout int `json:"SpecializationTimeout"`
// hpaMetrics is the list of metrics used to determine the desired replica count of the Deployment
// created for the function.
// Applicable for executor type newdeploy and container.
// +optional
Metrics []asv2beta2.MetricSpec `json:"hpaMetrics,omitempty"`
// hpaBehavior is the behavior of HPA when scaling in up/down direction.
// Applicable for executor type newdeploy and container.
// +optional
Behavior *asv2beta2.HorizontalPodAutoscalerBehavior `json:"hpaBehavior,omitempty"`
}
// FunctionReferenceType refers to type of Function
FunctionReferenceType string
+4 -3
View File
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"net/http"
"reflect"
"regexp"
"strings"
@@ -270,7 +271,7 @@ func (spec FunctionSpec) Validate() error {
result = multierror.Append(result, c.Validate())
}
if spec.InvokeStrategy != (InvokeStrategy{}) {
if !reflect.DeepEqual(spec.InvokeStrategy, InvokeStrategy{}) {
result = multierror.Append(result, spec.InvokeStrategy.Validate())
}
@@ -309,7 +310,7 @@ func (es ExecutionStrategy) Validate() error {
result = multierror.Append(result, MakeValidationErr(ErrorUnsupportedType, "ExecutionStrategy.ExecutorType", es.ExecutorType, "not a valid executor type"))
}
if es.ExecutorType == ExecutorTypeNewdeploy {
if es.ExecutorType == ExecutorTypeNewdeploy || es.ExecutorType == ExecutorTypeContainer {
if es.MinScale < 0 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MinScale", es.MinScale, "minimum scale must be greater than or equal to 0"))
}
@@ -322,7 +323,7 @@ func (es ExecutionStrategy) Validate() error {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.MaxScale", es.MaxScale, "maximum scale must be greater than or equal to minimum scale"))
}
if es.TargetCPUPercent <= 0 || es.TargetCPUPercent > 100 {
if es.TargetCPUPercent < 0 || es.TargetCPUPercent > 100 {
result = multierror.Append(result, MakeValidationErr(ErrorInvalidValue, "ExecutionStrategy.TargetCPUPercent", es.TargetCPUPercent, "TargetCPUPercent must be a value between 1 - 100"))
}
+15 -2
View File
@@ -22,6 +22,7 @@ limitations under the License.
package v1
import (
v2beta2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
@@ -313,6 +314,18 @@ func (in *EnvironmentSpec) DeepCopy() *EnvironmentSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExecutionStrategy) DeepCopyInto(out *ExecutionStrategy) {
*out = *in
if in.Metrics != nil {
in, out := &in.Metrics, &out.Metrics
*out = make([]v2beta2.MetricSpec, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Behavior != nil {
in, out := &in.Behavior, &out.Behavior
*out = new(v2beta2.HorizontalPodAutoscalerBehavior)
(*in).DeepCopyInto(*out)
}
return
}
@@ -442,7 +455,7 @@ func (in *FunctionSpec) DeepCopyInto(out *FunctionSpec) {
copy(*out, *in)
}
in.Resources.DeepCopyInto(&out.Resources)
out.InvokeStrategy = in.InvokeStrategy
in.InvokeStrategy.DeepCopyInto(&out.InvokeStrategy)
if in.IdleTimeout != nil {
in, out := &in.IdleTimeout, &out.IdleTimeout
*out = new(int)
@@ -580,7 +593,7 @@ func (in *IngressConfig) DeepCopy() *IngressConfig {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InvokeStrategy) DeepCopyInto(out *InvokeStrategy) {
*out = *in
out.ExecutionStrategy = in.ExecutionStrategy
in.ExecutionStrategy.DeepCopyInto(&out.ExecutionStrategy)
return
}
@@ -143,8 +143,10 @@ var map_ExecutionStrategy = map[string]string{
"ExecutorType": "ExecutorType is the executor type of function used. Defaults to \"poolmgr\".\n\nAvailable value:\n - poolmgr\n - newdeploy\n - container",
"MinScale": "This is only for newdeploy to set up minimum replicas of deployment.",
"MaxScale": "This is only for newdeploy to set up maximum replicas of deployment.",
"TargetCPUPercent": "This is only for newdeploy to set up target CPU utilization of HPA.",
"TargetCPUPercent": "Deprecated: use hpaMetrics instead. This is only for executor type newdeploy and container to set up target CPU utilization of HPA. Applicable for executor type newdeploy and container.",
"SpecializationTimeout": "This is the timeout setting for executor to wait for pod specialization.",
"hpaMetrics": "hpaMetrics is the list of metrics used to determine the desired replica count of the Deployment created for the function. Applicable for executor type newdeploy and container.",
"hpaBehavior": "hpaBehavior is the behavior of HPA when scaling in up/down direction. Applicable for executor type newdeploy and container.",
}
func (ExecutionStrategy) SwaggerDoc() map[string]string {