Проект: tempus.build — managed self-hosted раннеры для GitHub Actions  Публичный пост
30 октября 2026  101
tempus.build - managed self-hosted раннеры для GitHub Actions
https://tempus.build

В жизни айтишника случаются периоды, когда тянет делать пет-проекты или строить стартап. В далёком 2018-м у меня была первая попытка сделать онлайн-бизнес. Я пытался вывести на рынок LMS — онлайн-платформу для обучения персонала и франчайзи. Создать получилось, вывести на рынок — нет.

Это было время, когда франшизы продавали все кому не лень. Купить и продать франшизу можно было на что угодно: даже нерабочую бизнес-модель, если её красиво «упаковать», получалось кому-то втюхать. Рынок франчайзинга тогда был похож на Дикий Запад — без правил и с модными разбойниками. Я это понял не сразу, а когда стартап уже затухал.

Модель моего «бизнеса» строилась так: управляющим компаниям (тем, кто продаёт франшизы) нужно передавать франчайзинговые пакеты с обучающими материалами и обучать персонал — чтобы франчайзи соответствовали единым стандартам сети. В передаче знаний, обучении и контроле и должна была помогать моя платформа.

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

Успехи, правда, тоже были. Я попал в полуфинал программы Forbes «Школа молодого миллиардера» — хотя сразу после объявления результатов у Forbes начались свои проблемы, издательство вроде продали, а программу закрыли. Так что для меня это приятная ачивка, не более. Пробовал попасть во ФРИИ (Фонд развития интернет-инициатив) — отбор не прошёл, но в какую-то предакселерацию нас включили. Про меня даже писали в РБК, но это скорее тоже ачивка. В какой-то момент я был настолько в отчаянном поиске поддержки, что прошёл отбор в IT-парк в Набережных Челнах и готов был туда переехать. Но бог миловал — я тогда переехал в Москву =)

Стартап я закрыл с убытками. Долги выплатил и на какое-то время остановился с идеями делать своё: нужно было встать на ноги, начать новую жизнь в Москве, а после 2022-го — в эмиграции.

Сейчас у меня снова период, когда я готов — морально, психологически и по времени — думать о своём деле/стартапе/маленьком свечном заводике. Поэтому я взялся за создание tempus.build.

Стараюсь учитывать опыт прошлого запуска онлайн-продукта: продукт уже работает, и я занимаюсь маркетингом. В прошлый раз мы потратили кучу денег на разработку и почти ноль на маркетинг.

Как появилась идея

Начну с того, что мне нравится GitHub. По уровню входа и количеству готовых решений альтернатив ему, как мне кажется, просто нет. На втором месте у меня GitLab, но он для меня менее дружелюбный — и я не про UI/UX, а про автоматизацию и экосистему. Плюс GitLab банально дороже по лицензиям: в SaaS командный тариф Premium стоит $29 за участника в месяц, а GitHub Team — $4. На команду из 10 человек это $290 против $40 в месяц.

Мне как инженеру приятно работать с GitHub в части CI/CD. Даже с учётом главного косяка GitHub — низкого uptime. Пока он не так сильно раздражает (хотя раздражает), плюсы перевешивают.

Аптайм GitHub за 90 дней
Аптайм GitHub за 90 дней

Кстати, кому интересно копнуть в реальный аптайм GitHub, есть ресурс https://mrshu.github.io/github-statuses/ — там подробнее, чем на официальном https://www.githubstatus.com/. Инциденты, влияющие лично на мою работу, случаются не так часто и надолго не блокируют. В общем, я смирился, хотя надёжность их продукта считаю неадекватной его уровню. У меня к ним на эту тему претензия.

Основная стоимость у меня за GitHub формируется не за количество лицензий сотрудников, а за раннеры. И вот тут начинается интересное.

Что такое раннеры и почему за них платят

Мы работаем в GitHub как организация: коммерческие репозитории приватные и принадлежат организации. CI/CD — это полезная работа (сборки, тесты, развёртывание), которую нужно на чём-то выполнять. Это «что-то» называют раннерами. Когда мы гоняем пайплайны, мы фактически арендуем у GitHub серверные ресурсы. Аренда не бесплатна, поэтому у GitHub есть своё ценообразование.

