Олег Марков
Как управлять Resources и Requests в Kubernetes
Введение
Понимание выделения и управления ресурсами — один из важнейших аспектов работы с Kubernetes. Если вы используете Kubernetes для развертывания своих приложений, вам точно нужно знать, как правильно указывать и ограничивать ресурсы — например, процессор и оперативную память — для ваших контейнеров. Благодаря грамотной настройке Resources (requests
и limits
) вы сможете избежать ситуаций, когда поды потребляют чрезмерно много ресурсов и мешают другим приложениям в кластере. Эта статья покажет, как устроено управление ресурсами, на что влияют настройки requests и limits, с какими граблями чаще всего сталкиваются разработчики, и какие практики позволяют держать всё под контролем.
Мы рассмотрим реальные YAML-фрагменты, объясним теорию и дадим комментарии для разных ситуаций. Если вы хотите, чтобы ваши приложения работали стабильно, а кластер не страдал от перегрузок, этот материал упростит вашу работу.
Что такое Requests и Limits в Kubernetes
Краткое определение
Перед тем как перейти к деталям, давайте определим, что означают ключевые параметры:
- Requests (запрошенные ресурсы) — минимальное количество ресурсов (CPU, память), которое Kubernetes гарантированно выделит контейнеру.
- Limits (лимиты) — верхний предел ресурсов для контейнера. Контейнер не сможет использовать больше этих значений.
Смотрите, что происходит: когда вы создаете под и указываете эти параметры, Kubernetes на их основе выполняет планирование и защиту кластера от чрезмерных нагрузок.
Для чего нужны Requests
Requests нужны для планирования размещения пода на правильном ноде. Если ваш контейнеру нужен хотя бы 1 vCPU и 512MiB памяти, Kubernetes будет искать такой нод, где эти ресурсы точно зарезервированы — меньше никак.
Для чего нужны Limits
Limits ограничивают аппетиты контейнера. Даже если на ноде свободно много памяти или CPU, контейнер никогда не получит больше, чем ему разрешено лимитом. Это особенно важно для защиты от утечек памяти или слишком жадных процессов.
Где и как указывать Requests и Limits
Основы декларации ресурсов
Вы прописываете requests и limits прямо внутри спецификации контейнера в манифестах Pod, Deployment, StatefulSet или других контроллеров.
Вот базовый пример для одного контейнера:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: myapp
image: myapp:latest
resources:
requests:
memory: "256Mi" # Kubernetes постарается гарантировать минимум 256MiB памяти
cpu: "500m" # И минимум 0.5 vCPU (500 millicpu)
limits:
memory: "512Mi" # Контейнер не сможет использовать больше 512MiB памяти
cpu: "1000m" # И больше 1 vCPU
Комментарии:
- Значения указываются в
resources: requests
иresources: limits
. - CPU измеряется в millicores (1000m = 1 CPU). Для requests и limits можно указывать разные значения.
- Избыток ресурсов на ноде не даст контейнеру использовать больше, чем указано в limits.
Форматы ресурсов
CPU
- 1 CPU = 1 vCPU/ядро. Можно задавать как 1, 0.5, 100m (милликоры).
- Пример:
"0.5"
эквивалентно"500m"
.
Память
- Память указывается в байтах (
B
), килобайтах (Ki
), мегабайтах (Mi
), гигабайтах (Gi
). - Пример:
"128Mi"
,"1Gi"
.
Как работает планирование и ограничения
Scheduling: как Kubernetes использует requests
Когда вы создаете под с requests, Kubernetes рассчитывает — хватит ли у ноды ресурсов, чтобы выделить requested значения для каждого контейнера. Пока не найдётся подходящий нод, под останется в статусе Pending.
Пример: если у ноды осталось только 300Mi памяти, а под просит 400Mi — Kubernetes даже не попробует туда его посадить.
Enforcement: что происходит при превышении limits
- Ограничение по CPU: если контейнер попытается использовать больше CPU, чем указано в limits, Kubernetes throttle-ит (замедляет) выполнение процесса.
- Ограничение по памяти: если контейнер превышает лимит по памяти, его процесс будет убит (OOMKilled). Перезапуск зависит от политики рестарта.
Типичные сценарии и фрагменты YAML
Один контейнер — разные Requests и Limits
resources:
requests:
cpu: "250m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
- Здесь контейнеру гарантируют минимум 0.25 CPU и 128 MiB памяти, но он не сможет съесть больше 0.5 CPU и 256 MiB.
Несколько контейнеров внутри пода
В каждом контейнере свои ресурсы:
apiVersion: v1
kind: Pod
metadata:
name: multi-container
spec:
containers:
- name: frontend
image: frontend-img
resources:
requests:
cpu: "100m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "128Mi"
- name: backend
image: backend-img
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
Использование в Deployments
Так же указываются в шаблонах подов:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: sample-container
image: sample-img
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "300m"
memory: "256Mi"
- То, что указано в манифесте шаблона, будет применяться к каждому поду.
NS-контролирование: ResourceQuotas и LimitRanges
Ограничение ресурсов на Namespace
Иногда вы хотите застраховаться от случайного создания сотни подов, каждый из которых потребляет бесконечно много ресурсов. Для этого служат объекты типа ResourceQuota и LimitRange.
ResourceQuota
Позволяет лимитировать общее использование ресурсов в Namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "2" # Всего можно запрашивать максимум 2 CPU
requests.memory: "1Gi"
limits.cpu: "4"
limits.memory: "2Gi"
pods: "10" # Не более 10 подов в namespace
Если кто-то попробует создать еще под или запросить больше ресурсов, чем указано, Kubernetes не разрешит это сделать.
LimitRange
Назначает минимальные и максимальные requests/limits для подов или контейнеров в Namespace:
apiVersion: v1
kind: LimitRange
metadata:
name: container-limits
namespace: dev
spec:
limits:
- type: Container
defaultRequest:
cpu: 100m
memory: 128Mi
default:
cpu: 500m
memory: 256Mi
max:
cpu: 1
memory: 512Mi
Если разработчик не указал requests или limits — будут применяться defaultRequest и default. Значения max запрещают указание большего лимита.
Практические советы по управлению ресурсами
Как подобрать значения requests и limits
- Анализируйте историю использования ресурсов. Если приложение уже крутится, смотрите на среднее и пиковое потребление с помощью метрик (например, Prometheus, Grafana, kubectl top).
- Requests = минимально необходимое. Может быть чуть больше среднего, чтобы не было частых тормозов при пиковой нагрузке.
- Limits = максимально допускаемое. Пусть будет с запасом, но не слишком большим. Например, limit не должен превышать request более чем в 2-3 раза.
Как увидеть, сколько ресурсов потребляет ваш под
Используйте команду:
kubectl top pod <pod-name>
Это покажет реальное потребление CPU/Memory каждым подом.
Что делать, если не указали requests и limits
Если значения не установлены и в Namespace нет LimitRange с default, контейнеры могут потреблять любые ресурсы, пока не исчерпают лимиты ноды. Это опасно, особенно для памяти — приложение может слопать всю память хоста и вызвать OOM на всех подах ноды.
Рекомендации по CPU
- Планируйте requests примерно по среднему потреблению, но не близко к нулю.
- Для коротких всплесков CPU можно поставить limit выше, чем request.
- Если приложение чувствительно к задержкам (например, веб-серверы), лимит не должен сильно ограничивать производительность.
Рекомендации по памяти
- Память не масштабируется эластично, как CPU. Приложение может упасть (OOMKilled), если не рассчитать limit.
- Не ставьте limit слишком близко к request — может привести к неожиданным рестартам из-за ООМ.
Примеры ошибок и как их избегать
Пример ошибки: только limits без requests
resources:
limits:
cpu: "2"
memory: "4Gi"
В этом случае, если в Namespace нет LimitRange, Kubernetes считает, что pod не требует никаких ресурсов для планирования (requests=0). Под будет запущен даже на ноде с малым количеством ресурсов, но после запуска может перегружать хост и конкурировать на равных со всеми.
Совет: Всегда указывайте requests, даже если они совпадают с limits.
Пример ошибки: слишком высокие requests
Если каждое приложение просит слишком много ресурсов через requests, планировщик не сможет распределять поды эффективно — часть ресурсов может простаивать, многие поды будут висеть в Pending.
Совет: Регулярно пересматривайте usage и requests, не завышайте_defaults.
Особенности с autoscaling (HPA и VPA)
Horizontal Pod Autoscaler (HPA)
HPA (kubectl autoscale
) масштабирует количество подов на основе метрик, обычно CPU и/или памяти. Для HPA крайне важно указывать requests, потому что он на них ориентируется при расчете процента загрузки.
Vertical Pod Autoscaler (VPA)
VPA может автоматически корректировать requests и limits для подов. Перед использованием — убедитесь, что ваши приложения выдерживают перезапуски, потому что масштабирование VPA вызывает рестарт.
Инструменты для мониторинга ресурсов
- kubectl top
- Prometheus + kube-state-metrics
- Grafana дашборды
- Kubernetes Metrics Server
Их использование помогает находить неэффективно настроенные requests и limits, а также своевременно обнаруживать утечки или завышенное потребление.
Как трактовать события и статус подов
При превышении лимита по памяти — обычно видим событие OOMKilled
(список событий — kubectl describe pod <pod>
).
Если не хватает лимитов в Namespace, возникает ошибка при создании (Status Reason: FailedScheduling
). В описании пода подскажет причину.
Правильное управление ресурсами — фундамент для стабильной и эффективной работы кластера Kubernetes. Requests и limits позволяют находить баланс между необходимой гарантией доступности приложений и справедливым использованием инфраструктуры. Тестируйте и мониторьте выбранные значения: идеально подобранные настройки удерживают систему в оптимальной форме.
Частозадаваемые технические вопросы по теме
1. Как изменить ресурсы для уже запущенного Deployment?
Измените манифест Deployment (requests/limits) и примените его снова командой:
kubectl apply -f deployment.yaml
Kubernetes плавно перезапустит поды с новыми настройками.
2. Как узнать, какой нод занял контейнер и какие на нем есть ресурсы?
Получить имя ноды, где работает под:
kubectl get pod <pod-name> -o wide
Посмотреть ресурсы ноды:
kubectl describe node <node-name>
или
kubectl top node
3. Как увидеть причину сбоя (например, почему под OOMKilled)?
Проверьте события через:
kubectl describe pod <pod-name>
Или посмотрите статус последнего контейнера:
kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'
4. Могут ли requests превышать limits?
Нет, requests всегда должны быть меньше или равны limits. Если попытаться указать requests больше limits, манифест не пройдет валидацию.
5. Как задать разные ресурсы для dev и prod окружений?
Используйте разные YAML-манифесты или шаблонизаторы (например, Helm), указывая нужные values для разных окружений. Например, для production — более высокие значения requests/limits, для dev — ниже, чтобы не тратить ресурсы впустую.
Постройте личный план изучения Kubernetes до уровня Middle — бесплатно!
Kubernetes — часть карты развития DevOps
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Kubernetes
Лучшие курсы по теме

Kubernetes и Helm
Антон Ларичев
Docker и Ansible
Антон Ларичев