Больше не нужно искать работу мечты — присоединяйтесь к команде Клауда

Запросы и ограничения Kubernetes

Александр Бархатов
Александр Бархатов
Технический писатель
20 сентября 2024 г.
33
13 минут чтения
Средний рейтинг статьи: 5

При работе с платформой контейнеризации Kubernetes важно контролировать использование ресурсов у таких объектов кластера, как поды. С целью контроля запросов и ограничений в Kubernetes используются два параметра: запросы (requests) и ограничения (limits), при помощи которых можно гибко настраивать ограничения на потребляемые ресурсы — сколько ресурсов может использовать запускаемый под в кластере Kubernetes. В данной статье мы рассмотрим использование запросов и ограничений в Kubernetes на практических примерах.

Предварительные требования

Для работы с запросами и ограничениями в кластере Kubernetes нам понадобится:

  • Готовый кластер Kubernetes, которой можно арендовать в панели управления (раздел Kubernetes). Для теста нам будет достаточно кластера состоящего из двух нод. Также кластер можно развернуть вручную, арендовав необходимое количество облачных или выделенных (железных) серверов и самостоятельно произвести настройку операционной системы и установив необходимые пакеты. 

  • Установленная программа с графическим интерфейсом Lens, при помощи которой можно подключаться к кластерам Kubernetes и полноценно управлять всеми объектами кластера, или установленная консольная утилита kubectl для управления кластером Kubernetes. kubectl можно установить на все популярные операционные системы — Windows, Linux, macOS.

Аренда кластера Kubernetes

В первую очередь нам необходимо арендовать кластер Kubernetes.

1) Переходим на страницу авторизации и входим в аккаунт при помощи логина или адреса электронной почты и пароля.

2) После успешной авторизации отобразится панель управления текущего проекта. Переходим в раздел «Kubernetes» в меню слева и нажимаем на кнопку «Создать»:

Image27

3) На текущий момент кластеры доступны в Санкт-Петербурге и Москве. Выберите нужный регион:

Image1

4) На втором шаге сначала выбираем версию кластера Kubernetes. В выпадающем меню доступно несколько версий на выбор:

Image17

Обратите внимание, что после того как кластер будет создан, изменить версию уже будет нельзя.

Далее выбираем, сколько воркер-нод (worker node — рабочих нод) будет максимально доступно в создаваемом кластере. Доступно две конфигурации:

  • до 10 воркер-нод
  • до 100 воркер-нод

Image3

Для наших задач нам достаточно использовать тариф с лимитом на 10 воркер-нод.

5) На третьем этапе выбираем конфигурацию для воркер-нод. В качестве технических характеристик доступны несколько тарифов на выбор:

Image15

Мы воспользуемся тарифом, который включает в себя одноядерный процессор с тактовой частотой 3.3 ГГц, два гигабайта оперативной памяти и 30 гигабайт места на NVMe-диске. При использовании Kubernetes для рабочих проектов с реальной нагрузкой вам необходимо выбрать ту конфигурацию, которая будет отвечать вашим потребностям.

Также на этом этапе можно задать имя для кластера, которое будет отображаться в панели управления, а также выбрать необходимое количество нод кластера (кнопка «Количество нод»). Мы выберем две мастер-ноды.

6) На четвертом этапе необходимо выбрать следующие дополнения для кластера:

  • Nginx ingress — это обратный прокси-сервер (reverse proxy server), который предоставляет сетевой доступ к приложениям, развернутым внутри кластера. При помощи Nginx ingress можно предоставить доступ во внешнюю сеть (интернет) для запускаемых приложений внутри кластера Kubernetes (по умолчанию доступ в интернет у разворачиваемых приложений в кластере отсутствует). Ознакомиться более подробно c ingress-контроллерами, включая Nginx-контроллер, можно по ссылке. Так как в данной статье упор будет сделан исключительно на запросах и ограничениях ресурсов для приложений, мы выключим параметр Nginx ingress.
  • CNI — расшифровывается как Container network interface (сетевой интерфейс контейнеров). Данный интерфейс используется для обеспечения сетевой доступности между узлами кластера. Для Kubernetes разработано большое количество различных сетевых плагинов, каждый из которых поддерживает различные функции. При аренде кластера вы можете выбрать один из четырех поддерживаемых плагинов: flannel, calico, canal, weave. Для наших целей нам достаточно выбрать flannel.

