На каждую джобу поднимается одноразовая виртуальная машина на нашем железе, отдаёт себя GitHub Actions и исчезает. Ни кластера, ни автоскейлера, ни дежурства — вы меняете одну строку в workflow.
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: tatnet=${{ github.run_id }}/cpu=4 steps:
- uses: actions/checkout@v5
- run: make test
что происходит дальше
12:04:31джоба принята из вебхука
12:04:32раннер выдан из тёплого пула — 1 с
12:06:58джоба завершена, машина уничтожена
1 с
от вебхука до раннера, пока в пуле есть машина
144 vCPU
Xeon Gold 6146 @ 3,2 ГГц, три узла, 2,2 ТБ памяти
1 джоба
на машину: следующая получит чистую
ubuntu-24.04
образ собран из тех же скриптов, что у GitHub
путь одной джобы
От очереди до уничтожения — один круг.
Машина сама дозванивается наружу и забирает работу. Внутрь вашей сети и внутрь наших узлов никто не ходит, публичный адрес раннеру не нужен.
01
Событие
GitHub шлёт нам workflow_job с подписью. Из лейблов читаем, какая машина нужна: ядра, память, диск, образ.
02
Тёплый пул
Машины нужных классов уже загружены и ждут. Джоба получает готовую за секунду, а пул сразу заказывает замену.
03
Работа
Раннер регистрируется одноразовым конфигом и тянет джобу сам. Логи идут напрямую в GitHub — через нас они не проходят.
04
Уничтожение
Джоба закончилась — машина удаляется целиком, вместе с диском. Следующая сборка стартует на чистой, а не на чужих остатках.
Подключение — три шага
шаг 1Поставить приложениеGitHub App на нужные репозитории — права на Actions и чеки, ничего лишнего.
шаг 2Поменять одну строкуВ workflow вместо ubuntu-latest — лейбл с нужным классом машины.
шаг 3Запустить сборкуОбратно — тоже одна строка: удалите лейбл, и джоба вернётся на GitHub-hosted.
что в машине
То же, что у GitHub. Плюс то, чего у него нет.
Образ собран из тех же открытых скриптов, которыми GitHub собирает свои раннеры, — поэтому привычные действия работают без правок.
Виртуальная машина, а не контейнер
Чужой код в CI работает под root — и единственная граница, которой можно верить, это гипервизор. У каждой джобы своё ядро, свой диск и свой сетевой порт; после завершения не остаётся ни слоя кеша, ни процесса.
граница доверия
джоба клиента
ядро гостя
гипервизор KVM
узел TatNet
Вложенная виртуализация
Внутри джобы работает KVM: эмуляторы Android, тесты на qemu, Vagrant и всё, что на GitHub-hosted не заводится.
Образ как у GitHub
Docker, тулкеш Python, Node, Go, Java и Ruby, браузеры, gh, сборочные пакеты. Обновляется тем же расписанием, что и оригинал.
Кеш и зеркала рядом
Объектное хранилище и зеркало npm стоят в том же дата-центре, что и узлы: зависимости едут по локальной сети, а не через полмира.
Приватная сеть
У раннера нет публичного адреса, и соседние машины он не видит. Нужен доступ к вашему стенду — подключаем к вашей приватной сети.
три способа гонять CI
Та же джоба. Без кластера и без дежурного.
Свои раннеры обычно означают Kubernetes, автоскейлер и человека, который это чинит. Мы продаём результат этой работы, а не конструктор.
GitHub-hosted
Свои раннеры в K8s
TatNet Runners
Что разворачивать
Ничего
Кластер, контроллер, автоскейлер
Ничего
Изоляция джобы
Виртуальная машина
Обычно контейнер на общем узле
Виртуальная машина
Вложенная виртуализация
Нет
Зависит от узлов
Есть на всех узлах
Кеш и зеркала
Через интернет
Поднимаете сами
В том же дата-центре
Кто чинит и обновляет
GitHub
Ваша команда
Мы
Как вернуться обратно
—
Переписать workflow
Удалить один лейбл
Windows, macOS, ARM и видеокарты пока не поддерживаем — держим одну платформу и делаем её быстрой, вместо списка галочек.
Счёт пойдёт посекундно, пока джоба выполняется. Тёплый пул, простой машин и их уничтожение мы не считаем: это наша забота, а не ваш счёт. Тарифы объявим на запуске — сейчас продукт в раннем доступе, и он бесплатен для команд, которые помогают его обкатать.