Как ограничить ресурсы CPU и памяти для pod?

Как ограничить ресурсы CPU и памяти для Pod в Kubernetes

Основные понятия — requests и limits

  • requests — гарантия ресурсов для планировщика: сумма запросов контейнеров учитывается при решении, на какой ноде разместить Pod.

  • limits — верхний предел потребления, применяемый на уровне cgroup: если контейнер попытается превысить limit по CPU — он будет троттлиться (ограничиваться), по памяти — будет убит (OOMKilled).

Единицы: CPU задаётся в ядрах или мили-ядрах (1 = 1 ядро, 500m = 0.5 ядра). Память — в байтах с суффиксами Ki, Mi, Gi и т.д. (128Mi, 1Gi).

Где задать — в манифесте контейнера

Ограничения задаются в секции resources каждого контейнера в Pod/Deployment/StatefulSet:

containers:
\- name: app
image: myapp:latest
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"

Важно: ресурсы задаются на уровне контейнера; у Pod нет отдельного поля для суммарных ограничений — суммой контейнерных значений и оперирует планировщик.

Влияние на планирование и поведение

  • Планировщик использует requests для расчёта места на ноде (учитывая allocatable).

  • Если limits.cpu задан, а использование превысило limit — контейнер будет получать меньше CPU (throttling), но не будет убит.

  • Если память превысила limits.memory, ядро/oom-killer завершит процесс контейнера, Kubernetes пометит статус OOMKilled.

  • Если requests не заданы, планировщик считает их нулевыми — Pod может быть размещён легко, но риск перемещения/эвиктов и проблем с QoS увеличивается.

QoS-классы (влияют на приоритет при эвикшене)

  • Guaranteed — для каждого контейнера заданы и requests, и limits, и значения равны для CPU и памяти. Такие Pod’ы наиболее защищены от эвикшенов.

  • Burstable — заданы requests (или limits ≠ requests) — Pod получает частичную защиту.

  • BestEffort — ни requests, ни limits не заданы — наименее защищённые, первыми под ударом при давлении на ресурсы.

Политики на уровне namespace/кластера

  • LimitRange — задаёт дефолты, min/max значения и defaultRequest/defaultLimit в namespace; полезно, чтобы заставить разработчиков не забывать requests/limits. Пример (коротко): defaultRequest: cpu: "250m", memory: "256Mi".

  • ResourceQuota — ограничивает суммарные ресурсы в namespace (например, requests.cpu: "10", limits.memory: "20Gi"), предотвращая перепотребление.

Практические рекомендации

  • Всегда указывайте и requests, и limits для production-контейнеров.

  • Для стабильного QoS ставьте request == limit, если нужен Guaranteed.

  • Для приложений с пиковым характером можно давать меньший request и больший limit (burstable), но мониторьте throttling и OOM.

  • Проверяйте метрики (kubectl top pod с metrics-server) и логи OOMKilled (kubectl describe pod) при проблемах.

  • Используйте LimitRange чтобы стандартизировать значения в namespace и ResourceQuota для контролируемого мультиарендного окружения.

  • HPA (Horizontal Pod Autoscaler) по умолчанию опирается на использование CPU относительно requests — корректно заданные requests важны для правильного масштабирования.

Диагностика проблем

  • CPU-троттлинг: смотреть kubectl describe pod, kubectl top pod, прометей/метрики контроллера; высокая разница между usage и limits → возможны задержки.

  • OOMKilled: kubectl describe pod покажет статус OOMKilled и причину; анализировать потребление памяти и увеличить limits.memory или оптимизировать приложение.

  • Непланируемая плотность на ноде: проверять kubectl describe node (allocatable vs requests sum).