// Module included in the following assemblies:
//
// * nodes/nodes-vertical-autoscaler.adoc

:_mod-docs-content-type: CONCEPT
[id="nodes-pods-vertical-autoscaler-using-about_{context}"]
= About using the Vertical Pod Autoscaler Operator

[role="_abstract"]
To use the {product-title} Vertical Pod Autoscaler Operator (VPA) to help you maintain the optimal CPU and memory usage for your pods, you create a VPA custom resource (CR) for a workload object in your cluster. 

The VPA learns and applies the optimal CPU and memory resources for the pods associated with that workload object. You can use a VPA with a deployment, stateful set, job, daemon set, replica set, or replication controller workload object. The VPA CR must be in the same project as the pods that you want to check.

You use the VPA CR to associate a workload object and specify the mode that the VPA operates in. You can also use the CR to opt-out certain containers from VPA evaluation and updates.

For example, a pod has the following limits and requests:

[source,yaml]
----
resources:
  limits:
    cpu: 1
    memory: 500Mi
  requests:
    cpu: 500m
    memory: 100Mi
----

After creating a VPA that is set to `Recreate`, the VPA learns the resource usage and deletes the pod. When redeployed, the pod uses the new resource limits and requests:

[source,yaml]
----
resources:
  limits:
    cpu: 50m
    memory: 1250Mi
  requests:
    cpu: 25m
    memory: 262144k
----

You can view the VPA recommendations by using the following command:

[source,terminal]
----
$ oc get vpa <vpa-name> --output yaml
----

After a few minutes, the output shows the recommendations for CPU and memory requests, similar to the following:

.Example output
[source,yaml]
----
...
status:
...
  recommendation:
    containerRecommendations:
    - containerName: frontend
      lowerBound:
        cpu: 25m
        memory: 262144k
      target:
        cpu: 25m
        memory: 262144k
      uncappedTarget:
        cpu: 25m
        memory: 262144k
      upperBound:
        cpu: 262m
        memory: "274357142"
    - containerName: backend
      lowerBound:
        cpu: 12m
        memory: 131072k
      target:
        cpu: 12m
        memory: 131072k
      uncappedTarget:
        cpu: 12m
        memory: 131072k
      upperBound:
        cpu: 476m
        memory: "498558823"
...
----

The output shows the recommended resources, `target`, the minimum recommended resources, `lowerBound`, the highest recommended resources, `upperBound`, and the most recent  resource recommendations, `uncappedTarget`.

The VPA uses the `lowerBound` and `upperBound` values to determine if a pod needs updating. If a pod has resource requests less than the `lowerBound` values or more than the `upperBound` values, the VPA terminates and recreates the pod with the `target` values.

[id="nodes-pods-vertical-autoscaler-using-one-pod_{context}"]
== Changing the VPA minimum value

By default, workload objects must specify a minimum of two replicas in order for the VPA to automatically delete and update their pods. As a result, workload objects that specify fewer than two replicas are not automatically acted upon by the VPA. The VPA does update new pods from these workload objects if a process external to the VPA restarts the pods. You can change this cluster-wide minimum value by modifying the `minReplicas` parameter in the `VerticalPodAutoscalerController` custom resource (CR).

For example, if you set `minReplicas` to `3`, the VPA does not delete and update pods for workload objects that specify fewer than three replicas.

[NOTE]
====
If you set `minReplicas` to `1`, the VPA can delete the only pod for a workload object that specifies only one replica. Use this setting with one-replica objects only if your workload can tolerate downtime whenever the VPA deletes a pod to adjust its resources. To avoid unwanted downtime with one-replica objects, configure the VPA CRs with the `podUpdatePolicy` set to `Initial`, which automatically updates the pod only when a process external to the VPA restarts, or `Off`, which you can use to update the pod manually at an appropriate time for your application.
====

