MAATRIX / Блог / Сколько RAM нужно для Plane

Сколько RAM нужно для Plane

MAATRIX

Plane берут как открытую замену Linear или Jira и первым делом ставят на VPS с 2 ГБ памяти — «это же просто трекер задач с канбан-доской». Через день-два контейнер api или worker падает по OOM, и причина не в самом Plane, а в том, что за интерфейсом на самом деле стоит не один процесс, а мини-кластер из семи-девяти контейнеров: база, кэш, очередь задач, S3-хранилище и несколько Python/Node-процессов поверх них. Разберём, из чего складывается расход памяти у Plane, сколько закладывать под разный размер команды и как урезать стек на маленьком сервере, не теряя функциональность.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Из чего состоит Plane и почему это не «ещё один Wekan»

Plane распространяется как self-hosted вариант через docker compose, и это не один бинарник с базой рядом, а полноценная SaaS-архитектура, развёрнутая локально. Типичный набор сервисов в docker-compose.yml (точные имена и состав немного отличаются между релизами — свой список стоит сверить командой docker compose config --services):

  • api — бэкенд на Django, отданный через gunicorn. Основная логика: проекты, задачи, права, интеграции. Каждый gunicorn-воркер — отдельный процесс с полной копией приложения в памяти.
  • worker и beat-worker — фоновые задачи на Celery: уведомления, экспорт, вебхуки, импорт из Jira/Linear, повторяющиеся джобы по расписанию. beat-worker только планирует запуск, сам джобы не выполняет, поэтому лёгкий.
  • web, space, admin — интерфейс на Next.js. В части релизов это три отдельных Node-процесса (основной воркспейс, публичные страницы для гостей, панель администратора), в других — объединены в один контейнер. Каждый Node-процесс на Next.js в SSR-режиме держит свой рантайм и кэш страниц.
  • plane-db — PostgreSQL, основное хранилище: проекты, задачи, комментарии, права доступа.
  • plane-redis — Redis, кэш сессий и результатов Celery.
  • plane-mq — брокер очереди для Celery, чаще всего RabbitMQ. У RabbitMQ фиксированная цена входа: Erlang VM занимает память практически одинаково что при пустой очереди, что при нагруженной.
  • plane-minio — S3-совместимое хранилище для вложений, аватаров и экспортов.
  • proxy — nginx, единая точка входа, связывает всё в один HTTP-адрес.
  • migrator — одноразовый контейнер миграций базы, запускается при обновлении и завершается, в постоянном потреблении не участвует.

Итог: считать нужно сумму memory footprint примерно десятка процессов, а не память одного «трекера задач». Именно поэтому официальные ожидания по железу у Plane заметно выше, чем у однобинарных инструментов вроде Gitea или Wekan.

Сколько RAM нужно по размеру команды

Ниже — ориентировочные цифры, собранные из архитектуры стека, а не измеренные бенчмарки: точное потребление зависит от версии, числа проектов и настроек воркеров у вас. Считайте их отправной точкой, а не гарантией.

СценарийУчастниковRAM минимумRAM комфортно
Тест / посмотреть, что это такое14 GB, впритык6 GB
Небольшая команда, пара проектов5-156 GB8 GB
Активная команда, несколько проектов, интеграции15-508 GB12 GB
Крупная организация, много фоновых задач50-150+12-16 GB16-24 GB, БД и MinIO — на отдельный сервер

Разница с однопроцессными self-hosted инструментами в том, что нижняя граница у Plane — это не «попробовать», а уже сумма фиксированных издержек десятка контейнеров. 2 ГБ RAM, которых хватает многим лёгким сервисам, здесь съедаются одним Postgres, Redis и RabbitMQ ещё до старта самого приложения.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Docker Compose: сколько памяти забирает каждый контейнер

