Як виявити та вирішити проблему нестачі пам’яті та CPU на VPS: Реальний кейс

VPS сервер з Docker контейнерами періодично ставав недоступним – не відповідав SSH, сайт не працював. Після перезавантаження через хостинг-панель все запускалося нормально, але проблема повторювалася.

Характеристики сервера:

  • RAM: 4.8GB
  • CPU: 4 ядра
  • Диск: 34GB
  • OS: Ubuntu 22.04 LTS
  • Контейнери: Traefik, Nginx, PHP, MySQL, Redis, IoT система (Node.js)

Крок 1: Первинна діагностика після перезапуску

Перевірка системних ресурсів

Результат:

⚠️ Перша підозра: SWAP = 0 – немає резервної пам’яті!


Перевірка використання диску

Результат:

✅ Диск в нормі (41% використання).


Перевірка запущених контейнерів

Результат:

⚠️ Підозра: Багато контейнерів, деякі unhealthy.


Крок 2: Пошук “винуватця” – моніторинг ресурсів

Детальна статистика Docker контейнерів

КРИТИЧНИЙ РЕЗУЛЬТАТ:

🔴 ЗНАЙДЕНО ПРОБЛЕМУ!

iot-admin-panel:

  • CPU: 195% (майже 2 ядра з 4!)
  • RAM: 3.06GB (64% всієї пам’яті сервера!)

iot-pgadmin:

  • CPU: 68.76% (додатково навантажує)
  • RAM: 146MB

Топ процесів по пам’яті

Результат:

📊 Аналіз:

  • node next dev – Next.js в development режимі
  • python3 gunicorn – pgAdmin
  • Обидва процеси активно використовують ресурси

Крок 3: Пошук причини в логах

Перевірка системних логів

Результат:

⚠️ Помилки Docker після перезавантаження – контейнери не коректно зупинилися.


Перевірка OOM Killer (Out Of Memory)

Результат: Порожній вивід.

💡 Висновок: OOM Killer НЕ спрацював, але це лише тому що сервер завис раніше.


Крок 4: Розуміння причини

Чому Next.js dev режим з’їв всі ресурси?

Next.js в development режимі:

  • ✅ Hot Module Replacement (HMR) – перекомпіляція при зміні коду
  • ✅ Source maps для дебагу
  • ✅ Детальні логи помилок
  • ❌ Постійна компіляція TypeScript
  • ❌ Webpack Dev Server в пам’яті
  • ❌ Відсутність оптимізації коду

Що сталося:

  1. Next.js компілював код при старті
  2. Webpack зберігав всі модулі в RAM
  3. HMR слухав зміни файлів (додаткове навантаження)
  4. CPU 195% – постійна компіляція
  5. RAM 3GB – весь build в пам’яті
  6. Інші контейнери потребували пам’яті
  7. SWAP = 0 – немає резерву
  8. Система зависла – kernel не міг виділити пам’ять

Крок 5: Рішення проблеми

Рішення 1: Додати SWAP (негайно)

Результат після:

Тепер є резерв 2GB!


Рішення 2: Обмежити ресурси для контейнерів

Відкрити docker-compose.yml IoT проєкту:

Застосувати зміни:


Рішення 3: Перейти на Production режим

У docker-compose.yml:

Production режим Next.js:

  • ✅ Один раз компілює при старті
  • ✅ Оптимізований код (minified, tree-shaking)
  • ✅ Кешування build
  • CPU ~5% замість 195%
  • RAM ~300MB замість 3GB

Рішення 4: Налаштувати swappiness

Що це означає:

  • swappiness=60 (default) – використовує swap коли RAM 40% зайнята
  • swappiness=10 – використовує swap тільки коли RAM 90% зайнята
  • Для серверів рекомендується 10-20

Крок 6: Моніторинг для запобігання в майбутньому

Скрипт автоматичного моніторингу пам’яті

Додати в cron (кожні 5 хвилин):


Скрипт моніторингу CPU


Візуальний моніторинг з Netdata (опціонально)

Netdata покаже:

  • Real-time CPU, RAM, Disk, Network
  • Графіки за останні години/дні
  • Алерти при перевищенні порогів
  • Статистика по кожному контейнеру

Крок 7: Результати після виправлення

До виправлення

Проблеми:

  • Сервер періодично недоступний
  • SSH не відповідає
  • Сайти не працюють
  • Потрібен ручний перезапуск

Після виправлення

Результат:

  • ✅ Сервер стабільний 24/7
  • ✅ CPU знизився з 195% до 5% (в 39 разів!)
  • ✅ RAM знизилась з 3GB до 300MB (в 10 разів!)
  • ✅ Є резерв SWAP 2GB
  • ✅ Обмеження на контейнери
  • ✅ Автоматичний моніторинг

Алгоритм діагностики (checklist)

Коли VPS недоступний після перезапуску, використовуй цю послідовність:

1️⃣ Базова перевірка ресурсів

Що шукати:

  • SWAP = 0? → Додати swap
  • Диск > 90%? → Очистити
  • Load Average > кількість ядер? → Перевантаження CPU

2️⃣ Знайти проблемний контейнер

Що шукати:

  • CPU > 100%? → Оптимізувати або обмежити
  • RAM > 50% від ліміту? → Обмежити mem_limit
  • Unhealthy статус? → Перевірити логи

3️⃣ Перевірити логи

Що шукати:

  • “Out of memory” → Додати RAM або SWAP
  • “killed” → OOM Killer вбив процес
  • Постійні перезапуски → Помилка в додатку

4️⃣ Виправити проблему

Якщо нестача RAM:

Якщо високий CPU:

Якщо dev режим:


5️⃣ Налаштувати моніторинг


Корисні команди для діагностики

Моніторинг в реальному часі


Пошук проблем


Очистка ресурсів


Висновки

Причина проблеми

  1. Next.js dev режим використовував 195% CPU і 3GB RAM
  2. Відсутність SWAP – немає резерву пам’яті
  3. Немає обмежень на контейнери – могли з’їсти всі ресурси
  4. Відсутність моніторингу – не бачили проблему до краху

Рішення

  1. ✅ Додали SWAP 2GB
  2. ✅ Обмежили CPU до 1 ядра та RAM до 1GB
  3. ✅ Перейшли на production режим Next.js
  4. ✅ Налаштували автоматичний моніторинг

Результат

  • 📉 CPU: 195% → 5% (в 39 разів менше)
  • 📉 RAM: 3GB → 300MB (в 10 разів менше)
  • 📈 Стабільність: періодичні крахи → 24/7 uptime
  • 🔍 Моніторинг: немає → алерти кожні 5 хвилин

Додаткові рекомендації

Для production серверів завжди:

  1. Додавай SWAP = 2x RAM (мінімум 2GB)
  2. Обмежуй ресурси контейнерів через cpus і mem_limit
  3. Використовуй production режим для Node.js, Python, PHP
  4. Налаштуй моніторинг (cron скрипти або Netdata)
  5. Автозапуск Docker: sudo systemctl enable docker
  6. Регулярні бекапи через cron

Не роби:

  • ❌ Не запускай dev режим на production
  • ❌ Не ігноруй unhealthy контейнери
  • ❌ Не залишай сервер без SWAP
  • ❌ Не запускай багато контейнерів без обмежень

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *