---
title: 'Автомасштабирование в кластере Managed Kubernetes'
sidebar_label: 'Автомасштабирование'
sidebar_position: 7
description: 'Инструменты автомасштабирования в кластере Managed Kubernetes, принципы их работы и их настройка'
---

import Formbricks from '@theme/MDXComponents/Formbricks';
import MoreVerticalIcon from '@selectel/docux/icons/more-vertical';
import { CustomTable } from '@selectel/docux/components';

# Автомасштабирование в кластере Managed Kubernetes

:::info

Автомасштабирование недоступно:

* для групп нод с GPU без драйверов;
* групп нод на выделенных серверах.

:::

В кластере Managed Kubernetes для автомасштабирования групп нод можно использовать [Cluster Autoscaler](#autoscaling-with-cluster-autoscaler) или [Karpenter](#autoscaling-with-karpenter).
Они помогают оптимально использовать ресурсы кластера — в зависимости от нагрузки на кластер количество нод в группе будет автоматически уменьшаться или увеличиваться.
Cluster Autoscaler устанавливается автоматически при создании кластера, для начала работы его достаточно включить.
Karpenter нужно предварительно установить и настроить.

При использовании инструментов автомасштабирования учитывайте [рекомендации](#recommendations).

Для автомасштабирования подов в Managed Kubernetes используется [Metrics Server](/managed-kubernetes/clusters/metrics-server.mdx).

## Рекомендации \{#recommendations}

Для оптимальной работы автомасштабирования мы рекомендуем:

* не использовать одновременно несколько инструментов автомасштабирования;
* убедиться, что в проекте есть [квоты](/access-control/projects/quotas.mdx) на vCPU, RAM, GPU и объем диска для создания максимального количества нод в группе;
* указать в манифестах для подов запросы на ресурсы.
  Подробнее в инструкции [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) документации Kubernetes;
* настроить для подов, для которых недопустимы остановки, [PodDisruptionBudget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets).
  Это поможет избежать даунтайма при переносе между нодами;
* не изменять ресурсы ноды вручную через панель управления.
  Cluster Autoscaler и Karpenter не будут  учитывать эти изменения;
* при использовании Cluster Autoscaler проверить, что ноды в группе имеют одинаковую конфигурацию и лейблы.

## Автомасштабирование с помощью Cluster Autoscaler \{#autoscaling-with-cluster-autoscaler}

Cluster Autoscaler не требуется устанавливать в кластере — он устанавливается автоматически при создании кластера.
Чтобы использовать Cluster Autoscaler в кластере, [включите автомасшабирование группы нод](#enable-autoscaling).
После включения автомасштабирования используются настройки по умолчанию, но вы можете [настроить Cluster Autoscaler](#configure-cluster-autoscaler) для каждой группы нод.

### Принцип работы \{#principle-of-operation}

Cluster Autoscaler работает с существующими группами нод и заранее выбранными конфигурациями.
Если группа нод находится в статусе `ACTIVE`, Cluster Autoscaler каждые 10 секунд проверяет, есть ли поды в статусе `PENDING`, и анализирует нагрузку — запросы от подов на vCPU, RAM и GPU.
В зависимости от результатов проверки ноды [добавляются](#adding-node) или [удаляются](#deleting-node).
Группа нод в это время переходит в статус `PENDING_SCALE_UP` или `PENDING_SCALE_DOWN`.
Статус кластера во время автомасштабирования — `ACTIVE`.
Подробнее о статусах кластера в инструкции [Посмотреть статус кластера](/managed-kubernetes/clusters/cluster-statuses.mdx).

Минимальное и максимальное количество нод в группе можно задать при [включении автомасштабирования](#enable-autoscaling) — Cluster Autoscaler будет менять количество нод только в этих пределах.
Если в других группах нод кластера остается не менее двух рабочих нод, можно настроить [автомасштабирование до нуля нод](#autoscaling-down-to-zero).

#### Добавление ноды \{#adding-node}

Если есть поды в статусе `PENDING` и в кластере не хватает свободных ресурсов для их размещения, в кластер добавляется необходимое количество нод.
В кластере с версией Kubernetes 1.28 и выше Cluster Autoscaler будет работать сразу в нескольких группах и распределять ноды равномерно.

:::note

Например, у вас две группы нод с включенным автомасштабированием.
Нагрузка на кластер увеличилась и требует добавления четырех нод.
В каждой группе нод будет одновременно создано по две новые ноды.

:::

В кластере с версией Kubernetes 1.27 и ниже ноды добавляются по одной за цикл проверки.

#### Удаление ноды \{#deleting-node}

Если нет подов в статусе `PENDING`, Cluster Autoscaler проверяет количество ресурсов, которые запрашивают поды.

Если запрашиваемое количество ресурсов для подов на одной ноде меньше 50% от ее ресурсов, то Cluster Autoscaler помечает ноду как ненужную.
Если на ноде через 10 минут не вырастет количество запросов на ресурсы, Cluster Autoscaler проверит, можно ли перенести поды на другие ноды.

Cluster Autoscaler не перенесет поды и, соответственно, не удалит ноду, если выполняется одно из условий:

* поды используют [PodDisruptionBudget](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets);
* в Kube-system подах нет PodDisrptionBudget;
* поды созданы без контроллера — например, Deployment, ReplicaSet, StatefulSet;
* поды используют local storage;
* на других нодах нет ресурсов под запросы пода;
* есть несоответствие nodeSelector, правил affinity и anti-affinity или других параметров.

Вы можете разрешить таким подам перенос — для этого добавьте аннотацию:

```yaml
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
```

Если ограничений нет, поды будут перенесены, а малонагруженные ноды удалятся.
Ноды удаляются по одной за цикл проверки.

#### Автомасштабирование до нуля нод \{#autoscaling-down-to-zero}

В группе нод можно настроить автомасштабирование до нуля нод — при низкой нагрузке удаляются все ноды группы.
Карточка группы нод со всеми настройками не удаляется.
Когда нагрузка повысится, в этой группе нод снова могут быть добавлены ноды.

Автомасштабирование до нуля нод работает, только если в других группах нод кластера остается не менее двух рабочих нод.
В кластере должны оставаться рабочие ноды для размещения системных компонентов, которые нужны для функционирования кластера.

:::note

Например, автомасштабирование до нуля нод не сработает, если в кластере:

* две группы нод, в каждой из которых по одной рабочей ноде;
* одна группа нод с двумя рабочими нодами.

:::

Когда в группе нет нод, вы не платите за неиспользуемые ресурсы.

### Включить автомасштабирование с помощью Cluster Autoscaler \{#enable-autoscaling}

:::info

Если установить минимальное количество нод в группе больше, чем текущее количество, оно не увеличится до нижней границы сразу.
Группа нод будет масштабироваться только после появления подов в статусе `PENDING`.
Так же и с верхней границей нод в группе — если текущее количество нод больше верхней границы, удаление начнется только после проверки подов.

:::

Включить автомасштабирование с помощью Cluster Autoscaler можно в панели управления, через [API Managed Kubernetes](/api/managed-kubernetes/) или через [Terraform](/terraform/selectel-provider-reference/resources/mks_nodegroup_v1/).

1. В [панели управления](https://my.selectel.ru/mks/) в верхнем меню нажмите **Продукты** и выберите **Managed Kubernetes**.
2. В разделе **Кластеры** откройте страницу кластера → вкладка **Состав кластера**.
3. В меню <MoreVerticalIcon /> группы нод выберите **Изменить количество нод**.
4. В поле **Количество нод** откройте вкладку **С автомасштабированием**.
5. Установите минимальное и максимальное количество нод в группе — значение нод будет меняться только в этом диапазоне.
   Для отказоустойчивой работы системных компонентов мы рекомендуем использовать не менее двух рабочих нод в кластере. Ноды могут находиться в разных группах.
6. Нажмите **Сохранить**.

### Настроить Cluster Autoscaler \{#configure-cluster-autoscaler}

Вы можете настроить Cluster Autoscaler отдельно для каждой группы нод.

Параметры, их описание и значения по умолчанию можно посмотреть в таблице [Параметры Cluster Autoscaler](#cluster-autoscaler-parameters).
Если вы не укажете параметр в манифесте, будет использовано значение по умолчанию.

Пример манифеста:

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
    name: cluster-autoscaler-nodegroup-options
    namespace: kube-system
data:
    config.yaml: |
        150da0a9-6ea6-4148-892b-965282e195b0:
          scaleDownUtilizationThreshold: 0.55
          scaleDownUnneededTime: 7m
          zeroOrMaxNodeScaling: true
        e3dc24ca-df9d-429c-bcd5-be85f8d28710:
          scaleDownGpuUtilizationThreshold: 0.25
          ignoreDaemonSetsUtilization: true
```

Здесь `150da0a9-6ea6-4148-892b-965282e195b0` и `e3dc24ca-df9d-429c-bcd5-be85f8d28710` — уникальные идентификаторы (UUID) групп нод в кластере.
Можно посмотреть в [панели управления](https://my.selectel.ru/mks/): в верхнем меню нажмите **Продукты** ⟶ **Managed Kubernetes** ⟶ раздел **Kubernetes** ⟶ страница кластера ⟶ скопируйте UUID над карточкой группы нод, рядом с сегментом пула.

#### Параметры Cluster Autoscaler \{#cluster-autoscaler-parameters}

<CustomTable>
  <table data-sticky>
    <thead>
      <tr>
        <th />

        <th>Описание</th>
        <th>Значение по умолчанию</th>
      </tr>
    </thead>

    <tbody>
      <tr>
        <th>scaleDownUtilizationThreshold</th>
        <td>Минимальная загрузка vCPU и RAM ноды, при которой система может удалить ноду. Если нода использует меньше указанного процента vCPU и RAM, например меньше 50% при значении `0.5`, система удаляет ноду</td>
        <td>0.5</td>
      </tr>

      <tr>
        <th>scaleDownGpuUtilizationThreshold</th>
        <td>Минимальная загрузка GPU, при которой система может удалить ноду. Если нода использует меньше указанного процента GPU, например меньше 50% при значении `0.5`, система удаляет ноду</td>
        <td>0.5</td>
      </tr>

      <tr>
        <th>scaleDownUnneededTime</th>
        <td>Время ожидания перед удалением ноды с низкой нагрузкой. Система не удалит ноду сразу, как только упадет нагрузка ноды — она подождет указанное время, чтобы убедиться, что снижение нагрузки стабильное</td>
        <td>10m</td>
      </tr>

      <tr>
        <th>scaleDownUnreadyTime</th>
        <td>Время ожидания перед удалением ноды в статусе `NotReady`. Система не оставит ноду в статусе `NotReady` в кластере — она подождет указанное время, чтобы убедиться, что нода зависла и не восстановится, а затем удалит ее</td>
        <td>20m</td>
      </tr>

      <tr>
        <th>maxNodeProvisionTime</th>
        <td>Время ожидания при добавлении новой ноды. Если возникла ошибка и нода не добавилась в течение указанного времени, система заново запустит процесс добавления ноды</td>
        <td>15m</td>
      </tr>

      <tr>
        <th>zeroOrMaxNodeScaling</th>
        <td>Позволяет автоматически изменять количество нод только до нуля или максимума, который вы установили. Полезно, если нужно, чтобы при появлении нагрузки система развернула сразу все ноды в группе, а при отсутствии нагрузки — удалила все ноды</td>
        <td>false</td>
      </tr>

      <tr>
        <th>ignoreDaemonSetsUtilization</th>
        <td>Позволяет не учитывать служебные сервисы (DaemonSets), когда система определяет, нужно ли уменьшать количество нод в группе. Если значение `true`, служебные сервисы не учитываются</td>
        <td>false</td>
      </tr>
    </tbody>
  </table>
</CustomTable>

## Автомасштабирование с помощью Karpenter \{#autoscaling-with-karpenter}

### Принцип работы \{#principle-of-operation}

Karpenter — это инструмент автомасштабирования кластера с гибкими настройками.
В отличие от Cluster Autoscaler, Karpenter использует не только существующие группы нод, но и может создавать новые группы нод.

Karpenter может выбрать оптимальную конфигурацию ноды — с учетом не только технических параметров, но и стоимости.
Karpenter выбирает наиболее дешевый вариант, который подходит для текущей нагрузки.
Это возможно благодаря тому, что Karpenter интегрируется напрямую с OpenStack API, которое используется для создания ресурсов облачной платформы.

Если кластер находится в статусе `ACTIVE`, Karpenter проверяет, есть ли поды ([Pod](https://kubernetes.io/docs/concepts/workloads/pods/)) в статусе `PENDING`, и анализирует нагрузку — запросы от подов на vCPU, RAM и GPU.
В зависимости от результатов проверки группы нод и ноды добавляются или удаляются.
Karpenter может удалить только ноды и группы нод, которые он создал.

Кластер в это время переходит в статус `PENDING_SCALE_UP` или `PENDING_SCALE_DOWN`.
Статус кластера во время автомасштабирования — `ACTIVE`.
Подробнее о статусах кластера в инструкции [Посмотреть статус кластера](/managed-kubernetes/clusters/cluster-statuses.mdx).

### Установить Karpenter \{#install-karpenter}

1. В [панели управления](https://my.selectel.ru/mks/) в верхнем меню нажмите **Продукты** и выберите **Managed Kubernetes**.

2. В разделе **Кластеры** откройте страницу кластера → вкладка **Настройки**.

3. Нажмите **Скачать kubeconfig**.
   Скачивание kubeconfig-файла недоступно, если у кластера статус `PENDING_CREATE`, `PENDING_ROTATE_CERTS`, `PENDING_DELETE` или `ERROR`.

4. В переменную окружения `KUBECONFIG` экспортируйте путь к kubeconfig-файлу:

   ```bash
   export KUBECONFIG=<path>
   ```

   Укажите `<path>` — путь к kubeconfig-файлу `cluster_name.yaml`, где `<cluster_name>` — имя кластера.

5. В переменную окружения `ClusterID` экспортируйте ID кластера Managed Kubernetes:

   ```bash
   export ClusterID=<cluster_id>
   ```

   Укажите `<cluster_id>` — ID кластера Managed Kubernetes, можно посмотреть в [панели управления](https://my.selectel.ru/mks/): в верхнем меню нажмите **Продукты** → **Managed Kubernetes** → страница кластера → скопируйте ID под именем кластера, рядом с регионом и пулом.

6. Установите Karpenter с помощью Helm:

   ```bash

   helm install karpenter-helmrelease oci://ghcr.io/selectel/mks-charts/karpenter: \
   --namespace kube-system \
   --set controller.settings.clusterID=$ClusterID
   ```

   По умолчанию устанавливается последняя доступная версия. Доступные версии можно посмотреть в [репозитории mks-charts](https://github.com/selectel/mks-charts/releases) документации Selectel на сайте GitHub.

### Настроить Karpenter \{#configure-karpenter}

Чтобы настроить автомасштабирование с помощью Karpenter, настройте объекты NodePool и NodeClass.

NodePool описывает правила подбора и масштабирования нод.
Например:

* какие типы нод можно создавать;
* с какими конфигурациями (флейворами) и ресурсами;
* когда эти ноды можно удалить или пересоздать.

Каждый NodePool ссылается на конкретный NodeClass.
В конфигурациях (флейворах) с сетевыми дисками NodeClass определяет инфраструктурные параметры сетевых дисков, которые будут использоваться нодами в кластере.
В одном кластере может быть несколько разных NodeClass, например которые отличаются типом или размером сетевого диска.
Конфигурации (флейворы) с локальным загрузочным диском тоже могут использоваться, но параметры локального диска определяются выбранной конфигурацией.

Подробнее о NodePool в статье [NodePools](https://karpenter.sh/docs/concepts/nodepools/) документации Karpenter.

1. [Проверьте соответствие кластера требованиям](#check-compliance-with-requirements).
2. [Создайте NodeClass](#create-nodeclass).
3. [Создайте NodePool](#create-nodepool).

#### 1. Проверить соответствие кластера требованиям \{#check-compliance-with-requirements}

1. Убедитесь, что версия Kubernetes 1.28 или выше.
   Вы можете [обновить версию кластера](/managed-kubernetes/clusters/upgrade-version.mdx).

2. Убедитесь, что в кластере минимум одна нода, в которой не менее 2 vCPU и 4 GiB RAM.
   Для оптимальной работы Karpenter рекомендуем добавить в кластер две ноды, в каждой из которых не менее 2 vCPU и 4 GiB RAM;

3. Убедитесь, что выключено [автомасштабирование](/managed-kubernetes/node-groups/autoscaling.mdx).

4. Убедитесь, что выключено [автовосстановление](/managed-kubernetes/node-groups/reinstall-nodes.mdx).

#### 2. Создать NodeClass \{#create-nodeclass}

1. Создайте YAML-файл `nodeclass.yaml` с манифестом для объекта NodeClass.

   Пример манифеста NodeClass для сетевого диска типа Универсальный:

   ```yaml
   apiVersion: karpenter.k8s.selectel/v1alpha1
   kind: SelectelNodeClass
   metadata:
       name: default
   spec:
       disk:
           categories:
               - universal
           sizeGiB: 30
   ```

   Здесь:

   * `universal` — [тип сетевого диска](/cloud-servers/volumes/about-network-volumes.mdx#network-volume-types-list);
   * `30` — размер сетевого диска в ГБ.

2. Примените манифест:

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

#### 3. Создать NodePool \{#create-nodepool}

1. Создайте YAML-файл `nodepool.yaml` с манифестом для объекта NodePool.
   Описание всех параметров, кроме параметров блока `requirements`, можно посмотреть в инструкции [NodePools](https://karpenter.sh/docs/concepts/nodepools/) документации Karpenter.
   Описание параметров блока `requirements` — в таблице [Параметры блока requirements в NodePool](#requirements-in-nodepool).

   <details>
     <summary>Пример манифеста NodePool при использовании сетевого плагина Calico</summary>

     ```yaml
     apiVersion: karpenter.sh/v1
     kind: NodePool
     metadata:
         name: default
     spec:
         template:
             spec:
                 nodeClassRef:
                     name: default
                     kind: SelectelNodeClass
                     group: karpenter.k8s.selectel
                 requirements:
                     - key: topology.kubernetes.io/zone
                       operator: In
                       values: ['ru-7a', 'ru-7b']
                     - key: node.kubernetes.io/instance-type
                       operator: In
                       values: ['SL1.1-2048', 'SL1.2-4096', 'SL1.2-8192']
                     - key: karpenter.sh/capacity-type
                       operator: In
                       values: ['on-demand']
                 expireAfter: 720h
         disruption:
             consolidationPolicy: WhenEmptyOrUnderutilized
             consolidateAfter: 0s
         limits:
             cpu: '1000'
             memory: 1000Gi
     ```
   </details>

   <details>
     <summary>Пример манифеста NodePool при использовании сетевого плагина Cilium</summary>

     ```yaml
     apiVersion: karpenter.sh/v1
     kind: NodePool
     metadata:
         name: default
     spec:
         template:
             spec:
                 nodeClassRef:
                     name: default
                     kind: SelectelNodeClass
                     group: karpenter.k8s.selectel
                 startupTaints:
                     - key: node.cilium.io/agent-not-ready
                       value: "true"
                       effect: NoExecute
                     - key: node.cilium.io/agent-not-ready
                       effect: NoSchedule
                 requirements:
                     - key: topology.kubernetes.io/zone
                       operator: In
                       values: ['ru-7a', 'ru-7b']
                     - key: node.kubernetes.io/instance-type
                       operator: In
                       values: ['SL1.1-2048', 'SL1.2-4096', 'SL1.2-8192']
                     - key: karpenter.sh/capacity-type
                       operator: In
                       values: ['on-demand']
                 expireAfter: 720h
         disruption:
             consolidationPolicy: WhenEmptyOrUnderutilized
             consolidateAfter: 0s
         limits:
             cpu: '1000'
             memory: 1000Gi
     ```
   </details>

2. Примените манифест:

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

#### Параметры блока requirements в NodePool \{#requirements-in-nodepool}

В объекте NodePool в блоке `requirements` описываются требования к создаваемым нодам.

<CustomTable>
  <table>
    <tbody>
      <tr>
        <th>Параметр</th>
        <td>Описание</td>
      </tr>

      <tr>
        <th>karpenter.sh/capacity-type</th>

        <td>
          Тип создаваемых нод:

          * `on-demand` — непрерываемые ноды;
          * или `spot` — прерываемые ноды
        </td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-category</th>
        <td>Линейка конфигурации. Например, Standard Line (`SL`) или GPU Line (`GL`). Подробнее о конфигурациях в инструкции [Конфигурации](/cloud-servers/create/configurations.mdx#server-flavors-list)</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-family</th>
        <td>Линейка конфигурации и поколение линейки. Например, `SL1` или `GL1`</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-generation</th>
        <td>Поколение линейки. Например, `1` или `2`</td>
      </tr>

      <tr>
        <th>node.kubernetes.io/instance-type</th>
        <td>Конфигурации (флейворы). Например, `["SL1.1-2048", "SL1.2-4096", "SL1.2-8192"]`. Конфигурации можно посмотреть в подразделе [Список флейворов фиксированной конфигурации во всех пулах](/cloud-servers/create/configurations.mdx#server-flavors-full-list) инструкции [Конфигурации](/cloud-servers/create/configurations.mdx)</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-cpu</th>
        <td>Количество vCPU. Например, `Gt: "4"` — больше 4</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-memory</th>
        <td>Объем оперативной памяти в ГиБ. Например, `Gt: "8"` — больше 8 ГиБ</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-gpu-manufacturer</th>
        <td>Производитель графического процессора (GPU). Доступное значение — `["NVIDIA"]`</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-gpu-name</th>
        <td>Название GPU для конфигураций с GPU. Например, `["A100", "H100"]`. Доступные GPU можно посмотреть в подразделе [Доступные GPU](/managed-kubernetes/create/create-cloud-gpu-cluster.mdx#available-gpu) инструкции [Создать кластер Managed Kubernetes с GPU](/managed-kubernetes/create/create-cloud-gpu-cluster.mdx)</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-gpu-count</th>
        <td>Количество GPU. Например, `Gt: "0"` — больше одного графического процессора</td>
      </tr>

      <tr>
        <th>karpenter.k8s.selectel/instance-local-disk</th>
        <td>Указывает, используется ли в качестве загрузочного диска [локальный диск](/cloud-servers/volumes/about-local-disks.mdx) облачной платформы. Доступные значения — `["true"]` и `["false"]`</td>
      </tr>

      <tr>
        <th>topology.kubernetes.io/zone</th>
        <td>Сегменты пула, где могут быть созданы группы нод. Например, `["ru-7a", "ru-7b"]`. Доступные значения можно посмотреть в подразделе [Managed Kubernetes](/infrastructure/availability-matrix.mdx#managed-kubernetes) инструкции [Матрицы доступности](/infrastructure/availability-matrix.mdx)</td>
      </tr>
    </tbody>
  </table>
</CustomTable>

<Formbricks />