Без явных лимитов Docker позволит любому контейнеру дорасти до предела хоста — на 4 ГБ VPS это обычно кончается тем, что gunicorn-воркеры api съедают память, нужную PostgreSQL под пиковый запрос, и падает не сам api, а база. Явные mem_limit не увеличивают доступную память, зато делают падение предсказуемым и локальным. Рабочий набор лимитов для сервера на 4-5 ГБ (тест/соло-режим), добавляется override-файлом поверх штатного docker-compose.yml:

services:
  plane-db:
    mem_limit: 512m
    mem_reservation: 256m

  plane-redis:
    mem_limit: 256m
    mem_reservation: 128m

  plane-mq:
    mem_limit: 400m
    mem_reservation: 200m

  plane-minio:
    mem_limit: 300m
    mem_reservation: 128m

  api:
    mem_limit: 700m
    mem_reservation: 400m
    environment:
      - GUNICORN_WORKERS=2

  worker:
    mem_limit: 500m
    mem_reservation: 300m
    environment:
      - CELERY_CONCURRENCY=2

  beat-worker:
    mem_limit: 200m
    mem_reservation: 100m

  web:
    mem_limit: 400m
    mem_reservation: 200m

  space:
    mem_limit: 300m
    mem_reservation: 150m

  admin:
    mem_limit: 300m
    mem_reservation: 150m

  proxy:
    mem_limit: 64m
    mem_reservation: 32m

Сумма лимитов здесь около 3,9 ГБ — то есть даже без единого активного пользователя стек просит запас сверху для пиков, отсюда и минимум в 4 ГБ из таблицы выше. Общий принцип подбора mem_limit/mem_reservation (лимит с запасом 20-30% лучше лимита впритык) разобран подробнее в статье как настроить Docker Compose для продакшена на VPS — для Plane эти правила работают без изменений, только компонентов больше.

Проверка фактического потребления после разворачивания:

docker compose config --services
docker stats --no-stream
free -h
docker inspect plane-api-1 --format='{{.State.OOMKilled}}'

PostgreSQL, Redis и очередь задач — где расход растёт незаметно

Три компонента дают основной «незаметный» расход, который легко упустить, если считать только видимые в интерфейсе действия:

  • PostgreSQL держит shared_buffers под кэш горячих страниц базы — по умолчанию небольшой, но с ростом числа проектов и задач стоит поднимать вручную. Если раньше не настраивали Postgres отдельно от Plane, базовые принципы разобраны в статье как установить и настроить PostgreSQL на VPS — они применимы и здесь, только plane-db уже развёрнут в контейнере за вас.
  • Redis в связке Plane используется как кэш сессий и промежуточное хранилище результатов Celery-задач — расход умеренный и растёт с числом одновременных сессий, а не с объёмом данных в базе. Общие принципы настройки — в статье как установить и настроить Redis на VPS.
  • Брокер очереди (обычно RabbitMQ) — самая недооценённая статья расхода. Erlang VM, на которой работает RabbitMQ, занимает память практически фиксированно вне зависимости от того, пустая очередь или под нагрузкой: это не постепенно растущий процесс, а константа, которую нужно просто заложить в бюджет с первого дня, а не ждать, что она «появится под нагрузкой».

Дополнительный множитель — параллелизм Celery. Каждый worker-процесс с CELERY_CONCURRENCY=N — это N параллельных исполнителей, и каждый держит в памяти полную копию Django-приложения с зависимостями (обычно 150-250 МБ на процесс, но это ориентир, не измеренное число для вашей версии). На 4 ГБ VPS CELERY_CONCURRENCY=4 — это уже отдельный повод для OOM независимо от нагрузки самого api.

MinIO и вложения — где растёт хранилище, а не память