Image26

7) На последнем этапе можно задать имя для кластера, которое будет отображаться в панели управления или оставить автоматически сгенерированное имя, а также выбрать проект:

Image14

8) Перед тем как заказать кластер Kubernetes, проверьте итоговую информацию:

Image19

Если на вашем аккаунте недостаточно средств, то будет выведено предупреждение о необходимости пополнить баланс. Для оплаты нажмите на кнопку «Заказать». После оплаты откроется Дашборд кластера Kubernetes, где можно будет найти данные кластера, включая его версию и технические характеристики нод:

Image29

Создание кластера может занять до 10 минут. Для подключения к кластеру можно использовать программу Lens, чтобы управлять кластером и всеми его объектами через графический интерфейс. 

Также можно использовать консольную утилиту kubectl. При этом стоит отметить, что при установке Lens также будет автоматически установлена утилита kubectl.

kube

Подключение к кластеру Kubernetes с помощью Lens

1) Для начала переходим в панель управления кластером в меню «Информация». В разделе «Файл конфигурации» скачиваем конфигурационный файл кластера Kubernetes (он же файл kubeconfig):

Image13

2) Как только Lens был установлен в вашей системе, запускаем программу и в меню слева переходим в раздел «Catalog (app)»:

Image9

3) В открывшемся меню выбираем секцию «Clusters»:

Image30

Далее справа снизу нажимаем на синюю кнопку со знаком плюс:

Image12

И выбираем директорию, в которую был скачан файл с конфигурацией Kubernetes, нажав на кнопку «Sync»:

Image8

После этого в списках доступных кластеров отобразится наш кластер:

Image11

При клике на имя кластера отобразится его панель управления:

Image21

Что такое запросы и ограничения в Kubernetes

Для начала рассмотрим в теории, что такое запросы и ограничения в Kubernetes.

Запросы (Requests) — механизм в кластере Kubernetes, который отвечает за предоставление физических ресурсов, таких как оперативная память и ядер процессора, которые будут выделены для запускаемого контейнера. Простыми словами, запросы в Kubernetes — это минимальные системные требования, которые необходимы приложению для своей полноценной работы.

Ограничения (Limits) — механизм в кластере Kubernetes, который отвечает за ограничение физических ресурсов (оперативная память и ядра процессора) для запускаемого контейнера. Иными словами, ограничения в Kubernetes — это максимальные значения физических ресурсов, которые гарантируют, что запускаемое приложение не сможет получить больше ресурсов, чем указано в ограничениях. Контейнер сможет использовать ресурсы только до того предела, который указан в Limits.

Механизмы запросов и ограничений применяются только к объектам типа «под» и указываются в конфигурационных файлах пода, включая файлы типа deployment, StatefulSet, ReplicaSets.

Запросы (requests) добавляются в блок containers при помощи параметра resources. В разделе resources необходимо добавить блок requests, который состоит из двух значений: cpu (запрос на ресурсы процессора) и memory (запрос на ресурсы оперативной памяти). Синтаксис запросов выглядит следующим образом:

containers:
…
        resources:
            requests:
                cpu: "1.0"
                memory: "150Mi"

В данном примере для запуска контейнера на выбранной ноде кластера должно присутствовать минимум одно свободное ядро процессора и 150 мегабайт оперативной памяти.

Ограничения (limits) задаются по той же схеме, только используется параметр limits, например:

containers:
…
        resources:
            limits:
                cpu: "2.0"
                memory: "500Mi"

В данном примере контейнер не сможет использовать более двух ядер процессора и не более 500 мегабайт оперативной памяти.

