логотип PurpleSchool
логотип PurpleSchool

Как ограничить ресурсы используя Limits в Kubernetes

Автор

Олег Марков

Введение

В Kubernetes эффективное распределение вычислительных ресурсов между контейнерами и приложениями играет ключевую роль. Без правильных ограничений какое-то приложение может занять слишком много CPU или памяти, из-за чего другие сервисы окажутся «голодными» или даже будут завершены системой. Kubernetes предоставляет механизм для явного ограничения использования ресурсов контейнерами с помощью параметров Limits и Requests, и сегодня мы детально разберём, как именно эти ограничения на ресурсы (limits) работают, для чего они нужны, и как ими управлять.

Ограничения ресурсов в Kubernetes: основы

Что такое ресурсы в Kubernetes

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

Requests vs Limits: в чем разница

Здесь важно понимать два понятия:

  • Requests (запросы) — минимальное количество ресурса, которое Kubernetes выделит контейнеру. Если все Pods запросили больше ресурсов, чем есть в узле, новые Pods не запускаются.
  • Limits (лимиты) — это жесткий предел: контейнер не сможет использовать больше установленного значения этого ресурса.

Requests и Limits могут быть разными или совпадать в зависимости от ваших целей.

Пример: почему это важно

Представьте, что в кластере запускается сервис, который иногда активно использует CPU. Без ограничений он может «съесть» весь процессор на ноде, создав лаг для остальных контейнеров. Если задать предел, вы защищаете стабильность всей системы.

Как работают limits в Kubernetes

Где задаются ограничения

Ограничения ресурсов задаются на уровне контейнеров в спецификации Pod (или Deployment, StatefulSet и так далее), в секции resources для каждого контейнера.

Давайте посмотрим, как выглядит базовый пример

apiVersion: v1
kind: Pod
metadata:
  name: nginx-limited
spec:
  containers:
    - name: nginx
      image: nginx:latest
      resources:
        requests:
          memory: "64Mi"    # Минимум 64 MiB памяти
          cpu: "250m"       # Минимум 0.25 CPU
        limits:
          memory: "128Mi"   # Не больше 128 MiB памяти
          cpu: "500m"       # Не больше 0.5 CPU

Комментарии поясняют, как limits и requests управляют памятью и CPU для контейнера nginx. В этом примере контейнер гарантировано получит 250 мили-CPU (0.25 CPU) и 64 мегабайта памяти, но не сможет превысить лимит в 0.5 CPU и 128 мегабайт памяти.

За что отвечают limits

  • cpu — максимальное количество процессорного времени. Если контейнер пытается использовать больше, его процессы будут «замедлять».
  • memory — предел оперативной памяти. Превышение этого лимита приводит к тому, что процесс убивает ядро (OOM kill).

Обратите внимание: превышение лимита CPU ведёт лишь к замедлению, а лимита памяти — к принудительному завершению.

Как Kubernetes применяет limits

Kubernetes взаимодействует с container runtime (например, Docker, containerd), чтобы установить ограничения на уровне cgroups в Linux. Система ядра следит, чтобы процессы не превышали выделенные ресурсы.

Давайте разберём это на более практическом примере.

Пример с несколькими контейнерами

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-limits
spec:
  containers:
  - name: frontend
    image: frontend:latest
    resources:
      limits:
        memory: "256Mi"
        cpu: "1"
  - name: backend
    image: backend:latest
    resources:
      limits:
        memory: "512Mi"
        cpu: "2"

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

Как считать значения resources

  • CPU указывается в ядер (целые значения) или мили-CPU (1000m = 1 CPU, 500m = 0.5 CPU)
  • Память указывается в байтах (B), килобайтах (Ki), мегабайтах (Mi), гигабайтах (Gi), и т.д.

Пример: "500Mi" — это 500 «меби-байт», не 500 мегабайт (MB). 1 Mi = 1024^2 байта.

Что будет, если не задать limits

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

Примеры настройки limits в различных объектах

Применение limits для Deployment

Давайте создадим Deployment, где nginx ограничен по ресурсам:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-limited-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"

Этот пример показывает, как limits работают в типичных production-объектах Kubernetes.

Использование defaults через LimitRange

Чтобы не забывать проставлять limits для каждого контейнера, используйте LimitRange. Так можно задать лимиты по умолчанию для всего namespace.

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: dev
spec:
  limits:
  - default:
      cpu: 500m
      memory: 256Mi
    defaultRequest:
      cpu: 200m
      memory: 128Mi
    type: Container

Размещая этот объект в namespace dev, вы добиваетесь, что все контейнеры автоматически получат значения по умолчанию, если их не указать явно.

Советы, рекомендации и подводные камни

Как выбирать правильные значения limits

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

Как проверить текущие limits

Для любого pod запустите:

kubectl get pod <имя-pod> -o json | jq .spec.containers[].resources

Здесь я использовал jq для более удобного отображения ресурсов каждого контейнера.

Остановка контейнера из-за превышения лимита памяти