Тарифицируются два параметра: время, которое джоба отработала, и размер — раннер с определённым количеством ресурсов (чем мощнее, тем дороже за минуту). На старте GitHub даёт 2000 бесплатных минут в месяц на приватные репозитории. Раннер по умолчанию, который по моим наблюдениям используют чаще всего, — это ubuntu-latest: 2 vCPU, 7 ГБ RAM и 14 ГБ SSD.

И вот первая несправедливость: GitHub округляет время вверх, до минуты. Джоба отработала 20 секунд — с вас спишут целую минуту. Это одна из причин, по которой я вообще сел за tempus.build.

Поминутное округление GitHub против посекундной оплаты
Поминутное округление GitHub против посекундной оплаты

Второй момент: раннеры GitHub — это одноразовые виртуальные машины в облаке Azure (Microsoft же). Это важно, потому что «2 vCPU», которые вам выдают, — это неизвестно какое физическое железо. Поэтому вычислительная нагрузка на облачных раннерах, как правило, не даёт высокой производительности. А вычислительная нагрузка есть почти у всех, у кого есть тесты: юнит-тесты, компиляция и сборка в основном нагружают процессор.

Немного про безопасность и изоляцию

В CI/CD принято считать код недоверенным, даже если это ваш собственный: в зависимостях или в чужом PR может оказаться что угодно. Поэтому надёжной должна быть среда, в которой он исполняется: она изолирует код и не даёт ему дотянуться до лишнего.

Изоляция нужна не только ради безопасности (чтобы чужой или скомпрометированный код в пайплайне не дотянулся до соседей и до самой платформы), но и ради детерминизма — чтобы ваш код каждый раз исполнялся в одинаковой чистой среде, а не «как повезёт». Кстати, это не только моё мнение: GitHub сам не рекомендует self-hosted-раннеры на публичных репозиториях и советует одноразовые — ровно из-за недоверенного кода в PR.

Дешёвый способ изоляции — контейнер, но он делит ядро с хостом. Дорогой и надёжный — отдельная виртуальная машина на каждую джобу. В tempus.build я выбрал второе, но в лёгком варианте — про это ниже.

Три способа изолировать джобу: runc, gVisor, Kata
Три способа изолировать джобу: runc, gVisor, Kata

Подробный разбор, как каждый job получает собственное ядро, я вынес в отдельную статью — «Kata Containers: как каждый CI-job получает собственное ядро».

Что такое tempus.build

За раннеры надо платить, а раннеры GitHub, как выяснилось, недешёвые и не самые быстрые. Причин три: цена за минуту, округление до минуты и виртуальные машины в Azure на непонятном железе.

tempus.build — это managed-раннеры: вы меняете одну строку в workflow, а всё остальное делаю я. Что меняется:

  • Оплата посекундная. Джоба шла 10 секунд — платите за 10 секунд.
  • Минута дешевле на треть. tempus-ubuntu-24.04-2core стоит $0.004 за минуту, ubuntu-latest у GitHub — $0.006 при том же размере.
  • Железо — bare metal в EU, а не облачная виртуальная машина с неизвестным процессором. На вычислительных задачах это заметно.
  • Запуск VM не тарифицируется. Счётчик включается, когда джоба начала исполняться.
  • Кеш рядом с раннером, а не в облаке. Про него ниже отдельно.

Схема изоляции

Каждая джоба исполняется в аппаратно-виртуализированной микро-VM на Kata Containers. Это не контейнер с общим ядром, а лёгкая виртуальная машина со своим ядром на каждый job. После завершения она уничтожается. Даже если в пайплайн попадёт вредонос, из микро-VM на хост он не выберется.

Сеть и поведение раннеров под наблюдением eBPF (Cilium и Tetragon). Доступ к внутренней инфраструктуре кластера закрыт, выход в интернет открыт: граница недоверенного кода проходит по виртуальной машине, а не по принципу «запретить всё». Если нужен жёсткий сетевой замок, напишите: обсудим список разрешённых адресов для исходящего трафика.

Что ещё сделано, чтобы чужой код не дотянулся ни до вас, ни до соседей:

  • Своя VM и свой диск на каждую джобу. Для Docker внутри джобы создаётся новое блочное устройство, после джобы оно удаляется вместе с VM.
  • У раннера нет доступа к кластеру и к хосту. Ни токена Kubernetes, ни хостовых папок и сети. Права root (sudo, docker-in-docker) есть только внутри своей VM.
  • Каждый шаблон раннера проверяется дважды: политикой кластера и платформой перед развёртыванием. Без микро-VM, с образом не по точному digest или с доступом к хосту шаблон не пройдёт.
  • Отдельная группа раннеров на каждую организацию. Ваши джобы идут только в вашу группу.
  • Только приватные репозитории. PR из чужого форка не может запустить код на моих раннерах.
  • Кеш нельзя отравить из PR — подробно ниже, в разделе про кеш.
  • Данные организаций изолированы в базе, а логи ваших джоб я не читаю.

Никаких модных сертификаций вроде SOC 2 или ISO 27001 у проекта нет. Зато он с самого начала проектировался безопасным: я старался учесть все проблемы и риски, которые смог найти, поэтому защита в глубину сделана на каждом слое: виртуальная машина, сеть, кластер, кеш, база.

Почему одной инфраструктуры оказалось мало: платформа app.tempus.build

Сначала я хотел проверить гипотезу малой кровью: поднять только раннеры — быстрые, безопасные, и всё. Но без веб-платформы пользоваться этим неудобно: хочется видеть аналитику, детализацию по оплате, держать расходы под контролем. Так появилась app.tempus.build.

Подключение — одна строка. Ставите GitHub App на организацию, платформа сама заводит группу раннеров и подтягивает репозитории, мастер подключения подсказывает шаги. Дальше меняете в workflow runs-on: ubuntu-latest на runs-on: tempus-ubuntu-24.04-2core — и джобы выполняются на раннерах tempus.build. На вашей стороне никакой инфраструктуры. Откат — тоже одна строка: вернули ubuntu-latest, и джобы снова идут на GitHub.

Coverage — посчитать экономию, ничего не переносив. Этим я горжусь. При подключении платформа подтягивает историю ваших запусков на раннерах GitHub и показывает, сколько те же прогоны стоили бы в tempus.build. Не «сэкономьте до 40%», а цифры по вашей же истории.


Coverage: те же джобы до и после переезда (скриншот на демо-данных)

Биллинг, который сходится. Время считается от старта джобы до финиша, по секундам. Очередь, запуск VM и время после завершения не тарифицируются — вы не платите за задержку на моей стороне. Баланс — предоплатные кредиты в долларах, каждое списание ложится в неизменяемый журнал, и баланс всегда равен сумме журнала. Раз в сутки платформа сверяет списания с тем, что GitHub сам знает о ваших джобах: если я насчитал больше, это всплывёт у меня раньше, чем у вас. Есть автопополнение.


Баланс, прогноз и автопополнение (демо-данные)

Бюджеты и лимиты на организацию, репозиторий, workflow или автора. При превышении — сначала письмо, потом пауза, потом новые джобы не стартуют. Это защита от забытого цикла или чьего-то злоупотребления.


Лимиты на организацию, репозиторий, workflow и автора (демо-данные)

Дашборд, прогноз и AI-советник. Баланс в реальном времени, график трат, прогноз «на сколько хватит», разбор расходов по репозиториям, workflow и авторам, поиск аномальных всплесков и еженедельная сводка. AI-советник объясняет сводку человеческим языком и подсказывает, где сэкономить. Он только советует: сам ничего не списывает и не меняет настройки.


Главная: баланс, активные джобы, траты (демо-данные)


AI-советник расставляет рекомендации по выгоде (демо-данные)

Падения джоб я разбираю сам, не читая ваши логи. Каждый час платформа смотрит на метаданные джоб: исходы, длительность, сервер, аварийные остановки. Если на одном сервере вдруг стало вдвое больше падений, а у клиентов всё ровно, это сигнал, что сломалось у меня. Полные логи джоб открываю только вручную и только когда без них не подтвердить проблему на моей стороне.

А ещё:

  • джобы с container:/services: и docker build работают из коробки — поэтому QEMU, а не Firecracker, подробнее ниже;
  • образ раннера — копия ubuntu-24.04 от GitHub, workflow переезжают без правок;
  • GitHub App не видит ваш код: только метаданные репозиториев, события запусков и регистрация раннеров;
  • организации и роли; баланс видят только владелец и админ;
  • письма о важном: баланс, платежи, упавшие джобы, аномалии трат.

Оговорка: пока только организации и приватные репозитории. Личные аккаунты GitHub раннеры не получают — мастер подключения предложит создать организацию. Почему так, объясняю в коротком ролике:

Кеш: большая работа, которая уже проделана и ещё продолжается

Скорость CI упирается не только в CPU. Одно из узких мест — работа, которую джоба каждый раз делает заново: качает зависимости, пересобирает Docker-слои. На GitHub каждая джоба стартует с чистой машины, а кеш лежит в облаке: восстановление и сохранение идут по сети.

Кеш — это про ускорение. Но в нём лежат данные репозитория: зависимости, собранные слои, куски кода. Поэтому для меня это ещё и безопасность: другие репозитории не должны дотянуться до вашего кеша, а PR не должен его подменить.

У меня два собственных решения, оба работают на серверах рядом с раннерами.

1. Кеш Docker-сборок между запусками

У docker buildx есть свой кеш слоёв — BuildKit. На GitHub он умирает вместе с машиной. Его можно выгружать через cache-to: type=gha, но выгрузка и загрузка идут по сети и часто съедают выигрыш.

Я сделал так:

  • Состояние BuildKit живёт на сервере, отдельно для каждого репозитория. Когда джоба запускает buildx build, раннер сам подтягивает сохранённое состояние в свою изолированную VM. Ничего настраивать не нужно: docker/build-push-action работает как есть.
  • Сохраняется только то, что собрано в default-ветке. Решает это платформа, а не код внутри джобы. Поэтому PR из ветки не может подложить отравленный слой в кеш, которым потом соберётся main.
  • Если архив лежит на другом сервере, его забирают оттуда и оставляют копию у себя.
  • Если что-то пошло не так, сборка просто идёт холодной. Кеш никогда не роняет джобу.

Замер на открытом проекте excalidraw с Dockerfile, где зависимости ставятся до копирования кода (изменена одна строка кода, сборка под три платформы): без кеша джоба шла 59–60 секунд, с кешем — 41–46, вместе с восстановлением кеша в начале. Сама сборка образа — 26–27 секунд вместо 41: 14 шагов из 31, включая установку зависимостей, взяты из кеша. Восстановление — около 2 ГБ за 7–8 секунд.

Совет из замеров: если собираете на tempus.build, уберите cache-to: type=gha. На холодной сборке он добавлял около минуты (65 с без него против 127 с с ним), на тёплой — от 3 до 14 секунд.

2. Свой бэкенд для actions/cache

Зависимости между запусками сохраняют через кеш GitHub Actions: напрямую через actions/cache или через встроенный кеш в setup-node, setup-python, setup-go, setup-java. Например, setup-node с cache: yarn сохраняет скачанные пакеты yarn, чтобы следующая джоба не тянула их из интернета заново. Все они хранят кеш в облачном сервисе GitHub. Я написал свою реализацию того же протокола, она работает на сервере рядом с раннером. Actions ничего не замечают: те же ключи, те же restore-keys, те же правила веток.

Это бесплатно и включено у всех по умолчанию.

Замеры

Прилагательные ничего не стоят, поэтому ниже только измерения. У каждого замера подписано, какую нагрузку он проверяет: CPU, сборку Docker-образа или работу с кешем.

Открытые проекты

Как мерил. Один и тот же workflow в приватном репозитории, отличается только runs-on:. Каждый проект забирается на зафиксированном коммите и запускает свои же команды. Со стороны GitHub — стандартный ubuntu-24.04 (2 vCPU), на tempus.build — tempus-ubuntu-24.04-2core, то есть размер в размер; 4core — для справки. Первый прогон холодный, второй тёплый: перед сборкой Docker меняется одна строка в исходниках, как при обычном коммите. На графике — время самого шага (тесты, установка, сборка) в секундах.

GitHub против tempus.build: время шага в секундах, меньше — лучше
GitHub против tempus.build: время шага в секундах, меньше — лучше

Время на GitHub скачет. Оно сильно зависит от того, в какой регион Azure попала джоба: под одной и той же меткой там разное железо. На одном и том же наборе тестов django разброс между регионами — 1,7 раза: 300 секунд в centralus, 507 — в eastus2. На tempus.build время стабильное: 216–222 секунды на 2core. Ещё два прогона django на GitHub в регионе westus оборвались посреди набора тестов, на график они не попали.

На сборке Docker-образа excalidraw кеш почти не помогает — ни у GitHub, ни у меня. В Dockerfile проекта код копируется раньше установки зависимостей, поэтому любая правка сбрасывает и yarn install, и сборку Vite, а она занимает почти всё время. С моим кешем BuildKit тёплая сборка шла 43 секунды против 46 у холодной, плюс 8 секунд на восстановление 1,6 ГБ состояния. Здесь выигрыш даёт раннер, а не кеш. Польза кеша зависит от порядка слоёв: ставьте зависимости до того, как копируете код, тогда правка кода не трогает слой с зависимостями.

Живой клиент

Один из первых клиентов — из Клуба — разрешил показать цифры, без названия и подробностей. Большое ему спасибо, что доверился и стал одним из первых. Это монорепо, в CI тесты и сборки Docker-образов. До переезда они гоняли CI на стандартных раннерах GitHub с 2 vCPU, на tempus.build — на 4 vCPU.

Сравнил медианы успешных запусков тех же 31 джобы до и после переезда:

  • машинного времени ушло в 1,33 раза меньше;
  • тесты — 11,2 → 5,8 минуты;
  • сборки образов — чаще всего в 1,2–1,6 раза быстрее;
  • стоимость тех же запусков примерно на 7% ниже, хотя ядер вдвое больше: в tempus.build посекундно по $0.008, у GitHub — по $0.006 с округлением каждой джобы до минуты.

Честная оговорка: это не лабораторный замер. Сравниваются разные месяцы, код клиента за это время менялся, сам tempus.build тоже менялся в лучшую сторону, и размер раннеров разный.

Тарифы

Цена зашита в метку runs-on, скрытых множителей нет. Память — 1:4 к vCPU.

Метка runs-on Ресурсы Ставка
tempus-ubuntu-24.04-2core 2 vCPU / 8 ГБ $0.004 / мин
tempus-ubuntu-24.04-4core 4 vCPU / 16 ГБ $0.008 / мин

Это готовые размеры. Могу нарезать раннер любого размера, например tempus-ubuntu-24.04-8core или tempus-ubuntu-24.04-16core, и посчитать экономику под ваш CI. Раннеров на macOS и ARM у меня пока нет, но если найдётся клиент, который окупит железо, — сделаю.

Оплата посекундная, предоплатными кредитами: счёта-сюрприза в конце месяца не будет, баланс не сгорает. После подключения первой организации на балансе $5 без привязки карты — это 1 250 минут 2-core раннера или 625 минут 4-core.

Универсального «дешевле на X%» не обещаю: всё зависит от пайплайна. Прикинуть можно на калькуляторе, точно — через Coverage на своей истории.

Реальная стоимость владения (сравнение со своими раннерами)

Когда сравнивают managed-раннеры с «поднять свои», обычно считают только видимую часть: «да я VPS за $10 в месяц возьму». Это вершина айсберга. Полная стоимость владения — это вычислительные ресурсы плюс эксплуатация и риск, а их в цене сервера не видно:

Реальная стоимость владения self-hosted CI
Реальная стоимость владения self-hosted CI

  • Сборка своего образа раннера. Это не прихоть, а необходимость: чтобы workflow работали как на GitHub, раннеру нужен совместимый образ с теми же инструментами и версиями, и его надо регулярно пересобирать под обновления и патчи безопасности. У меня сборка занимает час на 8 ядрах. Хотелось бы вам или вашим платформенным инженерам этим заниматься? 🥲 Почему я собираю свой образ, а не беру готовый, — в отдельной статье. Она написана в общем виде, на примере tempus.build, и пригодится, даже если вы им не пользуетесь.
  • Железо под параллельные джобы. Чтобы одновременно гонять N раннеров, придётся купить или арендовать серверы под пик либо брать spot-машины в облаке. Это по сути то же облако, только со своими неудобствами: машину могут забрать посреди сборки, а обслуживать всё это снова вам.
  • И всё остальное: простой и запас под пики, автомасштабирование через ARC на Kubernetes, изоляция недоверенного кода, мониторинг и дежурства, когда раннеры лягут в пятницу вечером. И ваше время инженера — самое дорогое в списке.

Managed снимает всё это и превращает в одну строку runs-on. Иногда «дороже за минуту» на бумаге оказывается сильно дешевле по полной стоимости владения. Полный разбор с цифрами и честными примерами — «Self-hosted или managed: реальная стоимость».