В качестве единиц измерения запросы и лимиты устанавливаются в:

  • CPU — в милликорах (миллиядрах)
  • RAM — в байтах

Для ресурсов процессора (CPU) используются ядра. Например, если контейнеру необходимо выделить 1 физическое ядро процессора то в манифесте необходимо указать 1.0. Если же вам необходимо выделить пол-ядра то необходимо указать 0.5. Ядро можно разбить логически на миллиядра, например можно выделить 100m, что означает одну тысячную ядра (1 целое ядро процессора содержит в себе 1000 миллиядер).

Оперативная память (RAM) указывается в байтах. Поддерживаются  целые числа, а также суффиксы E, P, T, G, M, k. Например, если контейнеру необходимо выделить 1 гигабайт оперативной памяти то необходимо указать 1G, в мегабайтах это будет выглядеть как 1024M, в килобайтах это будет 1048576k и т.д.

Параметры requests и limits можно не указывать, однако стоит помнить, что в случае, если оба параметра не заданы, то запускаемый контейнер с приложением сможет запуститься на любой доступной ноде кластера вне зависимости от количества свободных ресурсов, а также использовать столько ресурсов, сколько физически доступно на каждой ноде. Фактически кластер будет выделять излишние ресурсы. Данная практика может крайне негативно повлиять на работоспособность всего кластера, так как велики риски возникновения таких ошибок, как OOM (Out of memory — нехватка оперативной памяти) и OutOfcpu (нехватка мощностей процессора). С целью предотвращения данных ошибок были придуманы механизмы запросов и ограничений в Kubernetes.

Практическое использование запросов и ограничений в Kubernetes

Рассмотрим использование запросов и ограничений на практике. Для начала запустим deployment-файл с образом Nginx, в котором зададим только запросы (requests). 

В конфигурации ниже для запуска пода с контейнером на ноде должно присутствовать минимум 100 миллиядер процессора (1/1000 процессора) и 150 мегабайт свободной оперативной памяти:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test-deployment
  namespace: ns-for-nginx
  labels:
    app: nginx-test
spec:
  selector:
    matchLabels:
      app: nginx-test
  template:
    metadata:
      labels:
        app: nginx-test
    spec:
      containers:
        - name: nginx-test
          image: nginx:1.25
          resources:
            requests:
              cpu: "100m"
              memory: "150Mi"

Прежде чем запускать deployment, создадим новый namespace с именем ns-for-nginx:

kubectl create ns ns-for-nginx

После создания namespace запустим файл deployment при помощи команды:

kubectl apply -f nginx-test-deployment.yml

Image28

Проверим, что deployment был успешно создан:

kubectl get deployments -A

Image22

Также проверим статус пода:

kubectl get po -n ns-for-nginx

Image5

Файл deployment и под были успешно запущены. Чтобы убедиться, что для пода с Nginx был задан минимальный запрос на ресурсы, воспользуемся командой kubectl describe pod (где nginx-test-deployment-786d6fcb57-7kddf — это имя запущенного пода):

kubectl describe pod nginx-test-deployment-786d6fcb57-7kddf -n ns-for-nginx

В выводе команды можно найти блок requests, а в нем — ранее заданные минимальные требования для запуска нашего контейнера:

Image10

В примере выше мы создали deployment, который устанавливает только минимально требуемые ресурсы для запуска. Добавим ограничения для запускаемого контейнера на уровне 1 целого ядра процессора и 1 гигабайта оперативной памяти, создав новый файл типа deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-test-deployment-2
  namespace: ns-for-nginx
  labels:
    app: nginx-test2
spec:
  selector:
    matchLabels:
      app: nginx-test2
  template:
    metadata:
      labels:
        app: nginx-test2
    spec:
      containers:
        - name: nginx-test2
          image: nginx:1.25
          resources:
            requests:
              cpu: "100m"
              memory: "150Mi"
            limits:
              cpu: "1.0"
              memory: "1G"

Создадим deployment в кластере:

