Контроль ресурсов Docker: лимиты CPU и памяти

Когда один контейнер поглощает все ресурсы хоста, OOM Killer может остановить критически важные сервисы, а CPU-спайки замедляют работу всей инфраструктуры. Мы настраиваем лимиты CPU и памяти для Docker-контейнеров, чтобы изолировать сбои и защитить ваши базы данных. Наша команда реализует проект под ключ: проводит аудит, внедряет конфигурации и обеспечивает последующую поддержку, чтобы ваша система работала стабильно.
Часто задаваемые вопросы

Мы помогаем командам настроить лимиты Docker-контейнеров, чтобы OOM Killer не убивал базы данных, а CPU-спайки не роняли продакшен. Memory leak в одном сервисе кладёт весь хост: ядро начинает убивать случайные процессы, и следующим может оказаться не проблемный контейнер, а Postgres. CPU-spike из-за кривого запроса замедляет все остальные сервисы на ноде одновременно. Наш подход — аудит, мониторинг и конфигурация под ключ. Как отмечается в документации Docker, рекомендуется устанавливать лимиты памяти и CPU для предотвращения ресурсной конкуренции. Закажите аудит Docker-инфраструктуры — оценим проект за 2 дня.

Почему OOM Killer убивает не тот процесс?

Без --memory ограничения Linux OOM Killer выбирает жертву по oom_score_adj и размеру потребляемой памяти. Docker-контейнеры по умолчанию имеют oom_score_adj=0. Postgres, который занимает 2GB shared_buffers, получит высокий score и будет убит раньше, чем NodeJS-контейнер с memory leak, который только что вырос до 3GB. Итог: база лежит, приложение живо.

С правильными лимитами Docker прибьёт именно тот контейнер, который превысил свой лимит. А если установить --memory-swap равным --memory, swap для контейнера тоже ограничен — он не сможет незаметно уходить в swap и деградировать по производительности.

Как правильно настроить лимиты контейнеров?

  1. Измерьте текущее потребление. Запустите docker stats и соберите данные за 7 дней через cAdvisor + Prometheus. Ключевые метрики: container_memory_working_set_bytes и container_cpu_usage_seconds_total. Обратите внимание на 90-й перцентиль — он покажет реальную нагрузку без выбросов.
  2. Определите пики. Для памяти используйте максимальное значение + 50% запас. Для CPU — смотрите p99 перцентиль, не среднее. Типичная ошибка: ориентироваться на среднее, из-за чего spike выбивает контейнер.
  3. Настройте limits и reservations. Жёсткий лимит (limits) не даст контейнеру выйти за рамки. Резервирование (reservations) гарантирует минимум при конкуренции. Например, для API сервиса ставьте memory limit 512m с запасом 20%.
  4. Добавьте алерты. Настройте оповещения на OOM events: docker events --filter type=container --filter event=oom. Также контролируйте CPU throttle: при превышении 80% quota срабатывает предупреждение.
  5. Проверьте под нагрузкой. Запустите нагрузочное тестирование с 50% загрузкой CPU и убедитесь, что ни один контейнер не превышает лимит, а latency остаётся в пределах SLA.

Ограничения памяти в Compose

services:
  api:
    image: myapp-api:latest
    deploy:
      resources:
        limits:
          memory: 512m
        reservations:
          memory: 256m
  worker:
    image: myapp-worker:latest
    deploy:
      resources:
        limits:
          memory: 1g
          cpus: "1.5"
        reservations:
          memory: 512m
          cpus: "0.5"

limits — жёсткий потолок. reservations — гарантированный минимум (Docker Swarm использует это для планирования размещения на нодах). Для standalone Compose v2+ лимиты работают напрямую, без --compatibility флага.

Какие CPU лимиты выбрать: shares или quota?

Docker предоставляет два механизма ограничения CPU, которые часто путают.

cpus (или --cpus) — это CFS quota. cpus: "0.5" означает, что контейнер получит не более 50% одного CPU-ядра за период 100ms. Это жёсткое ограничение: даже если хост не загружен, контейнер не получит больше. Жёсткий лимит cpus даёт в 2 раза более предсказуемую latency, чем cpu_shares.

cpu_shares — это относительный вес. По умолчанию 1024. Если у одного контейнера 512, у другого 2048 — при конкуренции первый получит 20% CPU, второй 80%. Но если хост свободен, оба получат столько, сколько нужно. Это мягкое ограничение, хорошо подходящее для batch-задач.

Тип Характер Когда использовать
cpus (quota) Жёсткий Критичные сервисы, требующие стабильной производительности
cpu_shares Мягкий Фоновые задачи, где важна утилизация, а не скорость
services:
  api:
    deploy:
      resources:
        limits:
          cpus: "2.0" # не более 2 ядер в любой момент
        reservations:
          cpus: "0.5" # гарантировано 50% ядра
  bg_worker:
    deploy:
      resources:
        limits:
          cpus: "0.5" # batch-worker не должен мешать API

Когда отключать OOM killer?

oom_kill_disable: true — одна из самых опасных настроек. Она отключает OOM killer для контейнера, что означает: при нехватке памяти ядро убьёт что-то другое вместо него. Используется только в крайних случаях (например, для Elasticsearch, который умеет самостоятельно управлять памятью).

Memory swap и OOM behaviour

---
services:
  app:
    mem_limit: 512m
    memswap_limit: 512m # swap = 0 (memswap_limit - mem_limit)
    oom_kill_disable: false # НЕ отключать OOM killer
---

Что входит в работу

  • Аудит текущих лимитов и конфигураций Docker Compose / Swarm.
  • Настройка мониторинга (cAdvisor + Prometheus) для сбора метрик.
  • Анализ пиков памяти и CPU по сервисам за 7 дней с учётом 90-го перцентиля.
  • Установка лимитов и reservations с учётом SLA.
  • Настройка алертов на OOM events.
  • Документация: runbook по управлению лимитами, политика масштабирования.
  • Передача знаний команде — обучение базовым командам и тюнингу.

Наши результаты

5+ лет опыта в DevOps, 50+ проектов по оптимизации Docker-инфраструктуры. После настройки лимитов клиенты фиксируют:

  • Экономию ресурсов хоста до 40%, что сокращает расходы на облако.
  • Снижение MTTR по OOM-инцидентам на 50%, уменьшение числа нештатных ситуаций в 3 раза.

Порядок работы

Запускаем мониторинг без лимитов — собираем данные о реальном потреблении. Анализируем пики памяти и CPU по сервисам. Устанавливаем лимиты и reservations. Настраиваем алерты на OOM events. Проверяем поведение под нагрузкой.

Чек-лист для самостоятельной проверки

  • Проверьте, что у каждого сервиса есть memory limit.
  • Установите --memory-swap равным --memory для отключения swap.
  • Добавьте алерты на OOM events.
  • Убедитесь, что cpu_shares не используются для критичных сервисов.
  • Протестируйте под нагрузкой с уровнем CPU 50-80%.
Масштаб Срок
Compose-стек до 5 сервисов 4–8 часов
Детальный анализ + мониторинг 1–2 дня
Docker Swarm с capacity planning 2–3 дня

Стоимость рассчитывается индивидуально после замера текущего потребления ресурсов. Получите консультацию — оценим ваш проект за 2 дня. Свяжитесь с нами для предварительного аудита.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139