Где self-hosted честно выигрывает (важно это признать): ровная 24/7-загрузка под 100% (своё железо по себестоимости обходит поштучную цену), строгий data residency / air-gap / свой VPC, особое железо (GPU, ARM, Windows/macOS) и независимость от вендора. Посекундная модель выигрывает на неравномерном CI, а не на плоской полной загрузке.

Сравнение с конкурентами

Рынок сторонних раннеров плотный: Depot, Blacksmith, Namespace, WarpBuild, Ubicloud и другие. Кто-то дешевле, кто-то умеет macOS, Windows и GPU, кто-то живёт в вашем облаке. Быстрый кеш рядом с раннером сейчас есть почти у всех, включая меня.

Самым дешёвым по ценнику tempus.build не является, и микро-VM есть не только у меня. Моя ниша — пересечение: конкурентная цена, аппаратная изоляция каждой джобы, кеш, который нельзя отравить из PR, хостинг в EU, открытые подписанные образы — копия образа GitHub — и оплата в любой валюте, включая рубли.

За 2026 год BuildJet закрылся, а Cirrus Runners сворачиваются (команда ушла в OpenAI). Оба объясняли уход тем, что GitHub догнал по железу. Урок: на одной цене и скорости долго не продержаться, если их легко повторить.

Про OSS и supply-chain

Часть tempus.build открыта, и это осознанно. Продукт продаёт доверие к изоляции и к тому, что внутри раннера, — а доверие странно продавать «на словах».

  • Образы раннеров — публичные (tempusbuild/runner-images), вместе с supply-chain-обвязкой: подпись cosign, SBOM, SLSA-provenance, скан trivy. Видно, что именно внутри образа и кто его собрал — можно собрать и проверить самому.
  • Лендинг и статус-страница — тоже публичные. Статус специально держу независимо от основной инфраструктуры.

Цепочка доверия к образу раннера
Цепочка доверия к образу раннера

Как проверить образ, который исполняет ваш CI, — в разборе «Supply chain раннер-образов». Приватным остаётся только то, что связано с поверхностью атаки: конфиги сети, версии компонентов, топология. Называть архитектурные имена стека (Kata, QEMU, Cilium, cosign/SBOM/SLSA) — это сигнал доверия, а не утечка.

Оплата в любой валюте, включая рубли

Отдельная боль для команд из СНГ — как вообще заплатить. GitHub принимает только зарубежные карты, и за него часто платят обходными схемами. tempus.build принимает оплату в любой валюте, в том числе в рублях — по курсу Rapira. Базовый учёт у меня в USD, но пополнить баланс можно тем, что удобно вам, без плясок с зарубежными платёжками. Могу предоставить закрывающие документы по оплате для любой юрисдикции, в том числе для РФ.

Технологический стек и как это построено

  • Бэкенд: FastAPI + HTMX + Jinja + Tailwind. Почти без клиентского JS: HTMX закрывает весь дашборд.
  • Раннеры: k3s + actions-runner-controller + Kata Containers (QEMU/KVM) на bare metal в EU.
  • Кеш: свой сервис на серверах (Go) — хранит состояние BuildKit и отвечает за actions/cache.
  • Сеть и безопасность во время выполнения: Cilium и Tetragon (eBPF).
  • Supply-chain образов: cosign + SBOM + SLSA + trivy.
  • Лендинг: Astro + Tailwind на GitHub Pages. Да, лендинг альтернативы GitHub я публикую на GitHub — инструмент хороший, мне не стыдно.

Самые неожиданные трудности

Главная неожиданность — объём работы. Я думал, что соберу продукт из готовых open source решений: Kubernetes, actions-runner-controller, Kata Containers. Оказалось, что open source — только фундамент. Поверх него пришлось писать своё на уровне инфраструктуры: кеш Docker-сборок, свой бэкенд для actions/cache, проверку и изоляцию раннеров. И отдельно — платформу с аналитикой, которая сильно богаче аналитики самого GitHub: траты по репозиториям, workflow и авторам, прогноз, аномалии, Coverage и бюджеты.

Первая — самая красивая техническая засада: Kata + Firecracker не поехали. Firecracker — модный минималистичный микро-VM-монитор, я хотел его. Но: Kata с Firecracker требует devmapper-snapshotter (блочное хранилище), а docker-in-docker внутри раннера работает на overlay2 — это взаимоисключающие требования. Вдобавок k3s-containerd поставляется без плагина devmapper. В итоге выбрал QEMU: он поддерживает overlay2 и проверен для CI.