Если ваш контейнер завершается с ошибкой OOMKilled, посмотрите события:

kubectl describe pod <имя-pod>

В строках событий (Events) будет видно, что pod был убит из-за Memory limit exceeded.

Изменение limits в уже созданных объектах

Для изменения ресурсов используйте kubectl edit или отредактируйте манифест и примените его заново:

kubectl edit deployment <имя>

При изменении limits происходит rolling update (если это Deployment).

Короткий обзор дополнительных возможностей

Ограничения на уровне Namespace с ResourceQuota

Вы можете ограничить общий объём ресурсов на namespace:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
  namespace: dev
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi

Так можно предотвратить злоупотребление ресурсами отдельным проектом или командой.

Настройка limits для нестандартных ресурсов

Если ваш кластер поддерживает GPU или другие специфические ресурсы, их тоже можно писать в limits. Пример для GPU NVIDIA:

resources:
  limits:
    nvidia.com/gpu: 1 # нужен 1 GPU

Это потребует наличия device plugin для GPU на worker-нодах.

Инструменты для наблюдения за потреблением ресурсов

  • kubectl top — покажет текущую нагрузку на pod'ы или ноды.
  • Prometheus + Grafana — лучшее решение для мониторинга ресурсов и анализа.

Пример просмотра загруженности пода:

kubectl top pod <имя-pod>

Вы увидите потребление CPU и памяти «живьём».

Использование limits в CI/CD

Вставляйте секцию resources с limits в шаблоны деплоймента ваших приложений — это best practice для Production среды. Часто для helm charts уже есть параметры values для настройки limits.

Как узнать, почему pod не стартует из-за requests/limits

Если Pod не стартует, посмотрите описание:

kubectl describe pod <имя-pod>

В разделе Events будет видно, если на ноде не хватает ресурсов для выделенных requests или limits слишком большие.

Как поступать с мультитенантными кластерами

  • Применяйте LimitRange и ResourceQuota для отдельных namespace.
  • Мониторьте потребление ресурсов и своевременно пересматривайте значения limits.

Заключение

Ограничение ресурсов с помощью limits в Kubernetes — важнейший механизм поддержания стабильности и безопасности в распределённом окружении. Грамотно подобранные лимиты защищают инфраструктуру от ран-ауэй контейнеров, минимизируют неожиданные остановки сервисов и повышают эффективность использования вычислительных мощностей кластера. Используйте limits вместе с requests, LimitRange и ResourceQuota, а для контроля применяйте инструменты мониторинга — так вы обеспечите безопасность и производительность ваших приложений.

Частозадаваемые технические вопросы по теме статьи и ответы на них

1. Как удалить LimitRange из namespace, если он мешает нужной конфигурации?
Удалите объект с помощью команды:
shell kubectl delete limitrange <имя-овъекта> -n <namespace>

2. Как узнать, используются ли дефолтные или явно прописанные limits в поде?
Используйте команду:
shell kubectl get pod <имя-pod> -o yaml | grep -A5 "resources:" Тут покажутся заданные ограничения. Дефолтные limits не прописываются явно в объекте pod — смотрите LimitRange вашего namespace.

3. Можно ли менять limits для работающего pod без пересоздания?
Нет, limits меняются только на уровне pod spec, для этого требуется пересоздание pod (например, rolling update для Deployment).

4. Могут ли контейнеры внутри одного pod видеть друг друга по потребляемому ресурсу?
Нет, limits назначаются для каждого контейнера отдельно. Но если один контейнер превышает лимиты памяти, это может привести к завершению всего pod.

5. Как задать limits для нескольких сред (dev, stage, prod) через helm?
Используйте values.yaml в helm charts, объявив отдельные параметры для limits и requests. Например: yaml resources: limits: cpu: {{ .Values.resources.limits.cpu }} memory: {{ .Values.resources.limits.memory }} Для каждой среды задайте свои значения в соответствующем values-<env>.yaml.

Стрелочка влевоИспользование логирования в KubernetesНастройка Ingress с Nginx в KubernetesСтрелочка вправо

Постройте личный план изучения Kubernetes до уровня Middle — бесплатно!

Kubernetes — часть карты развития DevOps

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Kubernetes

Terraform и Kubernetes инфраструктура как кодНастройка и использование Runners в KubernetesНастройка и деплой PostgreSQL в KubernetesСравнение и интеграция Openshift и KubernetesПримеры интеграции GitHub Actions и KubernetesDeploy приложений в Kubernetes - пошаговое руководство для начинающих и не толькоКак настроить CD в KubernetesИнтеграция Ansible в KubernetesИнтеграция CI/CD с Jenkins и KubernetesИнтеграция Kubernetes с GitLab - Автоматизация CI CD в облачной инфраструктуреГайд по DevOps инструментам в KubernetesОсобенности платформы Deckhouse в Kubernetes
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Kubernetes и Helm

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Docker и Ansible

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Микросервисы

Антон Ларичев
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий