Skip to content

Commit

Permalink
Configurable container limit scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
johanneswuerbach committed May 13, 2020
1 parent 7b7d704 commit 2d63e89
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewProvider(calculator limitrange.LimitRangeCalculator,
}

// GetContainersResources returns the recommended resources for each container in the given pod in the same order they are specified in the pod.Spec.
func GetContainersResources(pod *core.Pod, podRecommendation vpa_types.RecommendedPodResources, limitRange *core.LimitRangeItem,
func GetContainersResources(pod *core.Pod, vpaResourcePolicy *vpa_types.PodResourcePolicy, podRecommendation vpa_types.RecommendedPodResources, limitRange *core.LimitRangeItem,
annotations vpa_api_util.ContainerToAnnotationsMap) []vpa_api_util.ContainerResources {
resources := make([]vpa_api_util.ContainerResources, len(pod.Spec.Containers))
for i, container := range pod.Spec.Containers {
Expand All @@ -60,17 +60,29 @@ func GetContainersResources(pod *core.Pod, podRecommendation vpa_types.Recommend
if limitRange != nil {
defaultLimit = limitRange.Default
}
proportionalLimits, limitAnnotations := vpa_api_util.GetProportionalLimit(container.Resources.Limits, container.Resources.Requests, recommendation.Target, defaultLimit)
if proportionalLimits != nil {
resources[i].Limits = proportionalLimits
if len(limitAnnotations) > 0 {
annotations[container.Name] = append(annotations[container.Name], limitAnnotations...)
containerLimitPolicy := GetContainerLimitPolicy(container.Name, vpaResourcePolicy)
if containerLimitPolicy == vpa_types.ContainerLimitScalingModeAuto {
proportionalLimits, limitAnnotations := vpa_api_util.GetProportionalLimit(container.Resources.Limits, container.Resources.Requests, recommendation.Target, defaultLimit)
if proportionalLimits != nil {
resources[i].Limits = proportionalLimits
if len(limitAnnotations) > 0 {
annotations[container.Name] = append(annotations[container.Name], limitAnnotations...)
}
}
}
}
return resources
}

// GetContainerLimitPolicy returns container limit scaling policy by container name
func GetContainerLimitPolicy(name string, vpaResourcePolicy *vpa_types.PodResourcePolicy) vpa_types.ContainerLimitScalingMode {
containerPolicy := vpa_api_util.GetContainerResourcePolicy(name, vpaResourcePolicy)
if containerPolicy == nil || containerPolicy.LimitMode == nil {
return vpa_types.ContainerLimitScalingModeAuto
}
return *containerPolicy.LimitMode
}

// GetContainersResourcesForPod returns recommended request for a given pod and associated annotations.
// The returned slice corresponds 1-1 to containers in the Pod.
func (p *recommendationProvider) GetContainersResourcesForPod(pod *core.Pod, vpa *vpa_types.VerticalPodAutoscaler) ([]vpa_api_util.ContainerResources, vpa_api_util.ContainerToAnnotationsMap, error) {
Expand All @@ -95,6 +107,10 @@ func (p *recommendationProvider) GetContainersResourcesForPod(pod *core.Pod, vpa
if err != nil {
return nil, nil, fmt.Errorf("error getting containerLimitRange: %s", err)
}
containerResources := GetContainersResources(pod, *recommendedPodResources, containerLimitRange, annotations)
var resourcePolicy *vpa_types.PodResourcePolicy
if vpa.Spec.UpdatePolicy == nil || vpa.Spec.UpdatePolicy.UpdateMode == nil || *vpa.Spec.UpdatePolicy.UpdateMode != vpa_types.UpdateModeOff {
resourcePolicy = vpa.Spec.ResourcePolicy
}
containerResources := GetContainersResources(pod, resourcePolicy, *recommendedPodResources, containerLimitRange, annotations)
return containerResources, annotations, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ func validateVPA(vpa *vpa_types.VerticalPodAutoscaler, isCreate bool) error {
return fmt.Errorf("max resource for %v is lower than min", resource)
}
}

limitMode := policy.LimitMode
if mode != nil && limitMode != nil {
if *mode == vpa_types.ContainerScalingModeOff && *limitMode == vpa_types.ContainerLimitScalingModeAuto {
return fmt.Errorf("Mode can not be Off when LimitScaling is Auto")
}
}
}
}

Expand Down
17 changes: 17 additions & 0 deletions vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ type ContainerResourcePolicy struct {
// (and possibly applied) by VPA.
// If not specified, the default of [ResourceCPU, ResourceMemory] will be used.
ControlledResources *[]v1.ResourceName `json:"controlledResources,omitempty" patchStrategy:"merge" protobuf:"bytes,5,rep,name=controlledResources"`

// Whether autoscaler limit scaling is enabled for the container. The default is "Auto".
// Enabling this requires the autoscaler to be enabled for the container
// +optional
LimitMode *ContainerLimitScalingMode `json:"limitMode,omitempty" protobuf:"bytes,5,rep,name=limitMode"`
}

const (
Expand All @@ -171,6 +176,18 @@ const (
ContainerScalingModeOff ContainerScalingMode = "Off"
)

// ContainerLimitScalingMode controls whether autoscaler limit scaling
// is enabled for a specific container.
type ContainerLimitScalingMode string

const (
// ContainerLimitScalingModeAuto means limits are scaled automatically.
// Limit is scaled proportionally to the request.
ContainerLimitScalingModeAuto ContainerLimitScalingMode = "Auto"
// ContainerLimitScalingModeOff means limit scaling is disabled for a container.
ContainerLimitScalingModeOff ContainerLimitScalingMode = "Off"
)

// VerticalPodAutoscalerStatus describes the runtime state of the autoscaler.
type VerticalPodAutoscalerStatus struct {
// The most recently computed amount of resources recommended by the
Expand Down

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

0 comments on commit 2d63e89

Please sign in to comment.