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

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

MAATRIX

Jenkins ставят по инструкции с минимумом в пару гигабайт, а через месяц эксплуатации сервер начинает подвисать под вечер, сборки зависают в очереди, а веб-интерфейс отвечает секундами. Причина почти всегда не в контроллере как таковом, а в том, что на нём же по умолчанию выполняются сами сборки. Разберём память Jenkins по частям — JVM-контроллер, плагины, job'ы и агенты — и посчитаем, сколько реально нужно под вашу нагрузку.

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

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

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

Короткий ответ: сколько RAM нужно для Jenkins

Цифры для контроллера — то есть для машины, где живёт сам Jenkins и веб-интерфейс. Сборки в расчёт не идут: они считаются отдельно, ниже.

RAMЧто реально помещаетсяЧестный комментарий
1 ГБКонтроллер с executors=0 на built-in node, до 20 job, 20–30 плагиновУстановка пройдёт, но первая же сборка прямо на контроллере всё уронит
2 ГБКонтроллер-оркестратор, все сборки на отдельном агенте, 50–100 jobРабочий минимум для команды из 3–5 разработчиков
4 ГБПлюс Blue Ocean, Kubernetes/Docker-плагины, multibranch pipelines, до 200–300 jobВариант по умолчанию, который советуем чаще всего
8 ГБСотни job, длинные Pipeline-скрипты, история сборок за годыЕсли пока не готовы разносить агенты по отдельным машинам
16 ГБ+1000+ job, десятки multibranch-репозиториев, крупная монолитная инсталляцияАгенты сюда не входят — считайте их отдельным пунктом бюджета

Главное: требования Jenkins — это контроллер и агенты отдельно, и смешивать их в одну цифру — типичная ошибка новичка. Контроллер — это оркестратор: он раздаёт задачи, хранит конфиги и историю, крутит веб-интерфейс. Сама компиляция, тесты и сборка образов происходят на агентах — и именно там расход памяти скачет от сотен мегабайт до нескольких гигабайт на один job. Смешаете роли — получите ситуацию, когда один тяжёлый npm run build кладёт не только сборку, но и админку с логами всех остальных проектов.

Куда уходит память в контроллере: JVM, плагины и job'ы

Jenkins — это java-процесс, и память в нём делится на heap (объекты приложения) и metaspace (загруженные классы). Версию и параметры JVM смотрите сразу:

systemctl status jenkins
sudo journalctl -u jenkins --since "1 hour ago" | grep -i "java\|jvm"

Пустая инсталляция без плагинов и job держит на удивление немного — сотни мегабайт RSS. Но так Jenkins почти никто не эксплуатирует: типичный рабочий инстанс несёт сотню-другую плагинов (Git, Pipeline, Credentials, Blue Ocean, Docker, Kubernetes, Slack-нотификации, LDAP), и каждый плагин — это загруженные классы в metaspace плюс собственные фоновые потоки и кеши. Конкретную цифру для своей инсталляции надёжнее снять самостоятельно (см. раздел про измерение ниже), чем ориентироваться на чужой снимок.

Второй источник расхода — job'ы и их конфигурация. Каждый job — объект в памяти контроллера плюс закешированные данные: последние сборки, параметры, результаты. Multibranch pipeline умножает эту цифру незаметно: каждая ветка репозитория с Jenkinsfile становится отдельным job. Пять репозиториев по двадцать активных веток — это не пять, а сотня job'ов.

Третий, самый недооценённый источник — сама модель Pipeline. Declarative и Scripted Pipeline выполняются через CPS (Continuous Passing Style): каждый шаг превращается в узел графа выполнения (FlowNode), и весь граф держится в памяти контроллера, пока pipeline выполняется — включая parallel-блоки. Длинный pipeline с десятками стадий занимает заметно больше памяти на контроллере, чем короткий линейный скрипт, даже если сама сборка идёт на внешнем агенте — оркестрация графа остаётся на контроллере.

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

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

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

Executors на контроллере — главная ошибка новичков

Свежий Jenkins после установки создаёт «Built-In Node» (бывший «master») с двумя executors по умолчанию — готовая ловушка. Executor на built-in node означает, что сама сборка — mvn install, npm run build, docker build — выполняется в том же процессе и в той же куче JVM, что и сам Jenkins. Один тяжёлый job съедает память контроллера напрямую, и в худшем случае веб-интерфейс перестаёт отвечать для всех, пока OOM не остановит процесс целиком.

