mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Adds validation rules and proper defaults
This commit is contained in:
parent
141eaf79ee
commit
5c70cda6e5
@ -18,11 +18,52 @@ package v2beta2
|
||||
|
||||
import (
|
||||
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
)
|
||||
|
||||
var (
|
||||
// These constants repeats previous HPA behavior
|
||||
scaleUpLimitPercent int32 = 100
|
||||
scaleUpLimitMinimumPods int32 = 4
|
||||
scaleUpPeriod int32 = 15
|
||||
scaleUpStabilizationSeconds int32
|
||||
maxPolicy = autoscalingv2beta2.MaxPolicySelect
|
||||
defaultHPAScaleUpRules = autoscalingv2beta2.HPAScalingRules{
|
||||
StabilizationWindowSeconds: &scaleUpStabilizationSeconds,
|
||||
SelectPolicy: &maxPolicy,
|
||||
Policies: []autoscalingv2beta2.HPAScalingPolicy{
|
||||
{
|
||||
Type: autoscalingv2beta2.PodsScalingPolicy,
|
||||
Value: scaleUpLimitMinimumPods,
|
||||
PeriodSeconds: scaleUpPeriod,
|
||||
},
|
||||
{
|
||||
Type: autoscalingv2beta2.PercentScalingPolicy,
|
||||
Value: scaleUpLimitPercent,
|
||||
PeriodSeconds: scaleUpPeriod,
|
||||
},
|
||||
},
|
||||
}
|
||||
scaleDownPeriod int32 = 15
|
||||
// Currently we can set the downscaleStabilizationWindow from the command line
|
||||
// So we can not rewrite the command line option from here
|
||||
scaleDownStabilizationSeconds *int32 = nil
|
||||
scaleDownLimitPercent int32 = 100
|
||||
defaultHPAScaleDownRules = autoscalingv2beta2.HPAScalingRules{
|
||||
StabilizationWindowSeconds: scaleDownStabilizationSeconds,
|
||||
SelectPolicy: &maxPolicy,
|
||||
Policies: []autoscalingv2beta2.HPAScalingPolicy{
|
||||
{
|
||||
Type: autoscalingv2beta2.PercentScalingPolicy,
|
||||
Value: scaleDownLimitPercent,
|
||||
PeriodSeconds: scaleDownPeriod,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
@ -48,4 +89,46 @@ func SetDefaults_HorizontalPodAutoscaler(obj *autoscalingv2beta2.HorizontalPodAu
|
||||
},
|
||||
}
|
||||
}
|
||||
SetDefaults_HorizontalPodAutoscalerBehavior(obj)
|
||||
}
|
||||
|
||||
// SetDefaults_HorizontalPodAutoscalerBehavior fills the behavior if it is not null
|
||||
func SetDefaults_HorizontalPodAutoscalerBehavior(obj *autoscalingv2beta2.HorizontalPodAutoscaler) {
|
||||
// if behavior is specified, we should fill all the 'nil' values with the default ones
|
||||
if obj.Spec.Behavior != nil {
|
||||
obj.Spec.Behavior.ScaleUp = GenerateHPAScaleUpRules(obj.Spec.Behavior.ScaleUp)
|
||||
obj.Spec.Behavior.ScaleDown = GenerateHPAScaleDownRules(obj.Spec.Behavior.ScaleDown)
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateHPAScaleUpRules returns a fully-initialized HPAScalingRules value
|
||||
// We guarantee that no pointer in the structure will have the 'nil' value
|
||||
func GenerateHPAScaleUpRules(scalingRules *autoscalingv2beta2.HPAScalingRules) *autoscalingv2beta2.HPAScalingRules {
|
||||
defaultScalingRules := defaultHPAScaleUpRules.DeepCopy()
|
||||
return copyHPAScalingRules(scalingRules, defaultScalingRules)
|
||||
}
|
||||
|
||||
// GenerateHPAScaleDownRules returns a fully-initialized HPAScalingRules value
|
||||
// We guarantee that no pointer in the structure will have the 'nil' value
|
||||
// EXCEPT StabilizationWindowSeconds, for reasoning check the comment for defaultHPAScaleDownRules
|
||||
func GenerateHPAScaleDownRules(scalingRules *autoscalingv2beta2.HPAScalingRules) *autoscalingv2beta2.HPAScalingRules {
|
||||
defaultScalingRules := defaultHPAScaleDownRules.DeepCopy()
|
||||
return copyHPAScalingRules(scalingRules, defaultScalingRules)
|
||||
}
|
||||
|
||||
// copyHPAScalingRules copies all non-`nil` fields in HPA constraint structure
|
||||
func copyHPAScalingRules(from, to *autoscalingv2beta2.HPAScalingRules) *autoscalingv2beta2.HPAScalingRules {
|
||||
if from == nil {
|
||||
return to
|
||||
}
|
||||
if from.SelectPolicy != nil {
|
||||
to.SelectPolicy = from.SelectPolicy
|
||||
}
|
||||
if from.StabilizationWindowSeconds != nil {
|
||||
to.StabilizationWindowSeconds = from.StabilizationWindowSeconds
|
||||
}
|
||||
if from.Policies != nil {
|
||||
to.Policies = from.Policies
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
@ -30,6 +30,13 @@ import (
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxPeriodSeconds is the largest allowed scaling policy period (in seconds)
|
||||
MaxPeriodSeconds int32 = 1800
|
||||
// MaxStabilizationWindowSeconds is the largest allowed stabilization window (in seconds)
|
||||
MaxStabilizationWindowSeconds int32 = 3600
|
||||
)
|
||||
|
||||
// ValidateScale validates a Scale and returns an ErrorList with any errors.
|
||||
func ValidateScale(scale *autoscaling.Scale) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
@ -65,6 +72,9 @@ func validateHorizontalPodAutoscalerSpec(autoscaler autoscaling.HorizontalPodAut
|
||||
if refErrs := validateMetrics(autoscaler.Metrics, fldPath.Child("metrics"), autoscaler.MinReplicas); len(refErrs) > 0 {
|
||||
allErrs = append(allErrs, refErrs...)
|
||||
}
|
||||
if refErrs := validateBehavior(autoscaler.Behavior, fldPath.Child("behavior")); len(refErrs) > 0 {
|
||||
allErrs = append(allErrs, refErrs...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@ -165,6 +175,70 @@ func validateMetrics(metrics []autoscaling.MetricSpec, fldPath *field.Path, minR
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateBehavior(behavior *autoscaling.HorizontalPodAutoscalerBehavior, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if behavior != nil {
|
||||
if scaleUpErrs := validateScalingRules(behavior.ScaleUp, fldPath.Child("scaleUp")); len(scaleUpErrs) > 0 {
|
||||
allErrs = append(allErrs, scaleUpErrs...)
|
||||
}
|
||||
if scaleDownErrs := validateScalingRules(behavior.ScaleDown, fldPath.Child("scaleDown")); len(scaleDownErrs) > 0 {
|
||||
allErrs = append(allErrs, scaleDownErrs...)
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validSelectPolicyTypes = sets.NewString(string(autoscaling.MaxPolicySelect), string(autoscaling.MinPolicySelect), string(autoscaling.DisabledPolicySelect))
|
||||
var validSelectPolicyTypesList = validSelectPolicyTypes.List()
|
||||
|
||||
func validateScalingRules(rules *autoscaling.HPAScalingRules, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if rules != nil {
|
||||
if rules.StabilizationWindowSeconds != nil && *rules.StabilizationWindowSeconds < 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("stabilizationWindowSeconds"), rules.StabilizationWindowSeconds, "must be greater than or equal to zero"))
|
||||
}
|
||||
if rules.StabilizationWindowSeconds != nil && *rules.StabilizationWindowSeconds > MaxStabilizationWindowSeconds {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("stabilizationWindowSeconds"), rules.StabilizationWindowSeconds,
|
||||
fmt.Sprintf("must be less than or equal to %v", MaxStabilizationWindowSeconds)))
|
||||
}
|
||||
if rules.SelectPolicy != nil && !validSelectPolicyTypes.Has(string(*rules.SelectPolicy)) {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("selectPolicy"), rules.SelectPolicy, validSelectPolicyTypesList))
|
||||
}
|
||||
policiesPath := fldPath.Child("policies")
|
||||
if len(rules.Policies) == 0 {
|
||||
allErrs = append(allErrs, field.Required(policiesPath, "must specify at least one Policy"))
|
||||
}
|
||||
for i, policy := range rules.Policies {
|
||||
idxPath := policiesPath.Index(i)
|
||||
if policyErrs := validateScalingPolicy(policy, idxPath); len(policyErrs) > 0 {
|
||||
allErrs = append(allErrs, policyErrs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validPolicyTypes = sets.NewString(string(autoscaling.PodsScalingPolicy), string(autoscaling.PercentScalingPolicy))
|
||||
var validPolicyTypesList = validPolicyTypes.List()
|
||||
|
||||
func validateScalingPolicy(policy autoscaling.HPAScalingPolicy, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if policy.Type != autoscaling.PodsScalingPolicy && policy.Type != autoscaling.PercentScalingPolicy {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), policy.Type, validPolicyTypesList))
|
||||
}
|
||||
if policy.Value <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("value"), policy.Value, "must be greater than zero"))
|
||||
}
|
||||
if policy.PeriodSeconds <= 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("periodSeconds"), policy.PeriodSeconds, "must be greater than zero"))
|
||||
}
|
||||
if policy.PeriodSeconds > MaxPeriodSeconds {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("periodSeconds"), policy.PeriodSeconds,
|
||||
fmt.Sprintf("must be less than or equal to %v", MaxPeriodSeconds)))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var validMetricSourceTypes = sets.NewString(string(autoscaling.ObjectMetricSourceType), string(autoscaling.PodsMetricSourceType), string(autoscaling.ResourceMetricSourceType), string(autoscaling.ExternalMetricSourceType))
|
||||
var validMetricSourceTypesList = validMetricSourceTypes.List()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user