.Example `VerticalPodAutoscalerController` object
[source,yaml]
----
apiVersion: autoscaling.openshift.io/v1
kind: VerticalPodAutoscalerController
metadata:
  creationTimestamp: "2021-04-21T19:29:49Z"
  generation: 2
  name: default
  namespace: openshift-vertical-pod-autoscaler
  resourceVersion: "142172"
  uid: 180e17e9-03cc-427f-9955-3b4d7aeb2d59
spec:
  minReplicas: 3
  podMinCPUMillicores: 25
  podMinMemoryMb: 250
  recommendationOnly: false
  safetyMarginFraction: 0.15
----
where:

`spec.minReplicas`:: Specifies the minimum number of replicas in a workload object for the VPA to act on. Any objects with replicas fewer than the minimum are not automatically deleted by the VPA.

[id="nodes-pods-vertical-autoscaler-using-auto_{context}"]
== Automatically applying VPA recommendations
To use the VPA to automatically update pods, create a VPA CR for a specific workload object with `updateMode` set to `InPlaceOrRecreate` or `Recreate`.

When the pods are created for the workload object, the VPA constantly monitors the containers to analyze their CPU and memory needs. The VPA updates any pods that do not meet the VPA recommendations for CPU and memory to use the new resource limits and requests based on the VPA recommendations, honoring any pod disruption budget set for your applications. The recommendations are added to the `status` field of the VPA CR for reference.

[NOTE]
====
By default, workload objects must specify a minimum of two replicas in order for the VPA to automatically delete their pods. Workload objects that specify fewer replicas than this minimum are not deleted. If you manually delete these pods, when the workload object redeploys the pods, the VPA does update the new pods with its recommendations. You can change this minimum by modifying the `VerticalPodAutoscalerController` object as shown in _Changing the VPA minimum value_.
====

.Example VPA CR for the `InPlaceOrRecreate` or `Recreate` mode
[source,yaml]
----
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: vpa-recommender
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       frontend
  updatePolicy:
    updateMode: "InPlaceOrRecreate"
----
where:

`spec.targetRef.kind`:: Specifies the type of workload object you want this VPA CR to manage.
`spec.targetRef.name`:: Specifies the name of the workload object you want this VPA CR to manage.
`spec.updatePolicy.updateMode`:: Specifies the mode, either `InPlaceOrRecreate` or `Recreate`: 
--
* `InPlaceOrRecreate`. The VPA attempts to update the workload object with the new resource requests without re-creating the pod. If the VPA is unable to update the object in place, the VPA re-creates it.
* `Recreate`. The VPA assigns resource requests on pod creation and updates the existing pods by terminating them. Use this mode rarely, only if you need to ensure that when the resource request changes the pods restart.
--

[NOTE]
====
Before a VPA can determine recommendations for resources and apply the recommended resources to new pods, operating pods must exist and be running in the project.

If a workload's resource usage, such as CPU and memory, is consistent, the VPA can determine recommendations for resources in a few minutes. If a workload's resource usage is inconsistent, the VPA must collect metrics at various resource usage intervals for the VPA to make an accurate recommendation.
====

[id="nodes-pods-vertical-autoscaler-using-pod_{context}"]
== Automatically applying VPA recommendations on pod creation
To use the VPA to apply the recommended resources only when a pod is first deployed, create a VPA CR for a specific workload object with `updateMode` set to `Initial`.

Then, manually delete any pods associated with the workload object that you want to use the VPA recommendations. In the `Initial` mode, the VPA does not delete pods and does not update the pods as it learns new resource recommendations.

.Example VPA CR for the `Initial` mode
[source,yaml]
----
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: vpa-recommender
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       frontend
  updatePolicy:
    updateMode: "Initial"
----
where:

`spec.targetRef.kind`:: Specifies the type of workload object you want this VPA CR to manage.
`spec.targetRef.name`:: Specifies the name of the workload object you want this VPA CR to manage.
`spec.updatePolicy.updateMode`:: Specifies the mode as `Initial`. The VPA assigns resources when pods are created and does not change the resources during the lifetime of the pod.

