[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Kubernetes](../index.md) > [Step-by-step guides](index.md) > Configuring autoscaling

# Configuring autoscaling

Managed Service for Kubernetes supports the following [autoscaling](../concepts/autoscale.md) options:
* [Cluster autoscaling](#ca)
* [Master autoscaling](../concepts/autoscale.md#master-autoscaler)
* [Horizontal pod autoscaling](#hpa)
* [Vertical pod autoscaling](#vpa)

{% note warning %}

Starting June 18, 2026, master node auto-scaling will be enabled on all clusters in the `RAPID` [release channel](../concepts/release-channels-and-updates.md) where the master is deployed in a [highly available configuration](../concepts/index.md#master).

{% endnote %}

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

1. [Create a Managed Service for Kubernetes cluster](kubernetes-cluster/kubernetes-cluster-create.md) with any suitable configuration.

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

## Configuring cluster autoscaling {#ca}

{% note warning %}

You can only enable autoscaling of this type when creating a [Managed Service for Kubernetes node group](../concepts/index.md#node-group).

{% endnote %}

To create an autoscaling Managed Service for Kubernetes node group:

{% list tabs group=instructions %}

- Management console {#console}

  [Create a Managed Service for Kubernetes node group](node-group/node-group-create.md) with the following parameters:
  * Scaling **Type**: `Automatic`.
  * **Minimum number of nodes**: Number of Managed Service for Kubernetes nodes to remain in the group at the minimum workload.
  * **Maximum number of nodes**: Maximum number of Managed Service for Kubernetes nodes allowed in the group.
  * **Initial number of nodes**: Number of Managed Service for Kubernetes nodes to create together with the group. This number must be between the minimum and the maximum number of nodes in the group.

- CLI {#cli}

  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. Check the command to create a Managed Service for Kubernetes node group:

     ```bash
     yc managed-kubernetes node-group create --help
     ```

  1. Create an autoscaling Managed Service for Kubernetes node group:

     ```bash
     yc managed-kubernetes node-group create \
     ...
       --auto-scale min=<minimum_number_of_nodes>, max=<maximum_number_of_nodes>, initial=<initial_number_of_nodes>
     ```

- Terraform {#tf}

  1. With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
     
     Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.
     
     For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../terraform/index.md).

     If you do not have Terraform yet, [install it and configure the Yandex Cloud provider](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
     
     
     To manage infrastructure using Terraform under a service account or user accounts (a Yandex account, a federated account, or a local user), [authenticate](../../terraform/authentication.md) using the appropriate method.
  1. Open the current Terraform configuration file describing the node group.

     For more on how to create such a file, see [Creating a node group](node-group/node-group-create.md).
  1. Add a description of the new node group and specify the autoscaling settings under `scale_policy.auto_scale`:

     ```hcl
     resource "yandex_kubernetes_node_group" "<node_group_name>" {
     ...
       scale_policy {
         auto_scale {
           min     = <minimum_number_of_nodes_in_group>
           max     = <maximum_number_of_nodes_in_group>
           initial = <initial_number_of_nodes_in_group>
         }
       }
     }
     ```

  1. Make sure the configuration files are correct.

     1. In the command line, navigate to the directory that contains the current Terraform configuration files defining the infrastructure.
     1. Run this command:
     
        ```bash
        terraform validate
        ```
     
        Terraform will show any errors found in your configuration files.

  1. Confirm updating the resources.

     1. Run this command to view the planned changes:
     
        ```bash
        terraform plan
        ```
     
        If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
     
     1. If everything looks correct, apply the changes:
        1. Run this command:
     
           ```bash
           terraform apply
           ```
     
        1. Confirm updating the resources.
        1. Wait for the operation to complete.

     {% note warning "Timeouts" %}
     
     The Terraform provider sets time limits for operations with Managed Service for Kubernetes cluster node groups:
     
     * Creating and editing: 60 minutes.
     * Deleting: 20 minutes.
     
     Operations in excess of this time will be interrupted.
     
     {% cut "How do I modify these limits?" %}
     
     Add the `timeouts` section to the cluster node group description, e.g.:
     
     ```hcl
     resource "yandex_kubernetes_node_group" "<node_group_name>" {
       ...
       timeouts {
         create = "1h30m"
         update = "1h30m"
         delete = "60m"
       }
     }
     ```
     
     {% endcut %}
     
     {% endnote %}

{% endlist %}

Cluster Autoscaler is managed on the Managed Service for Kubernetes side.

Learn more about Cluster Autoscaler in [Cluster autoscaling](../concepts/autoscale.md#ca). You can find the default parameters in [this Kubernetes guide](https://github.com/kubernetes/autoscaler/blob/c6b754c359a8563050933a590f9a5dece823c836/cluster-autoscaler/FAQ.md#what-are-the-parameters-to-ca).

See also [Questions and answers about node group autoscaling in Managed Service for Kubernetes](../qa/cluster-autoscaler.md).

## Configuring horizontal pod autoscaling {#hpa}

{% list tabs group=instructions %}

- CLI {#cli}

  1. Create a Horizontal Pod Autoscaler for your application, for example:

     ```bash
     kubectl autoscale deployment/<application_name> --cpu-percent=50 --min=1 --max=3
     ```

     Where:
     * `--cpu-percent`: Expected [Managed Service for Kubernetes pod](../concepts/index.md#pod) load on the vCPU.
     * `--min`: Minimum number of Managed Service for Kubernetes pods.
     * `--max`: Maximum number of Managed Service for Kubernetes pods.
  1. Check the Horizontal Pod Autoscaler status:

     ```bash
     kubectl describe hpa/<application_name>
     ```

{% endlist %}

Learn more about Horizontal Pod Autoscaler in [Horizontal pod autoscaling](../concepts/autoscale.md#hpa).

## Configuring vertical pod autoscaling {#vpa}

{% list tabs group=instructions %}

- CLI {#cli}

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

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

  1. Create a configuration file named `vpa.yaml` for your application:

     ```yaml
     apiVersion: autoscaling.k8s.io/v1
     kind: VerticalPodAutoscaler
     metadata:
       name: <application_name>
     spec:
       targetRef:
         apiVersion: "apps/v1"
         kind:       Deployment
         name:       <application_name>
       updatePolicy:
         updateMode: "<VPA_update_mode>"
     ```

     Where `updateMode` is Vertical Pod Autoscaler's operating mode: `Off`, `Initial`, `Recreate`, or `InPlaceOrRecreate`. For more information, see [Vertical pod autoscaling](../concepts/autoscale.md#vpa).

  1. Create a Vertical Pod Autoscaler for your application:

     ```bash
     kubectl apply -f vpa.yaml
     ```

  1. Check the Vertical Pod Autoscaler status:

     ```bash
     kubectl describe vpa <application_name>
     ```

{% endlist %}

Learn more about Vertical Pod Autoscaler in [Vertical pod autoscaling](../concepts/autoscale.md#vpa).

## Deleting terminated pods {#delete-terminated}

Sometimes during autoscaling, Managed Service for Kubernetes node pods are not removed and stay in the **Terminated** state. This happens because the [Pod garbage collector (PodGC)](https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection) fails to timely clean up these pods.

You can remove terminated Managed Service for Kubernetes pods:
* [Manually](#manually)
* [Automatically using a CronJob](#automatically-cronjob)

### Manually {#manually}

Run this command:

```bash
kubectl get pods --all-namespaces | grep -i Terminated \
| awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n
```

### Automatically using a CronJob {#automatically-cronjob}

To remove terminated Managed Service for Kubernetes pods automatically:
1. [Set up a CronJob](#setup-cronjob).
1. [Check the results of your CronJob jobs](#check-cronjob).

If you no longer need the CronJob, [delete it](#delete-cronjob).

#### Setting up automatic deletion in a CronJob {#setup-cronjob}

1. Create a file named `cronjob.yaml` with a specification for the [CronJob](https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#creating-a-cron-job) and resources to run it:

   ```yaml
   ---
   apiVersion: batch/v1
   kind: CronJob
   metadata:
     name: terminated-pod-cleaner
   spec:
     schedule: "*/5 * * * *"
     jobTemplate:
       spec:
         template:
           spec:
             serviceAccountName: terminated-pod-cleaner
             containers:
             - name: terminated-pod-cleaner
               image: bitnamilegacy/kubectl
               imagePullPolicy: IfNotPresent
               command: ["/bin/sh", "-c"]
               args: ["kubectl get pods --all-namespaces | grep -i Terminated | awk '{print $1, $2}' | xargs --no-run-if-empty -n2 kubectl delete pod -n"]
             restartPolicy: Never

   ---
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: terminated-pod-cleaner

   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRole
   metadata:
     name: terminated-pod-cleaner
   rules:
     - apiGroups: [""]
       resources:
         - pods
       verbs: [list, delete]

   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRoleBinding
   metadata:
     name: terminated-pod-cleaner
   subjects:
   - kind: ServiceAccount
     name: terminated-pod-cleaner
     namespace: default
   roleRef:
     kind: ClusterRole
     name: terminated-pod-cleaner
     apiGroup: rbac.authorization.k8s.io
   ```

   The `schedule: "*/5 * * * *"` line defines a schedule in cron format: the job runs every 5 minutes. Change the interval if needed.
1. Create a CronJob and its resources:

   ```bash
   kubectl create -f cronjob.yaml
   ```

   Result:

   ```text
   cronjob.batch/terminated-pod-cleaner created
   serviceaccount/terminated-pod-cleaner created
   clusterrole.rbac.authorization.k8s.io/terminated-pod-cleaner created
   clusterrolebinding.rbac.authorization.k8s.io/terminated-pod-cleaner created
   ```

1. Make sure the CronJob has been created:

   ```bash
   kubectl get cronjob terminated-pod-cleaner
   ```

   Result:

   ```text
   NAME                    SCHEDULE     SUSPEND  ACTIVE  LAST SCHEDULE  AGE
   terminated-pod-cleaner  */5 * * * *  False    0       <none>         4s
   ```

   After the interval specified in `SCHEDULE`, a time value will appear in the `LAST SCHEDULE` column. This means that the job run has finished successfully or finished failed.

#### Checking the results of CronJob jobs {#check-cronjob}

1. Get a list of jobs:

   ```bash
   kubectl get jobs
   ```

   Result:

   ```text
   NAME           COMPLETIONS  DURATION  AGE
   <job_name>  1/1          4s        2m1s
   ...
   ```

1. Get the name of the Managed Service for Kubernetes pod that ran the job:

   ```bash
   kubectl get pods --selector=job-name=<job_name> --output=jsonpath={.items[*].metadata.name}
   ```

1. View the Managed Service for Kubernetes pod logs:

   ```bash
   kubectl logs <pod_name>
   ```

   The log will include a list of removed Managed Service for Kubernetes pods. If the log is empty, this means that there were no Managed Service for Kubernetes **Terminated** pods when the job ran.

#### Deleting the CronJob {#delete-cronjob}

To delete the CronJob and its resources, run this command:

```bash
kubectl delete cronjob terminated-pod-cleaner && \
kubectl delete serviceaccount terminated-pod-cleaner && \
kubectl delete clusterrole terminated-pod-cleaner && \
kubectl delete clusterrolebinding terminated-pod-cleaner
```