Правильная практика — свести число executors на built-in node к нулю и выносить сборки на агентов:

  1. Manage Jenkins → Nodes → Built-In Node → Configure → Number of executors: 0.
  2. Подключить агента: постоянный через SSH (Manage Nodes → New Node → Launch agents via SSH) или временный через Docker/Kubernetes-плагин, который поднимает контейнер на каждый job и убирает его после.
  3. В Jenkinsfile указывать конкретный agent { label 'build' } вместо неявного выполнения на контроллере.

Разница принципиальная: если агент — отдельный процесс, падение сборки по памяти убивает только job, а контроллер и веб-интерфейс продолжают работать. Если сборка идёт прямо на built-in node — падает всё сразу, включая доступ к логам, по которым вы стали бы разбираться в причине.

Агенты и тяжёлые сборки: где память расходится по-настоящему

Инбаунд-агент сам по себе лёгкий — JVM-процесс на несколько десятков мегабайт, который держит соединение с контроллером и запускает шаги сборки как дочерние процессы. Память уходит в сами инструменты сборки:

Что делает jobОриентировочный пик RAMКомментарий
mvn install на среднем Java-проектесотни МБ — 1–2 ГБЗависит от числа модулей и параллельных потоков сборки
npm ci && npm run build (Webpack, Vite, Next)1–3 ГБЧастая причина JavaScript heap out of memory на слабом агенте
docker build с buildkitдо 1–2 ГБ на процесс сборкиПлюс место на диске под слои — считайте отдельно
Тесты с поднятием БД/сервисов в контейнерахзависит от числа сервисовКаждый service-контейнер в Jenkinsfile — это ещё один процесс с своей памятью

Это ориентиры из практики, а не бенчмарк — у вас цифры отличаются в зависимости от числа зависимостей и размера кодовой базы. В Docker- и Kubernetes-плагинах для эфемерных агентов память каждого пода ограничивается явно (resourceLimitMemory в podTemplate, параметры контейнера — в Docker-плагине), и это плюс, а не минус: сборка упадёт сама, с понятным кодом выхода в своём логе, а не утащит за собой соседние job'ы на общем агенте.

Если несколько executors настроены на одном агенте (частая экономия — гонять 3–4 job параллельно на одной машине), считайте пик как сумму пиков одновременных сборок, а не память одной. Именно так и случается двух-трёхкратный перерасход: агент рассчитан на одну сборку, а фактически стартуют три сразу. Как считать ресурсы под сборочный сервер, если Jenkins — не единственная роль на машине, разобрано в статье про ресурсы VPS для разработчика и CI/CD; логика лимитов на контейнеры пригодится и для Docker-агентов — в статье про лимиты CPU и памяти в Docker.

Настройка JVM: heap, metaspace и GC

Параметры JVM задаются переменной JAVA_OPTS, а место, куда её вписывать, зависит от способа установки. Для пакета Debian/Ubuntu (systemd-юнит) — через override, без правки самого юнита:

sudo systemctl edit jenkins
[Service]
Environment="JAVA_OPTS=-Xms512m -Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/lib/jenkins/heapdump"

Для Docker-образа jenkins/jenkins:lts — той же переменной в окружении контейнера (environment: - JAVA_OPTS=... в compose-файле); для запуска WAR напрямую — аргументом перед -jar jenkins.war. Синтаксис флагов одинаковый везде.

Что делает каждый флаг: -Xmx — жёсткий потолок кучи, за него JVM не выйдет, вместо непредсказуемого захвата всей памяти сервера вы получите управляемый OutOfMemoryError. -Xms разумно ставить примерно четвертью от -Xmx, чтобы JVM не тратила время на расширение кучи при старте. -XX:MaxMetaspaceSize — отдельный лимит на классы плагинов; без него metaspace растёт неограниченно, и утечка в старом плагине незаметно съедает память, отведённую под heap. -XX:+HeapDumpOnOutOfMemoryError с -HeapDumpPath пригодится один раз — когда будете разбираться, какой плагин виноват в OOM: дамп открывается в Eclipse MAT и показывает, какие объекты держат память.

Честная оговорка: современные JDK (11+) по умолчанию уже используют G1GC, отдельно включать его обычно не нужно. В контейнерах, где память сервиса меняется динамически, вместо фиксированного -Xmx иногда удобнее -XX:MaxRAMPercentage=75.0 — куча пересчитывается от лимита контейнера автоматически.

Как измерить реальное потребление и не гадать

Пик из cgroup — так же, как для любого systemd-сервиса:

cat /sys/fs/cgroup/system.slice/jenkins.service/memory.peak
grep -E '^(anon|file) ' /sys/fs/cgroup/system.slice/jenkins.service/memory.stat

memory.peak — максимум за время жизни юнита в байтах; именно с ним сравнивайте тариф, а не с текущим потреблением в момент затишья.

Встроенная диагностика. Manage Jenkins → System Information показывает текущие параметры JVM и heap. Плагин Metrics, если установлен, отдаёт Prometheus-совместимый эндпоинт — держите его на локальном адресе и закрывайте firewall'ом, наружу пускайте только сам Jenkins через reverse-proxy.

Прямой JVM-инструмент. Найдите PID процесса и снимите статистику по сборщику мусора:

sudo -u jenkins jps -l
jstat -gc <PID> 5000

Колонка OU (old generation used), растущая без остановки между сборками, — верный признак утечки памяти, обычно в конкретном плагине, а не в самом Jenkins.

Журнал после падения. Что искать:

sudo journalctl -u jenkins --since "yesterday" | grep -iE "outofmemory|gc overhead|killed"
sudo dmesg -T | grep -iE "out of memory|oom-kill"

java.lang.OutOfMemoryError: Java heap space в логе Jenkins значит, что не хватило -Xmx — либо контроллеру при большой нагрузке job'ов, либо (если executors не вынесены) прямо во время сборки. Запись oom-kill в dmesg с процессом java — сигнал, что памяти не хватило уже на уровне системы, и здесь помогает не только тюнинг heap, но и своп как временная страховка от разового пика — как его правильно посчитать, разобрано в статье про настройку swap-файла.

Какой сервер взять в MAATRIX под Jenkins

Честный минимум для контроллера: 1 vCPU, 2 ГБ RAM, 40 ГБ NVMe. Подходит, если все сборки вынесены на отдельные агенты, а на самой машине живёт только оркестрация. Для команды из 3–5 разработчиков этого достаточно с запасом.

Комфортный вариант: 2 vCPU, 4 ГБ RAM, 80 ГБ NVMe. Контроллер с полусотней плагинов, Blue Ocean, Kubernetes-плагином для эфемерных агентов, multibranch pipelines на несколько репозиториев. Советуем эту конфигурацию чаще всего — она не упирается в потолок даже при росте числа job до пары сотен.

Если инсталляция крупная: 4 vCPU, 8 ГБ, 160 ГБ NVMe. Сотни job, длинные Pipeline-скрипты, история сборок за годы. Дешевле и надёжнее здесь — держать контроллер отдельно от агентов физически: агент под тяжёлые сборки разумно брать отдельным сервером и масштабировать по мере роста нагрузки.

Диск тоже стоит закладывать с запасом: артефакты сборок, workspace каждого job и слои Docker-образов копятся быстрее, чем кажется — регулярная чистка через Discard old builds и docker system prune на агентах экономит немало места. Если вместо Jenkins присматриваетесь к встроенному CI других систем — типичные проблемы разобраны в статье про раннер GitLab CI на сервере.

Сервер под Jenkins на MAATRIX разворачивается за минуты, конфигурацию — ядра, память, диск — меняете без переезда на новый тариф, когда число job или executors выросло. Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT, без иностранной карты и посредников.

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

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

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

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

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

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

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

Да, если сборки не выполняются на самом контроллере — только оркестрация, а executors на built-in node сведены к нулю. Для команды из 3–5 разработчиков это рабочий минимум.

Почему сборка на built-in node опаснее, чем на агенте?

Она выполняется в том же процессе JVM, что и сам Jenkins: тяжёлый job может забрать память контроллера целиком и уронить веб-интерфейс для всех, а на отдельном агенте падает только сама сборка.

Сколько памяти закладывать под агента?

Зависит от инструмента: для Java-проекта с Maven обычно хватает 1–2 ГБ, для сборки фронтенда через npm/Webpack — 2–3 ГБ. При нескольких параллельных executors на одном агенте суммируйте пики, а не берите память одной сборки.

Jenkins стал медленнее через несколько месяцев работы — почему?

Проверьте jstat -gc на растущий OU между сборками — признак утечки в плагине. Обновите плагины и сделайте Safe Restart; если не помогло, смотрите heap dump по -XX:+HeapDumpOnOutOfMemoryError.

Нужен ли Kubernetes-плагин для маленькой команды?

Не обязательно — SSH-агент на отдельном VPS решает ту же задачу изоляции проще. Kubernetes-плагин оправдан, когда нагрузка неровная и хочется поднимать агентов только на время сборки.

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

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

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