[NOTE]
====
Before a VPA can determine recommended resources and apply the recommendations to new pods, operating pods must exist and be running in the project.

To obtain the most accurate recommendations from the VPA, wait at least 8 days for the pods to run and for the VPA to stabilize.
====

[id="nodes-pods-vertical-autoscaler-using-manual_{context}"]
== Manually applying VPA recommendations

To use the VPA to only determine the recommended CPU and memory values, create a VPA CR for a specific workload object with `updateMode` set to `Off`.

When the pods are created for that workload object, the VPA analyzes the CPU and memory needs of the containers and records those recommendations in the `status` field of the VPA CR. The VPA does not update the pods as it determines new resource recommendations.

.Example VPA CR for the `Off` mode
[source,yaml]
----
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: vpa-recommender
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       frontend
  updatePolicy:
    updateMode: "Off"
----
where:

`spec.targetRef.kind`:: Specifies the type of workload object you want this VPA CR to manage.
`spec.targetRef.name`:: Specifies the name of the workload object you want this VPA CR to manage.
`spec.updatePolicy.updateMode`:: Specifies the mode as `Off`.

You can view the recommendations by using the following command.

[source,terminal]
----
$ oc get vpa <vpa-name> --output yaml
----

With the recommendations, you can edit the workload object to add CPU and memory requests, then delete and redeploy the pods by using the recommended resources.

[NOTE]
====
Before a VPA can determine recommended resources and apply the recommendations to new pods, operating pods must exist and be running in the project.

To obtain the most accurate recommendations from the VPA, wait at least 8 days for the pods to run and for the VPA to stabilize.
====

[id="nodes-pods-vertical-autoscaler-using-exempt_{context}"]
== Exempting containers from applying VPA recommendations

If your workload object has multiple containers and you do not want the VPA to evaluate and act on all of the containers, create a VPA CR for a specific workload object and add a `resourcePolicy` to opt-out specific containers.

When the VPA updates the pods with recommended resources, any containers with a `resourcePolicy` are not updated and the VPA does not present recommendations for those containers in the pod.

[source,yaml]
----
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: vpa-recommender
spec:
  targetRef:
    apiVersion: "apps/v1"
    kind:       Deployment
    name:       frontend
  updatePolicy:
    updateMode: "InPlaceOrRecreate"
  resourcePolicy:
    containerPolicies:
    - containerName: my-opt-sidecar
      mode: "Off"
----
where:

`spec.targetRef.kind`:: Specifies the type of workload object you want this VPA CR to manage.
`spec.targetRef.name`:: Specifies the name of the workload object you want this VPA CR to manage.
`spec.updatePolicy.updateMode`:: Specifies the mode as `InPlaceOrRecreate`, `Recreate`, `Initial`, or `Off`. Use the `Recreate` mode rarely. For example, use this mode to ensure that the pods restart when the resources are updated.
`spec.resourcePolicy`:: Specifies the containers that you do not want updated by the VPA and set the `mode` to `Off`.

For example, a pod has two containers, the same resource requests and limits:

[source,yaml]
----
# ...
spec:
  containers:
  - name: frontend
    resources:
      limits:
        cpu: 1
        memory: 500Mi
      requests:
        cpu: 500m
        memory: 100Mi
  - name: backend
    resources:
      limits:
        cpu: "1"
        memory: 500Mi
      requests:
        cpu: 500m
        memory: 100Mi
# ...
----

After launching a VPA CR with the `backend` container set to opt-out, the VPA terminates and recreates the pod with the recommended resources applied only to the `frontend` container:

[source,yaml]
----
...
spec:
  containers:
    name: frontend
    resources:
      limits:
        cpu: 50m
        memory: 1250Mi
      requests:
        cpu: 25m
        memory: 262144k
...
    name: backend
    resources:
      limits:
        cpu: "1"
        memory: 500Mi
      requests:
        cpu: 500m
        memory: 100Mi
...
----
