[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Kubernetes](../index.md) > [Tutorials](index.md) > Setting up and testing scaling > Vertical scaling of an application in a cluster

# Vertical scaling of an application in a cluster

Managed Service for Kubernetes supports several types of autoscaling. In this tutorial, you will learn how to set up automatic [pod](../concepts/index.md#pod) resource management with [Vertical Pod Autoscaler](../concepts/autoscale.md#vpa):

* [Create Vertical Pod Autoscaler and a test application](#create-vpa-workload).
* [Test Vertical Pod Autoscaler](#test-vpa).

If you no longer need the resources you created, [delete them](#clear-out).


## Required paid resources {#paid-resources}

The support cost for this solution includes:

* Fee for a Managed Service for Kubernetes cluster: using the master and outbound traffic (see [Managed Service for Kubernetes pricing](../pricing.md)).
* Fee for cluster nodes (VMs): using computing resources, OS, and storage (see [Compute Cloud pricing](../../compute/pricing.md)).
* Fee for a public IP address for cluster nodes (see [Virtual Private Cloud pricing](../../vpc/pricing.md#prices-public-ip)).


## Getting started {#before-you-begin}

1. If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

   The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

1. [Create security groups](../operations/connect/security-groups.md) for the Managed Service for Kubernetes cluster and its node groups.

    {% note warning %}
    
    The configuration of security groups determines performance and availability of the cluster and the services and applications running in it.
    
    {% endnote %}

1. [Create](../operations/kubernetes-cluster/kubernetes-cluster-create.md#kubernetes-cluster-create) a Managed Service for Kubernetes cluster. Use these settings:

   * Use the security groups you created earlier.
   * For Yandex Cloud internal network usage, your cluster does not need a public IP address. To enable internet access to your cluster, assign it a public IP address.

1. [Create a node group](../operations/node-group/node-group-create.md). Use these settings:

   * Use the previously created security groups.
   * To enable internet access for your node group (e.g., for Docker image pulls), assign it a public IP address.

1. [Install kubect](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [configure it to work with the new cluster](../operations/connect/index.md#kubectl-connect).

   If your cluster has no public IP address assigned and `kubectl` is configured via the cluster's private IP address, run `kubectl` commands on a Yandex Cloud VM residing in the same network as the cluster.

1. Install Vertical Pod Autoscaler from [this repository](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler) as follows:

     ```bash
     cd /tmp && \
       git clone https://github.com/kubernetes/autoscaler.git && \
       cd autoscaler/vertical-pod-autoscaler/hack && \
       ./vpa-up.sh
     ```

## Create Vertical Pod Autoscaler and a test application {#create-vpa-workload}

1. Create a file named `app.yaml` with the `nginx` test application and load balancer settings:

   {% cut "app.yaml" %}

   ```yaml
   ---
   ### Deployment
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: nginx
     labels:
       app: nginx
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: nginx
     template:
       metadata:
         name: nginx
         labels:
           app: nginx
       spec:
         containers:
           - name: nginx
             image: registry.k8s.io/hpa-example
             resources:
               requests:
                 memory: "256Mi"
                 cpu: "500m"
               limits:
                 memory: "500Mi"
                 cpu: "1"
   ---
   ### Service
   apiVersion: v1
   kind: Service
   metadata:
     name: nginx
   spec:
     selector:
       app: nginx
     ports:
       - protocol: TCP
         port: 80
         targetPort: 80
     type: LoadBalancer
   ```

   {% endcut %}

1. Create a file named `vpa.yaml` with Vertical Pod Autoscaler configuration:

   {% cut "vpa.yaml" %}

   ```yaml
   ---
   apiVersion: autoscaling.k8s.io/v1
   kind: VerticalPodAutoscaler
   metadata:
     name: nginx
   spec:
     targetRef:
       apiVersion: "apps/v1"
       kind:       Deployment
       name:       nginx
     updatePolicy:
       updateMode:  "Recreate"
       minReplicas: 1
   ```

   {% endcut %}

1. Create the objects:

   ```bash
   kubectl apply -f app.yaml && \
   kubectl apply -f vpa.yaml
   ```

1. Make sure the Vertical Pod Autoscaler and `nginx` pods switched to `Running`:

   ```bash
   kubectl get pods -n kube-system | grep vpa && \
   kubectl get pods | grep nginx
   ```

   Result:

   ```text
   vpa-admission-controller-58********-qmxtv  1/1  Running  0  44h
   vpa-recommender-67********-jqvgt           1/1  Running  0  44h
   vpa-updater-64********-xqsts               1/1  Running  0  44h
   nginx-6c********-62j7w                     1/1  Running  0  42h
   ```

## Test Vertical Pod Autoscaler {#test-vpa}

To test Vertical Pod Autoscaler, you will simulate `nginx` workload.
1. Review the recommendations provided by Vertical Pod Autoscaler prior to simulating the workload:

   ```bash
   kubectl describe vpa nginx
   ```

   Note the low `Cpu` values in the `Status.Recommendation.Container Recommendations` metrics:

   ```yaml
   Name:         nginx
   Namespace:    default
   Labels:       <none>
   Annotations:  <none>
   API Version:  autoscaling.k8s.io/v1
   Kind:         VerticalPodAutoscaler
   ...
   Status:
     Conditions:
       Last Transition Time:  2022-03-18T08:02:04Z
       Status:                True
       Type:                  RecommendationProvided
     Recommendation:
       Container Recommendations:
         Container Name:  nginx
         Lower Bound:
           Cpu:     25m
           Memory:  262144k
         Target:
           Cpu:     25m
           Memory:  262144k
         Uncapped Target:
           Cpu:     25m
           Memory:  262144k
         Upper Bound:
           Cpu:     25m
           Memory:  262144k
   ```

1. Make sure Vertical Pod Autoscaler is managing the `nginx` pod resources:

   ```bash
   kubectl get pod <nginx_pod_name> --output yaml
   ```

   Result:

   ```bash
   apiVersion: v1
   kind: Pod
   metadata:
     annotations:
       vpaObservedContainers: nginx
       vpaUpdates: 'Pod resources updated by nginx: container 0: cpu request, memory
         request, cpu limit, memory limit'
   ...
   spec:
     containers:
     ...
       name: nginx
       resources:
         limits:
           cpu: 50m
           memory: 500000Ki
         requests:
           cpu: 25m
           memory: 262144k
   ```

1. In a separate terminal window, run the following command to simulate a workload:

   ```bash
   URL=$(kubectl get service nginx -o json \
     | jq -r '.status.loadBalancer.ingress[0].ip') && \
     while true; do wget -q -O- http://$URL; done
   ```

   {% note tip %}

   To increase the load and speed up the scenario, run multiple simulations in separate windows.

   {% endnote %}

    {% note info %}
    
    If you cannot access the resource at the specified URL, [make sure](../operations/connect/security-groups.md) the security groups for the Managed Service for Kubernetes cluster and its node groups are configured correctly. If a rule is missing, [add it](../../vpc/operations/security-group-add-rule.md).
    
    {% endnote %}

1. Wait a few minutes and review the recommendation provided by Vertical Pod Autoscaler after simulating the workload:

   ```bash
   kubectl describe vpa nginx
   ```

   Vertical Pod Autoscaler allocated additional resources to the pods as the workload increased. Note the increased `Cpu` values in the `Status.Recommendation.Container Recommendations` metrics:

   ```yaml
   Name:         nginx
   Namespace:    default
   Labels:       <none>
   Annotations:  <none>
   API Version:  autoscaling.k8s.io/v1
   Kind:         VerticalPodAutoscaler
   ...
   Status:
    Conditions:
       Last Transition Time:  2022-03-18T08:02:04Z
       Status:                True
       Type:                  RecommendationProvided
     Recommendation:
       Container Recommendations:
         Container Name:  nginx
         Lower Bound:
           Cpu:     25m
           Memory:  262144k
         Target:
           Cpu:     410m
           Memory:  262144k
         Uncapped Target:
           Cpu:     410m
           Memory:  262144k
         Upper Bound:
           Cpu:     28897m
           Memory:  1431232100
   ```

1. Stop simulating the workload. Within a few minutes, the `Status.Recommendation.Container Recommendations` metrics will regain their initial values.

## Delete the resources you created {#clear-out}

Delete the resources you no longer need to avoid paying for them:

1. [Delete the Kubernetes cluster](../operations/kubernetes-cluster/kubernetes-cluster-delete.md).
1. If you used static public IP addresses to access your cluster or nodes, release and [delete](../../vpc/operations/address-delete.md) them.