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

Сколько RAM нужно для Woodpecker CI

MAATRIX

Если вы искали self-hosted CI/CD после того как Drone сменил лицензию, скорее всего уже наткнулись на Woodpecker — и первый практический вопрос звучит так: какой сервер под него брать, чтобы не упереться в OOM на первом же пайплайне с npm install. Ответ не сводится к одной цифре — Woodpecker состоит из двух разных процессов с разным аппетитом к памяти, и путать их — самая частая ошибка при планировании сервера. Разберём по частям: что жрёт память в самом Woodpecker, сколько закладывать на старте и что менять, когда параллельных сборок становится больше одной.

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

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

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

Что такое Woodpecker CI и почему это не просто форк ради форка

Woodpecker — прямой потомок Drone CI: в 2019 году, когда Drone перешёл на Business Source License (фактически закрыв бесплатное использование в некоторых сценариях), часть сообщества форкнула последнюю открытую версию и продолжила развивать её как полностью open-source проект под Apache 2.0. С тех пор кодовые базы разошлись — Woodpecker получил свой backend для Kubernetes, локального exec-режима, автоскейлер агентов и собственный синтаксис конфигов (.woodpecker.yml), хотя концептуально многое узнаваемо для тех, кто работал с Drone.

Для вас как для того, кто выбирает сервер, важны два практических следствия. Во-первых, никакого vendor lock-in и скрытых платных тарифов — весь функционал доступен в self-hosted варианте бесплатно. Во-вторых, архитектура «сервер + агенты» унаследована от Drone почти без изменений, а значит и логика расчёта ресурсов похожа на то, что было у Drone CI — если раньше держали Drone, память под Woodpecker считается теми же прикидками.

Из чего складывается расход памяти: сервер и агент — это разные процессы

Ключевая вещь, которую нужно понять до аренды сервера: woodpecker-server и woodpecker-agent — это два независимых процесса, и почти вся память съедается вторым.

Сервер (woodpeckerci/woodpecker-server) — это Go-бинарник плюс встроенная база данных (по умолчанию SQLite, хранится в /var/lib/woodpecker/). Он отдаёт веб-интерфейс, API, хранит историю пайплайнов и координирует агентов по gRPC (порт 9000) и HTTP (порт 8000). Сам по себе он лёгкий — как ориентир, в простое это обычно первые сотни мегабайт, и даже на десятках репозиториев без активных сборок сервер редко становится узким местом по памяти. Реальную цифру для вашей нагрузки лучше смотреть через docker stats, а не верить чужим замерам — зависит от версии, числа репозиториев и глубины истории билдов.

Агент (woodpecker-agent) сам по себе тоже почти ничего не весит в простое — это демон, который держит gRPC-соединение с сервером и ждёт задач. Вся память уходит не на сам агент, а на контейнеры шагов пайплайна, которые он поднимает через docker.sock (при WOODPECKER_BACKEND=docker, это значение по умолчанию в стандартном docker-compose развёртывании). То есть если ваш .woodpecker.yml гоняет npm ci, собирает Docker-образ и поднимает тестовую Postgres — это три контейнера, и именно их суммарное потребление определяет, сколько RAM нужно узлу с агентом.

Отсюда практическое правило: сервер почти всегда можно держать на минимальной VPS, а под агент память считается исходя из того, что реально происходит в ваших пайплайнах, а не исходя из самого Woodpecker.

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

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

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

Минимальная конфигурация: соло-проект на одной VPS

Для личного проекта или маленького сайд-проекта — один-два репозитория, редкие пуши, простые шаги (линтер, тесты, сборка одного Docker-образа без экзотики) — сервер и агент прекрасно уживаются на одной машине:

ПараметрЗначение
vCPU1-2
RAM2 GB
Диск20-30 GB SSD (образы Docker кэшируются)
WOODPECKER_MAX_WORKFLOWS1 (по умолчанию)

