Skip to content

Commit

Permalink
Add Vertical Pod Autoscaler support (#183)
Browse files Browse the repository at this point in the history
* feat: add Vertical Pod Autoscaler

* docs: add VPA section

* feat: Add tests for VPA

* feat: add support for k8s < 1.25 for VPA

* fix(vpa): fix typos

* fix: typos
  • Loading branch information
mateimicu authored Feb 8, 2024
1 parent 5ee6616 commit a6533b9
Show file tree
Hide file tree
Showing 5 changed files with 403 additions and 0 deletions.
39 changes: 39 additions & 0 deletions charts/k8s-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ The following resources will be deployed with this Helm Chart, depending on whic
- `Horizontal Pod Autoscaler`: The `Horizontal Pod Autoscaler` automatically scales the number of pods in a replication
controller, deployment, replica set or stateful set based on observed CPU or memory utilization.
Created only if the user sets `horizontalPodAutoscaler.enabled = true`.
- `Vertical Pod Autoscaler`: The `Vertical Pod Autoscaler` can offer recommendations or change the CPU and memory for both
requests and limits based on specified configuration.
Created only if the user sets `verticalPodAutoscaler.enabled = true`.
- `PodDisruptionBudget`: The `PodDisruptionBudget` resource that specifies a disruption budget for the `Pods` managed by
the `Deployment`. This manages how many pods can be disrupted by a voluntary disruption (e.g
node maintenance). Created if you specify a non-zero value for the `minPodsAvailable` input
Expand Down Expand Up @@ -1218,3 +1221,39 @@ You can learn more about using private registries with Kubernetes in [the offici
documentation](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry).

back to [root README](/README.adoc#day-to-day-operations)

## How to enable Vertical Pod Autoscaler ?

[Vertical Pod Auto scaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) is used to dynamically change
the requests and limits of running pods. It should **not be used** in combination with Horizontal Pod Autoscaler.

First you need to install it in the cluster by following the [installation guide](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#installation)


VPA has the following modes:

* `Off` where right sizing recommendation will be generated but it won't change any existing pods
* `Initial` when a new pod is created, it will be configured with the limits/requests that are considered appropriate
* `Recreate` every time a new suitable sizing event happens (when better requests/limits are computed) pods may be evicted to apply the new configuration
* `Auto` it is the same as `Recreate`, but in the future, it may support restart-free updates

By default, the VPA is configured to generate recommendations only. The following configuration enables it:
```yaml
verticalPodAutoscaler:
enabled: true
```

To see the recommendation you can run
```bash
~ $ kubectl get vpa
NAME MODE CPU MEM PROVIDED AGE
release-nginx Auto 24m
~ $ kubectl describe vpa release-nginx
```

You can learn more about using Vertical Pod Autoscaler [the official
documentation](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler).

back to [root README](/README.adoc#day-to-day-operations)
9 changes: 9 additions & 0 deletions charts/k8s-service/templates/_capabilities_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,12 @@
{{- print "autoscaling/v2beta2" -}}
{{- end -}}
{{- end -}}

{{/* Get VertialPodAutoscaler API Version */}}
{{- define "gruntwork.verticalPodAutoscaler.apiVersion" -}}
{{- if and (.Capabilities.APIVersions.Has "autoscaling.k8s.io/v1") (semverCompare ">= 1.23-0" (include "gruntwork.kubeVersion" .)) -}}
{{- print "autoscaling.k8s.io/v1" -}}
{{- else -}}
{{- print "autoscaling.k8s.io/v1beta2" -}}
{{- end -}}
{{- end -}}
40 changes: 40 additions & 0 deletions charts/k8s-service/templates/verticalpodautoscaler.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{{- if .Values.verticalPodAutoscaler.enabled }}
apiVersion: {{ include "gruntwork.verticalPodAutoscaler.apiVersion" . }}
kind: VerticalPodAutoscaler
metadata:
name: {{ include "k8s-service.fullname" . }}
namespace: {{ $.Release.Namespace }}
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "k8s-service.fullname" . }}
updatePolicy:
updateMode: {{ .Values.verticalPodAutoscaler.updateMode | quote }}
minReplicas: {{ .Values.verticalPodAutoscaler.minReplicas }}
resourcePolicy:
containerPolicies:
- containerName: {{ include "k8s-service.fullname" . }}
{{- if .Values.verticalPodAutoscaler.mainContainerResourcePolicy.minAllowed }}
minAllowed:
{{- toYaml .Values.verticalPodAutoscaler.mainContainerResourcePolicy.minAllowed | nindent 8 }}
{{- end }}

{{- if .Values.verticalPodAutoscaler.mainContainerResourcePolicy.maxAllowed }}
maxAllowed:
{{- toYaml .Values.verticalPodAutoscaler.mainContainerResourcePolicy.maxAllowed | nindent 8 }}
{{- end }}

{{- if .Values.verticalPodAutoscaler.mainContainerResourcePolicy.controlledResources }}
controlledResources:
{{- toYaml .Values.verticalPodAutoscaler.mainContainerResourcePolicy.controlledResources | nindent 8 }}
{{- end }}

{{- if .Values.verticalPodAutoscaler.mainContainerResourcePolicy.controlledValues }}
controlledValues: {{ .Values.verticalPodAutoscaler.mainContainerResourcePolicy.controlledValues }}
{{- end }}

{{- if .Values.verticalPodAutoscaler.extraResourcePolicy }}
{{- toYaml .Values.verticalPodAutoscaler.extraResourcePolicy | nindent 4 }}
{{- end }}
{{- end }}
153 changes: 153 additions & 0 deletions charts/k8s-service/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,159 @@ horizontalPodAutoscaler:
minReplicas: 1
maxReplicas: 10

# verticalPodAutoscaler is a map that configures the Vertical Pod Autoscaler information for this pod
# The expected keys of vpa are:
# - enabled (bool) : Whether or not Vertical Pod Autoscaler should be created, if false the
# Vertical Pod Autoscaler will not be created
# - updateMode (string) : Controls when autoscaler applies changes to the pod resources. Possible values:
# * "Off" Changes are only recommended but the pods are not changed
# * "Initial" Changes are applied at pod creation only
# * "Recreate" Pods will be evicted to apply new scaling settings
# * "Auto" Currently it is equivalent with "Recreate" but in the future
# it will update pods without eviction
# - minReplicas (int) : Minimal number of replicas which need to be alive for Updater to attempt
# pod eviction (pending other checks like PDB).
# - evictionRequirements (list) : Requirements that need to be true for an eviction event to be attempted
# - mainContainerResourcePolicy (object) : Configuration for the main container
# - extraResourcePolicy (list) : Configuration injected. Can be used if other sideCarContainers are used
#
#
# The expected attributes for objects of type evictionRequirement:
# - resource (list) : A list of one or more resources that the condition applies to. These resources can be "cpu", "memory", etc.
# - changeRequirement (string) : The type of change required. Possible options:
# * "TargetHigherThanRequests" - The eviction is attempted when the new target is higher than the current requests,
# i.e., the Pod is scaled up.
# * "TargetLowerThanRequests" - The eviction is attempted if the new target is lower than the current requests,
# i.e., the Pod is scaled down.
#
# The expected attributes for `mainContainerResourcePolicy` object:
# - mode (string) : The mode of operation. Can be "Off", "Auto"
# - minAllowed (object) : The minimum resources allowed for the container.
# - maxAllowed (object) : The maximum resources allowed for the container.
# - controlledResources (list) : The list of resources that the policy can control. Can include "cpu" and "memory".
# - controlledValues (string) : The values that the policy can control. Can be "RequestsOnly" or "RequestsAndLimits".
#
#
# The expected attributes for `extraResourcePolicy` list of objects:
# - containerName (string) : The name of the container that the policy applies to.
# - mode (string) : The mode of operation. Can be "Off", "Auto"
# - minAllowed (object) : The minimum resources allowed for the container.
# - maxAllowed (object) : The maximum resources allowed for the container.
# - controlledResources (list) : The list of resources that the policy can control. Can include "cpu" and "memory".
# - controlledValues (string) : The values that the policy can control. Can be "RequestsOnly" or "RequestsAndLimits".

# The expected attributes for `minAllowed` and `maxAllowed` objects:
# - cpu (string):
# - memory (string):
#
#
# Example configuration that uses all the features
#
# ```yaml
# verticalPodAutoscaler:
# enabled: true
# updateMode: "Auto"
# minPodsAvailable: 2
# evictionRequirements:
# # Allow scale up events if the CPU needs adjusting
# - resource: ["cpu"]
# changeRequirement: TargetHigherThanRequests
#
# # Allow scale up events if the Memory needs adjusting
# - resource: ["memory"]
# changeRequirement: TargetHigherThanRequests
#
# # Allow scale down events if both the CPU and memory need adjusting
# - resource: ["cpu", "memory"]
# changeRequirement: TargetLowerThanRequests
# mainContainerResourcePolicy:
# # Enable scaling for the main container
# mode: "Auto"
# minAllowed:
# cpu: "0.2"
# memory: "200Mi"
# maxAllowed:
# cpu: "1"
# memory: "500Mi"
# # Scale both the CPU and Memory of the container
# controlledResources: ["cpu", "memory"]
# # Adjust both requests and limits
# controlledValues: "RequestsAndLimits"
# # Configuration for other containers (e.g. when sideCarContainers are used)
# extraResourcePolicy:
# # Disable the scaling for all other containers by default
# - containerName: "*"
# mode: "Off"
# # Assuming we have a sideCarContainers called "proxy"
# - containerName: "proxy"
# # Enable scaling actions
# mode: "Auto"
# minAllowed:
# cpu: "0.2"
# maxAllowed:
# cpu: "1"
# # Only scale the CPU
# controlledResources: ["cpu"]
# # Scale only the requests
# controlledValues: "RequestsOnly"
# ```
#
#
# This will result in the following configuration
#
# ```yaml
# apiVersion: autoscaling.k8s.io/v1
# kind: VerticalPodAutoscaler
# metadata:
# name: XXXX
# spec:
# resourcePolicy:
# containerPolicies:
# - containerName: XXXX
# controlledResources:
# - cpu
# - memory
# controlledValues: RequestsAndLimits
# maxAllowed:
# cpu: "1"
# memory: 500Mi
# minAllowed:
# cpu: "0.2"
# memory: 200Mi
# - containerName: ""
# mode: "Off"
# - containerName: proxy
# controlledResources:
# - cpu
# controlledValues: RequestsOnly
# maxAllowed:
# cpu: "1"
# minAllowed:
# cpu: "0.2"
# mode: Auto
# targetRef:
# apiVersion: apps/v1
# kind: Deployment
# name: m1-nginx
# updatePolicy:
# minReplicas: 2
# updateMode: Auto
#```
#
# The default config will not create the Vertical Pod Autoscaler by setting enabled = false,
# the default values are set so if enabled is true the verticalPodAutoscaler has valid values
# and is running in recommendation only mode
verticalPodAutoscaler:
enabled: false
updateMode: "Off"
minReplicas: 2
mainContainerResourcePolicy:
controlledResources: ["cpu", "memory"]
controlledValues: "RequestsAndLimits"
extraResourcePolicy:
- containerName: ""
mode: "Off"

# customResources is a map that lets you define Kubernetes resources you want installed and configured as part of this chart.
# The expected keys of customResources are:
# - enabled (bool) : Whether or not the provided custom resource definitions should be created.
Expand Down
Loading

0 comments on commit a6533b9

Please sign in to comment.