kubectl apply -f nginx-test-deployment2.yml

Используя команду kubectl describe, убедимся, что запросы и лимиты были применены (где nginx-test-deployment-2-6d5df6c95c-brw8n — это имя пода):

kubectl describe pod nginx-test-deployment-2-6d5df6c95c-brw8n -n ns-for-nginx

Image24

На скриншоте выше контейнеру были заданы и запросы (requests) и ограничения (limits). При таких квотах контейнер будет запущен на той ноде, на которой доступно 150 мегабайт оперативной памяти и 100 милиядер процессора. В тоже время контейнер не сможет потреблять более 1 гигабайта оперативной памяти и 1 ядра процессора.

Использование ResourceQuota

Помимо ручного назначения ресурсов для каждого запускаемого контейнера, существует способ выделения квоты на конкретный namespace в кластере. Это можно реализовать при помощи механизма ResourceQuota, который позволяет устанавливать ограничения на использование ресурсов в каждом конкретном namespace. ResourceQuota предназначен для ограничения таких ресурсов, как процессор и оперативная память. 

На практике использование ResourceQuota выглядит следующим образом.

1) Создаем новый namespace с настройкой квот:

kubectl create ns ns-for-resource-quota

Image7

2) Далее создаем объект ResourceQuota:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: resource-quota-test
  namespace: ns-for-resource-quota
spec:
  hard:
    pods: "2"
    requests.cpu: "0.5"
    requests.memory: "800Mi"
    limits.cpu: "1"
    limits.memory: "1G"

В данном примере для всех создаваемых объектов в namespace с именем ns-for-resource-quota будут заданы следующие ограничения:

  • Можно создавать максимум 2 пода.
  • Минимальное количество ресурсов процессора, которое необходимо для запуска подов, составляет 0.5 миллиядер процессора.
  • Минимальное количество ресурсов оперативной памяти, необходимой для запуска подов, составляет 800 мегабайт.
  • Лимиты на использование процессора установлены в одно ядро процессора — больше выделить не получится.
  • Лимиты на использование оперативной памяти заданы в один гигабайт оперативной памяти — больше выделить не получится.

3) Применяем файл:

kubectl apply -f test-resource-quota.yaml

Image16

4) Проверим свойства объекта ResourceQuota:

kubectl get resourcequota resource-quota-test -n ns-for-resource-quota

Image18

Как можно заметить, у нас появились квоты на ресурсы.

Также проверим вывод команды kubectl describe ns:

kubectl describe ns ns-for-resource-quota

Image25

Ранее созданный namespace с именем ns-for-resource-quota был создан с соответствующей квотой на ресурсы.

5) Пример пода с Nginx со следующей конфигурацией:

apiVersion: apps/v1
kind: Deployment
metadata:
  name:  nginx-with-quota
  namespace: ns-for-resource-quota
  labels:
    app:   nginx-with-quota
spec:
  selector:
    matchLabels:
      app:  nginx-with-quota
  replicas: 3
  template:
    metadata:
      labels:
        app:  nginx-with-quota
    spec:
      containers:
      - name:  nginx
        image:  nginx:1.22.1
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 100m
            memory: 100Mi

Укажем три реплики пода с Nginx для проверки механизма. Также создадим квоту на минимальное предоставление ресурсов для запуска контейнеров и укажем лимиты, чтобы контейнеры не потребляли ресурсов больше, чем задано. 

Применяем файл с конфигурацией:

kubectl apply -f nginx-deployment-with-quota.yaml

Image2

kubectl get all -n ns-for-resource-quota

Image23

По итогу из три реплик пода будет запущено только две. В deployment будет отображена ошибка, которая сообщает о том, что превышена квота на создание ресурсов (в данном случае мы пытаемся создать больше подов чем разрешено):

Image4

При этом оставшиеся две реплики пода с Nginx были успешно запущены:

Image6

Заключение

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

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
20 сентября 2024 г.
33
13 минут чтения
Средний рейтинг статьи: 5
Пока нет комментариев