По умолчанию WOODPECKER_MAX_WORKFLOWS=1 — агент выполняет ровно один workflow за раз, что для соло-разработки чаще плюс, чем минус: пики нагрузки предсказуемы, вы не рискуете словить два параллельных docker build одновременно на слабой машине. На 2 GB такой сценарий работает без напряга; на 1 GB — тоже реально, но тесно, особенно если в пайплайне есть шаг с реальной сборкой фронтенда (webpack/vite под нагрузкой легко просит 500 MB-1 GB сам по себе).

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

Сколько нужно для команды: параллельные workflows и WOODPECKER_MAX_WORKFLOWS

Как только в игру вступает команда — несколько разработчиков пушат параллельно, PR-сборки должны стартовать без очереди — придётся поднимать WOODPECKER_MAX_WORKFLOWS выше единицы. Официальный пример docker-compose от разработчиков Woodpecker (docker-compose.example.yaml в репозитории проекта) сам по умолчанию ставит агенту WOODPECKER_MAX_WORKFLOWS: 2 — это разумная отправная точка для небольшой команды.

Здесь память считается прямым умножением: если один "тяжёлый" workflow (сборка образа + тесты) потребляет условно 1-1.5 GB на пике, то при WOODPECKER_MAX_WORKFLOWS=3 агенту нужно закладывать не менее 4-5 GB запаса, потому что три workflow могут одновременно оказаться на самом тяжёлом шаге. Это тот случай, где цифры сильно зависят от вашего конкретного стека — приведённые числа именно ориентир для прикидки, а не гарантия.

СценарийvCPURAMКомментарий
Соло / pet-project1-22 GBСервер + агент вместе
Команда 2-5 человек, 2 параллельных workflow2-44-6 GBСервер + агент вместе, либо агент отдельно
Активный CI: сборка образов, интеграционные тесты с БД48 GBАгент лучше вынести на отдельный сервер
Monorepo / несколько сервисов, 3+ параллельных workflow4-816 GB+Несколько агентов на разных VPS

Важный момент: разносить сервер и агент по разным машинам обычно нужно не из-за памяти сервера (она невелика), а чтобы изоляция сборочных нагрузок не роняла веб-интерфейс и API, пока кто-то гоняет тяжёлый билд. Агенты подключаются к серверу исходящим gRPC-соединением на порт 9000, так что держать их за NAT без белого IP — нормально, лишь бы был исходящий доступ до сервера.

Docker backend против Kubernetes: что это меняет для памяти

По умолчанию (и в подавляющем большинстве self-hosted установок) Woodpecker использует WOODPECKER_BACKEND=docker — агент монтирует /var/run/docker.sock и поднимает контейнер на каждый шаг пайплайна через локальный Docker daemon. Это самый предсказуемый вариант для расчёта: вся память видна через docker stats на той же машине, где крутится агент.

Есть ещё Kubernetes backend — его берут, когда CI уже часть большей инфраструктуры на k8s и хочется, чтобы шаги пайплайна планировались как обычные поды с собственными requests/limits. Здесь память считается не по агенту, а по кластеру в целом: Woodpecker Kubernetes backend позволяет задавать resources на уровне шага прямо в .woodpecker.yml, и это удобно, если разные шаги реально нуждаются в разной памяти (линтер — 128 MB, сборка образа — 2 GB). Для небольшой команды тащить ради этого целый Kubernetes обычно избыточно — если у вас уже есть кластер, почитайте про то, когда k3s выгоднее Docker Swarm, а если кластера нет — оставайтесь на Docker backend, он проще и для 90% сценариев CI/CD этого достаточно.

Отдельно стоит exec/local backend — шаги выполняются прямо на хосте без контейнеризации. Он экономит память на оверхеде самого Docker, но ломает изоляцию между шагами и требует, чтобы все зависимости пайплайнов были предустановлены на хосте агента. На практике встречается редко и только там, где docker-in-docker по каким-то причинам неприемлем.

Пример: docker-compose с адекватными лимитами и как избежать OOM

