При работе с платформой контейнеризации Kubernetes важно контролировать использование ресурсов у таких объектов кластера, как поды. С целью контроля запросов и ограничений в Kubernetes используются два параметра: запросы (requests
) и ограничения (limits
), при помощи которых можно гибко настраивать ограничения на потребляемые ресурсы — сколько ресурсов может использовать запускаемый под в кластере Kubernetes. В данной статье мы рассмотрим использование запросов и ограничений в Kubernetes на практических примерах.
Для работы с запросами и ограничениями в кластере Kubernetes нам понадобится:
Готовый кластер Kubernetes, которой можно арендовать в панели управления (раздел Kubernetes). Для теста нам будет достаточно кластера состоящего из двух нод. Также кластер можно развернуть вручную, арендовав необходимое количество облачных или выделенных (железных) серверов и самостоятельно произвести настройку операционной системы и установив необходимые пакеты.
Установленная программа с графическим интерфейсом Lens, при помощи которой можно подключаться к кластерам Kubernetes и полноценно управлять всеми объектами кластера, или установленная консольная утилита kubectl
для управления кластером Kubernetes. kubectl
можно установить на все популярные операционные системы — Windows, Linux, macOS.
В первую очередь нам необходимо арендовать кластер Kubernetes.
1) Переходим на страницу авторизации и входим в аккаунт при помощи логина или адреса электронной почты и пароля.
2) После успешной авторизации отобразится панель управления текущего проекта. Переходим в раздел «Kubernetes» в меню слева и нажимаем на кнопку «Создать»:
3) На текущий момент кластеры доступны в Санкт-Петербурге и Москве. Выберите нужный регион:
4) На втором шаге сначала выбираем версию кластера Kubernetes. В выпадающем меню доступно несколько версий на выбор:
Обратите внимание, что после того как кластер будет создан, изменить версию уже будет нельзя.
Далее выбираем, сколько воркер-нод (worker node — рабочих нод) будет максимально доступно в создаваемом кластере. Доступно две конфигурации:
Для наших задач нам достаточно использовать тариф с лимитом на 10 воркер-нод.
5) На третьем этапе выбираем конфигурацию для воркер-нод. В качестве технических характеристик доступны несколько тарифов на выбор:
Мы воспользуемся тарифом, который включает в себя одноядерный процессор с тактовой частотой 3.3 ГГц, два гигабайта оперативной памяти и 30 гигабайт места на NVMe-диске. При использовании Kubernetes для рабочих проектов с реальной нагрузкой вам необходимо выбрать ту конфигурацию, которая будет отвечать вашим потребностям.
Также на этом этапе можно задать имя для кластера, которое будет отображаться в панели управления, а также выбрать необходимое количество нод кластера (кнопка «Количество нод»). Мы выберем две мастер-ноды.
6) На четвертом этапе необходимо выбрать следующие дополнения для кластера:
7) На последнем этапе можно задать имя для кластера, которое будет отображаться в панели управления или оставить автоматически сгенерированное имя, а также выбрать проект:
8) Перед тем как заказать кластер Kubernetes, проверьте итоговую информацию:
Если на вашем аккаунте недостаточно средств, то будет выведено предупреждение о необходимости пополнить баланс. Для оплаты нажмите на кнопку «Заказать». После оплаты откроется Дашборд кластера Kubernetes, где можно будет найти данные кластера, включая его версию и технические характеристики нод:
Создание кластера может занять до 10 минут. Для подключения к кластеру можно использовать программу Lens, чтобы управлять кластером и всеми его объектами через графический интерфейс.
Также можно использовать консольную утилиту kubectl
. При этом стоит отметить, что при установке Lens также будет автоматически установлена утилита kubectl
.
kube
1) Для начала переходим в панель управления кластером в меню «Информация». В разделе «Файл конфигурации» скачиваем конфигурационный файл кластера Kubernetes (он же файл kubeconfig
):
2) Как только Lens был установлен в вашей системе, запускаем программу и в меню слева переходим в раздел «Catalog (app)»:
3) В открывшемся меню выбираем секцию «Clusters»:
Далее справа снизу нажимаем на синюю кнопку со знаком плюс:
И выбираем директорию, в которую был скачан файл с конфигурацией Kubernetes, нажав на кнопку «Sync»:
После этого в списках доступных кластеров отобразится наш кластер:
При клике на имя кластера отобразится его панель управления:
Для начала рассмотрим в теории, что такое запросы и ограничения в 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) используются ядра. Например, если контейнеру необходимо выделить 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.
Рассмотрим использование запросов и ограничений на практике. Для начала запустим 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
Проверим, что deployment
был успешно создан:
kubectl get deployments -A
Также проверим статус пода:
kubectl get po -n ns-for-nginx
Файл deployment
и под были успешно запущены. Чтобы убедиться, что для пода с Nginx был задан минимальный запрос на ресурсы, воспользуемся командой kubectl describe pod
(где nginx-test-deployment-786d6fcb57-7kddf
— это имя запущенного пода):
kubectl describe pod nginx-test-deployment-786d6fcb57-7kddf -n ns-for-nginx
В выводе команды можно найти блок requests
, а в нем — ранее заданные минимальные требования для запуска нашего контейнера:
В примере выше мы создали 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
На скриншоте выше контейнеру были заданы и запросы (requests
) и ограничения (limits
). При таких квотах контейнер будет запущен на той ноде, на которой доступно 150 мегабайт оперативной памяти и 100 милиядер процессора. В тоже время контейнер не сможет потреблять более 1 гигабайта оперативной памяти и 1 ядра процессора.
Помимо ручного назначения ресурсов для каждого запускаемого контейнера, существует способ выделения квоты на конкретный namespace в кластере. Это можно реализовать при помощи механизма ResourceQuota
, который позволяет устанавливать ограничения на использование ресурсов в каждом конкретном namespace. ResourceQuota
предназначен для ограничения таких ресурсов, как процессор и оперативная память.
На практике использование ResourceQuota
выглядит следующим образом.
1) Создаем новый namespace
с настройкой квот:
kubectl create ns ns-for-resource-quota
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
будут заданы следующие ограничения:
3) Применяем файл:
kubectl apply -f test-resource-quota.yaml
4) Проверим свойства объекта ResourceQuota
:
kubectl get resourcequota resource-quota-test -n ns-for-resource-quota
Как можно заметить, у нас появились квоты на ресурсы.
Также проверим вывод команды kubectl describe ns
:
kubectl describe ns ns-for-resource-quota
Ранее созданный 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
kubectl get all -n ns-for-resource-quota
По итогу из три реплик пода будет запущено только две. В deployment
будет отображена ошибка, которая сообщает о том, что превышена квота на создание ресурсов (в данном случае мы пытаемся создать больше подов чем разрешено):
При этом оставшиеся две реплики пода с Nginx были успешно запущены:
Запросы и ограничения являются важнейшим механизмом в Kubernetes, благодаря которым можно гибко выделять и контролировать физические ресурсы кластера, чтобы не допустить неожиданных ошибок в запускаемых приложениях и проблем с самим кластером.