[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Kubernetes](../index.md) > [Tutorials](index.md) > Working with DNS > DNS autoscaling based on the cluster size

# DNS autoscaling based on the cluster size


Managed Service for Kubernetes supports DNS autoscaling. `kube-dns-autoscaler` running in a [Managed Service for Kubernetes cluster](../concepts/index.md#kubernetes-cluster) adjusts the number of CoreDNS replicas based on:
* Number of Managed Service for Kubernetes cluster [nodes](../concepts/index.md#node-group).
* [Number of vCPUs](../../compute/concepts/performance-levels.md) in the Managed Service for Kubernetes cluster.

The number of replicas is calculated [by the formulas](#parameters).

To automate DNS scaling:

1. [Configure kube-dns-autoscaler](#configure-autoscaler).
1. [Test scaling](#test-autoscaler).

If you no longer need automatic scaling, [disable it](#disable-autoscaler).

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 using the master and outgoing traffic in a Managed Service for Kubernetes cluster (see [Managed Service for Kubernetes pricing](../pricing.md)).
* Fee for each VM (cluster nodes and management VMs without public access) which covers the use of computing resources, operating system, 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. Create Managed Service for Kubernetes resources:

   {% list tabs group=instructions %}

   - Manually {#manual}

     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 a Managed Service for Kubernetes cluster](../operations/kubernetes-cluster/kubernetes-cluster-create.md). When creating a cluster, specify the preconfigured security groups.
        
        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). To enable internet access for your node group (e.g., for Docker image pulls), assign it a public IP address. Specify the preconfigured security groups.

   - Terraform {#tf}

     1. If you do not have Terraform yet, [install it](../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform).
     1. [Get the authentication credentials](../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials). You can add them to environment variables or specify them later in the provider configuration file.
     1. [Configure and initialize a provider](../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider). There is no need to create a provider configuration file manually, you can [download it](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
     1. Place the configuration file in a separate working directory and [specify the parameter values](../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider). If you did not add the authentication credentials to environment variables, specify them in the configuration file.

     1. Download the [k8s-cluster.tf](https://github.com/yandex-cloud-examples/yc-mk8s-cluster-infrastructure/blob/main/k8s-cluster.tf) configuration file for the Managed Service for Kubernetes cluster to the same working directory. This file describes:
        * [Network](../../vpc/concepts/network.md#network).
        * [Subnet](../../vpc/concepts/network.md#subnet).
        * Managed Service for Kubernetes cluster.
        * Managed Service for Kubernetes node group.
        * [Service account](../../iam/concepts/users/service-accounts.md) required to create the Managed Service for Kubernetes cluster and node group.
        * [Security groups](../../vpc/concepts/security-groups.md) which contain [rules](../operations/connect/security-groups.md) required 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. Specify the [folder ID](../../resource-manager/operations/folder/get-id.md) in the configuration file.
     1. Validate your Terraform configuration files using this command:

        ```bash
        terraform validate
        ```

        Terraform will display any configuration errors detected in your files.
     1. Create the required infrastructure:

        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.

        All the required resources will be created in the specified folder. You can check resource availability and their settings in the [management console](https://console.yandex.cloud).

   {% endlist %}

   {% note warning %}
   
   Do not change or delete Virtual Private Cloud resources used by the Managed Service for Kubernetes cluster. This may cause cluster errors or make it impossible to delete later.
   
   {% endnote %}

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.

## Configure kube-dns-autoscaler {#configure-autoscaler}

### Make sure the app is up and running {#verify-app}

Check for [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) in the `kube-system` [namespace](../concepts/index.md#namespace):

```bash
kubectl get deployment --namespace=kube-system
```

Result:

```text
NAME                 READY  UP-TO-DATE  AVAILABLE  AGE
...
kube-dns-autoscaler  1/1    1           1          52m
```

### Define the scaling parameters {#parameters}

The `kube-dns-autoscaler` [pod](../concepts/index.md#pod) regularly polls the Kubernetes server for the number of Managed Service for Kubernetes cluster nodes and cores. Based on this data, it calculates the number of CoreDNS replicas.

There are two calculation modes:
* Linear
* Ladder (step function)

For more information about calculating, see [this cluster-proportional-autoscaler page on GitHub](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler#calculation-of-number-of-replicas).

This example uses the `linear` mode which calculates the number of replicas by the following formula:

```text
replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) )
```

Where:
* `coresPerReplica`: Configuration parameter indicating the number of CoreDNS replicas per vCPU of the Managed Service for Kubernetes cluster.
* `nodesPerReplica`: Configuration parameter indicating the number of CoreDNS replicas per node of the Managed Service for Kubernetes cluster.
* `cores`: Actual number of vCPUs in the Managed Service for Kubernetes cluster.
* `nodes`: Actual number of nodes in the Managed Service for Kubernetes cluster.
* `ceil`: Function that rounds a decimal to an integer.
* `max`: Function that returns the maximum of the two values.

The optional `preventSinglePointFailure` parameter is relevant for multi-node Managed Service for Kubernetes clusters. If `true`, the minimum number of DNS replicas is two.

You can also define the `min` and `max` configuration parameters that set the minimum and maximum number of CoreDNS replicas in the Managed Service for Kubernetes cluster:

```text
replicas = min(replicas, max)
replicas = max(replicas, min)
```

For more information about calculating, see [this cluster-proportional-autoscaler page on GitHub](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler#calculation-of-number-of-replicas).

### Change the configuration {#edit-config}

1. Check the current settings.

   In this example, we have a Managed Service for Kubernetes node group named `node-group-1` with the following settings:
   * Number of Managed Service for Kubernetes nodes: `3`
   * Number of vCPUs: `12`

   By default, `linear` mode and the following scaling parameters are used:
   * `coresPerReplica`: `256`
   * `nodesPerReplica`: `16`
   * `preventSinglePointFailure`: `true`

   ```text
   replicas = max( ceil( 12 * 1/256 ), ceil( 3 * 1/16 ) ) = 1
   ```

   As `preventSinglePointFailure` is set to `true`, the number of CoreDNS replicas will be two.

   To get the `coredns` pod details, run this command:

   ```bash
   kubectl get pods -n kube-system
   ```

   Result:

   ```bash
   NAME                      READY  STATUS   RESTARTS  AGE
   ...
   coredns-7c********-4dmjl  1/1    Running  0         128m
   coredns-7c********-n7qsv  1/1    Running  0         134m
   ```

1. Set new parameter values.

   Change the configuration as follows:
   * `coresPerReplica`: `4`
   * `nodesPerReplica`: `2`
   * `preventSinglePointFailure`: `true`

   ```text
   replicas = max( ceil( 12 * 1/4 ), ceil( 3 * 1/2 ) ) = 3
   ```

   To deliver the parameters to `kube-dns-autoscaler`, edit the relevant [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) using this command:

   ```bash
   kubectl edit configmap kube-dns-autoscaler --namespace=kube-system
   ```

   This will open the `kube-dns-autoscaler` configuration in a text editor. Edit the parameter line as follows:

   ```text
   linear: '{"coresPerReplica":4,"nodesPerReplica":2,"preventSinglePointFailure":true}'
   ```

   Save your changes. You will see the result of the operation on the screen:

   ```text
   configmap/kube-dns-autoscaler edited
   ```

   `kube-dns-autoscaler` will load this configuration and scale the DNS service based on the new parameters.

## Test scaling {#test-autoscaler}

### Resize the Managed Service for Kubernetes cluster {#resize-cluster}

Create another Managed Service for Kubernetes node group using this command:

```bash
yc managed-kubernetes node-group create \
  --name node-group-2 \
  --cluster-name dns-autoscaler \
  --location zone=ru-central1-a \
  --public-ip \
  --fixed-size 2 \
  --cores 4 \
  --core-fraction 5
```

Result:

```text
done (2m43s)
...
```

Now the Managed Service for Kubernetes cluster has five nodes with 20 vCPUs. Calculate the number of replicas:

```text
replicas = max( ceil( 20 * 1/4 ), ceil( 5 * 1/2 ) ) = 5
```

### Check the changes in the number of CoreDNS replicas {#inspect-changes}

Run this command:

```bash
kubectl get pods -n kube-system
```

Result:

```text
NAME                      READY  STATUS   RESTARTS  AGE
...
coredns-7c********-7l8mc  1/1    Running  0         3m30s
coredns-7c********-n7qsv  1/1    Running  0         3h20m
coredns-7c********-pv9cv  1/1    Running  0         3m40s
coredns-7c********-r2lss  1/1    Running  0         49m
coredns-7c********-s5jgz  1/1    Running  0         57m
```

### Set up Managed Service for Kubernetes node downscaling {#reduce-nodes}

By default, Cluster Autoscaler does not scale down nodes in autoscaling Managed Service for Kubernetes node group if these nodes runs pods from the `kube-system` namespace managed by the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/), [ReplicaSet](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/), or [StatefulSet](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) controllers, e.g., CoreDNS pods. In this case, the number of Managed Service for Kubernetes nodes per group cannot fall below the number of CoreDNS pods.

To enable Managed Service for Kubernetes node downscaling, configure a [PodDisruptionBudget](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) that allows stopping up to two CoreDNS pods at the same time:

```bash
kubectl create poddisruptionbudget <pdb_name> \
  --namespace=kube-system \
  --selector k8s-app=kube-dns \
  --min-available=2
```

Result:

```text
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: <pdb_name>
spec:
  minAvailable: 2
  selector:
    matchLabels:
      k8s-app: kube-dns
```

## Disable scaling {#disable-autoscaler}

Set the number of replicas in the `kube-dns-autoscaler` [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) to zero:

```bash
kubectl scale deployment --replicas=0 kube-dns-autoscaler --namespace=kube-system
```

Result:

```text
deployment.apps/kube-dns-autoscaler scaled
```

Check the result with this command:

```bash
kubectl get rs --namespace=kube-system
```

Result:

```text
NAME                 READY  UP-TO-DATE  AVAILABLE  AGE
...
kube-dns-autoscaler  0/0    0           0          3h53m
```

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

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

{% list tabs group=instructions %}

- Manually {#manual}

  [Delete the Managed Service for Kubernetes cluster](../operations/kubernetes-cluster/kubernetes-cluster-delete.md).

- Terraform {#tf}

  1. In the terminal window, go to the directory containing the infrastructure plan.
  
      {% note warning %}
  
      Make sure the directory has no Terraform manifests with the resources you want to keep. Terraform deletes all resources that were created using the manifests in the current directory.
  
      {% endnote %}
  
  1. Delete resources:
  
      1. Run this command:
  
          ```bash
          terraform destroy
          ```
  
      1. Confirm deleting the resources and wait for the operation to complete.
  
      All the resources described in the Terraform manifests will be deleted.

{% endlist %}