Рабочий минимальный докер-компоуз для сервера и агента на одной машине выглядит так:

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v3
    ports:
      - "8000:8000"
    environment:
      - WOODPECKER_OPEN=false
      - WOODPECKER_ADMIN=your-git-username
      - WOODPECKER_HOST=https://ci.example.com
      - WOODPECKER_GITEA=true
      - WOODPECKER_GITEA_URL=https://git.example.com
      - WOODPECKER_GITEA_CLIENT=${WOODPECKER_GITEA_CLIENT}
      - WOODPECKER_GITEA_SECRET=${WOODPECKER_GITEA_SECRET}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker/
    restart: unless-stopped

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v3
    command: agent
    depends_on:
      - woodpecker-server
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
      - WOODPECKER_MAX_WORKFLOWS=2
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped
    mem_limit: 4g

volumes:
  woodpecker-server-data:

WOODPECKER_AGENT_SECRET — общий секрет для аутентификации агентов, генерируется командой openssl rand -hex 32 и хранится в .env, а не в самом compose-файле. Обратите внимание на mem_limit: 4g у агента — это лимит самого compose (уровень Docker Compose, не переменная Woodpecker), который не даёт сумме дочерних контейнеров-шагов утащить в OOM весь хост. Без такого предохранителя один неудачно написанный пайплайн (например, зависший процесс без ограничений, который жрёт память бесконечно) может положить и сервер, если они на одной машине.

Общие принципы контроля памяти в Docker-окружении — какие лимиты где выставлять и как их читать — разобраны в статье про лимиты CPU и памяти для контейнеров; всё оттуда применимо и к контейнерам, которые поднимает Woodpecker-агент, потому что технически это обычные Docker-контейнеры.

Практические шаги, которые реально экономят память на CI-сервере:

  • Чистите Docker-кэш регулярно: docker system prune -af --volumes по расписанию (но не на живом агенте посреди сборки) — старые слои образов не едят RAM напрямую, но раздутый диск провоцирует своп и деградацию I/O.
  • Держите WOODPECKER_MAX_WORKFLOWS чуть ниже теоретического максимума, который выдержит память — лучше сборка постоит в очереди 30 секунд, чем агент уйдёт в OOM-kill и оборвёт все параллельные workflow разом.
  • Для тяжёлых интеграционных тестов (поднятие БД, брокера очередей в пайплайне) выносите такие репозитории на отдельного агента с большим запасом RAM, а лёгкие линтеры и unit-тесты — на дешёвый агент с 2 GB.
  • Мониторьте docker stats на хосте агента хотя бы вручную первую неделю после запуска — это быстро покажет, какой из ваших пайплайнов реально "тяжёлый", вместо того чтобы гадать по документации.

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

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

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

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

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

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

Хватит ли 1 GB RAM для Woodpecker?

Формально сервер запустится и на 1 GB, но с реальными пайплайнами (даже простой npm install) велик риск OOM на шаге сборки. Для рабочего варианта закладывайте от 2 GB, даже для соло-проекта.

Нужно ли разносить сервер и агент по разным серверам?

Не обязательно для небольшой нагрузки. Разносить стоит, когда тяжёлые сборки начинают влиять на отзывчивость веб-интерфейса и API, или когда нужно несколько агентов с разными профилями ресурсов.

Почему Woodpecker вообще существует, если есть Drone?

Потому что Drone сменил лицензию на Business Source License, и часть сообщества продолжила развивать последнюю полностью открытую версию как независимый проект под Apache 2.0 — без ограничений на коммерческое использование.

Можно ли ограничить память конкретному шагу пайплайна в .woodpecker.yml?

На Kubernetes backend — да, через resources в backend_options. На Docker backend встроенного способа задать лимит на уровне шага в актуальных версиях нет — ограничивать нужно на уровне самого агента (mem_limit в compose) или контролировать через WOODPECKER_MAX_WORKFLOWS.

SQLite выдержит нагрузку команды?

Для небольшой и средней команды — да, это база по умолчанию и она не требует отдельного администрирования. При росте числа репозиториев и глубокой истории билдов имеет смысл перейти на Postgres, но это вопрос не памяти, а конкурентной записи в БД.

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

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

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