Вторая — не техническая, а занудная: платежи и юрлицо. Принять деньги из разных юрисдикций, да ещё и в рублях, — это отдельный квест с провайдерами, налогами и комплаенсом, который съедает время не хуже кода.

Третья — кеш. Сделать быстрый кеш несложно. Сложно сделать кеш, которому можно доверять, — как он устроен, я рассказал выше.

Сколько потратил и заработал, как монетизировать

Платящие клиенты уже есть, но выручка пока небольшая. Монетизация прямая и простая: вы платите за вычислительные ресурсы, как и должно быть. Никаких доплат, например за кеширование: оно уже включено. Я маленький, могу себе это позволить, и по идее моя экономика должна сходиться =)

Железо и всё вокруг него сейчас обходятся мне примерно в €200 в месяц. Если загрузить его круглосуточно, это около 900 тысяч минут 2-core раннера в месяц. Сейчас занято около 6%. Нагрузка пиковая: днём идут сборки, а ночью почти тишина, потому что клиенты пока в европейских часовых поясах. Загрузить железо на 100% всё равно не получится: в пики клиенты конкурируют за одни и те же раннеры. Реалистичный путь — добавлять серверы, брать spot-машины в облаке (этого я не хочу) или выделять серверы под команды, которым важны гарантированные слоты и отсутствие очереди в пики. Это всё решается, были бы клиенты.

Сейчас рост продукта упирается в число платящих клиентов и мой личный бюджет на железо: новые серверы нужны, чтобы в пики не было очередей, слотов стало больше, а текущие серверы не работали на пределе. Добавлю их, когда их окупят клиенты. Поэтому каждая команда, которая пользуется tempus.build, напрямую помогает ему расти. Больше железа — это больше параллельных раннеров на команду и ещё более быстрые пайплайны, при этом дешевле.

Планы на будущее

Всё зависит от потребностей команд: это могут быть новые размеры раннеров или новые платформы — macOS, ARM, GPU.

Нужны ли советы или помощь Клуба

Да. Мне важен живой фидбек от инженеров: где болит ваш CI, что бесит в GitHub Actions, за что вы готовы платить, а за что — ни за что. И первые пользователи, которые не боятся ранних продуктов и скажут, где кривое.

Для клубчан

Клубчанам — $50 на баланс вместо $5. Это 12 500 минут 2-core раннера. И мои прямые контакты: помогу перенести CI и сделать его лучше, быстрей, сильней.

Чтобы получить — подключите организацию и напишите мне в Клубе или в Telegram её название.

Ссылки

2 комментария 👇

Главный вопрос, который возник: если это bare metal - то как организован скейл железа (как вверх, так и вниз)?
Даже у buildjet (который был не самым маленьким) случались просадки, когда не было доступных тачек под раннеры.
Не получится ли так, что с ростом нагрузки вся эта выгода по скорости от bare metal нивелируется тем, что придется ждать, пока освободятся раннеры, готовые подхватить мою джобу?

Второе: киллер-фичей buildjet были ARM-машины (пока github не запустил свои раннеры). ARM - это хороший способ сэкономить на нетребовательных к CPU сервисах, как при сборке, так и в эксплуатации. Да, можно собирать под несколько архитектур и на x64 с помощью buildx, но это часто очень неоптимально по времени.

  Развернуть 1 комментарий

@strangeman, это очень хорошие вопросы. По первому, такой риск есть и до конца он не решен. Это будет зависеть от нагрузки и модели монетизации. Пока я маленький, то могу позволить себе покупать bare metal под нагрузки, которые есть. Дальше, буду думать. Может дать моя модель в том чтобы командам выделенные тачки давать, а не из общего пула.

По второму. Я думал про это тоже, но пока вижу это распылением, до тех пор пока кто-то не придет и скажет: «нам нужно так и так». Собственно пока я не большой то могу не сильно заботиться о таких проблемах, но я о них думаю

  Развернуть 1 комментарий

😎

Автор поста открыл его для большого интернета, но комментирование и движухи доступны только участникам Клуба

Что вообще здесь происходит?


Войти  или  Вступить в Клуб