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