MinIO в связке Plane отвечает за файлы: аватары, вложения к задачам, экспорты в CSV/PDF. В покое контейнер занимает немного — по архитектуре сопоставимо с лёгким HTTP-сервером, а не с базой данных. Но два момента стоит учитывать заранее:

  • Диск растёт быстрее, чем кажется, если команда активно прикладывает скриншоты и документы к задачам — а MinIO хранит файлы локально на том же VPS, если не подключено внешнее S3-совместимое хранилище. Если раньше не разворачивали MinIO отдельно, базовая настройка описана в статье как установить и настроить MinIO на VPS — те же принципы работают и для встроенного в Plane инстанса.
  • Одновременная загрузка/скачивание крупных файлов временно поднимает потребление памяти контейнером за счёт буферизации — на команду с частыми вложениями закладывайте mem_reservation для plane-minio выше базового.

Для команды от полусотни человек с активными вложениями разумно вынести хранилище на внешний S3-совместимый бакет вместо локального MinIO — это не только снимает нагрузку с диска и памяти VPS, но и упрощает бэкапы: файлы перестают быть частью снапшота сервера.

Как ужать Plane под маленький VPS

Если сервер меньше комфортного объёма из таблицы, есть рабочие способы срезать потребление без потери функциональности:

  • Снизить параллелизм там, где он избыточен. GUNICORN_WORKERS=1-2 для api и CELERY_CONCURRENCY=1-2 для worker — на команде до 10-15 человек очередь задач и так не нагружена, а память экономится линейно.
  • Проверить реальный список контейнеров. Если ваш релиз объединяет web, space и admin в один процесс — это заведомо меньше базового расхода, чем три отдельных Node-рантайма; если нет и админ-панель или публичные страницы не нужны — можно не поднимать соответствующий сервис вовсе, если инсталляция это позволяет.
  • Вынести PostgreSQL и MinIO за пределы VPS. Управляемая база или объектное хранилище у отдельного провайдера убирают два самых прожорливых по фиксированному оверхеду контейнера с локальной машины — остаются только api, воркеры и фронтенд.
  • Добавить swap как страховку от одиночного пика, а не как постоянный ресурс — RabbitMQ и PostgreSQL из-за свопа резко теряют в отзывчивости, поэтому это защита от разового всплеска (массовый импорт задач, одновременный вход всей команды после простоя), а не способ работать на постоянной нехватке памяти.

Признаки нехватки памяти различаются по компоненту, и это стоит уметь читать до падения сервиса в рабочее время:

docker stats --no-stream
dmesg -T | grep -i "killed process"
docker logs plane-mq-1 --tail 100 | grep -i "memory"
docker inspect plane-worker-1 --format='{{.State.OOMKilled}}'

Если в dmesg убит процесс postgres — упирается база и первым делом смотрите shared_buffers; если beam.smp (процесс Erlang) — это RabbitMQ, и лечится либо увеличением лимита, либо переносом брокера отдельно; если контейнер worker — снижайте CELERY_CONCURRENCY раньше, чем добавлять память.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Хватит ли 2 ГБ RAM для Plane?

Формально контейнеры могут стартовать, но уже PostgreSQL, Redis и RabbitMQ вместе почти выбирают этот объём до запуска самого приложения. Для рабочей инсталляции даже соло-теста закладывайте от 4 ГБ.

Можно ли убрать RabbitMQ или MinIO, чтобы сэкономить память?

Зависит от версии и способа установки — в части конфигураций брокер и очередь являются обязательной частью docker-compose набора и не выключаются флагом. Хранилище MinIO можно заменить на внешний S3-совместимый бакет через переменные окружения, это снимает один контейнер с локального сервера.

Что чаще падает первым — api, worker или база?

Обычно первым падает то, что настроено с наибольшим параллелизмом без лимита — чаще всего api при высоком GUNICORN_WORKERS или worker при высоком CELERY_CONCURRENCY, а не сама PostgreSQL: у базы обычно самый предсказуемый и стабильный профиль потребления из всего стека.

Стоит ли выносить PostgreSQL и MinIO на отдельный сервер?

Для команды до полусотни человек обычно не требуется — один VPS с явными mem_limit справляется. Разделять сервисы имеет смысл, когда локальный диск начинает упираться в объём вложений или когда бэкап всего стека одним снапшотом становится неудобным по времени.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →