Публикации стоят в очереди, а новые Mac всё равно не успевают принять задания.
Быстрее всего работает двухслойная схема: небольшой базовый тёплый пул для обычной нагрузки и эластичные узлы, которые запускаются по очереди. Для продакшена используйте ephemeral self-hosted runner или JIT-регистрацию, очищайте Mac после каждого задания и сохраняйте логи вне узла.
Эта статья предназначена:
- руководителям по эффективности разработки, которые устраняют очереди iOS-сборок и задержки релизов;
- IT- и специалистам по безопасности, отвечающим за права Runner, изоляцию ключей и аудит;
- техническим директорам и закупщикам инфраструктуры, сравнивающим постоянные Mac, удалённую аренду и гибридную ёмкость.
Последнее обновление: 21 августа 2026 года; сведения о статусе компонентов и API сверены с официальной документацией GitHub и репозиторием Runner Scale Set Client.
До запуска: определите границы автоматического масштабирования
Автоматическое масштабирование macOS Runner в GitHub Actions не начинается с выбора количества Mac. Сначала нужно измерить, почему возникает задержка: задания действительно ждут свободный Runner или больше времени уходит на доставку хоста, установку зависимостей, подготовку сертификатов и проверку окружения.
Разделите наблюдаемую задержку на отдельные интервалы:
- ожидание задания в очереди;
- передача запроса от управляющего слоя к планировщику ресурсов;
- запуск или выделение Mac;
- инициализация macOS, Xcode, SDK и зависимостей;
- регистрация Runner и получение задания;
- выполнение сборки;
- очистка и возврат узла в пул либо его уничтожение.
Так вы не будете лечить нехватку Runner увеличением постоянного парка, когда настоящая причина находится в медленной инициализации или ошибках очистки.
Управляющий слой должен принимать запрос, выбирать профиль ресурса и отслеживать состояние узла. Он не заменяет систему закупки или поставки Mac. Runner Scale Set Client не покупает физические машины, не создаёт Mac, не устанавливает на них macOS, не готовит Xcode и не уничтожает хосты. Эти действия остаются за вашей автоматизацией, внутренним планировщиком или интерфейсом поставщика удалённых Mac. Такое ограничение подтверждается описанием компонента в официальном репозитории Runner Scale Set Client.
Три слоя ресурсов
Базовый тёплый пул обслуживает регулярные задания. В нём находятся подготовленные Mac, но они не должны быть универсальным общим сервером для всех репозиториев. Тёплый пул уменьшает задержку доставки, однако постоянно занятые узлы оплачиваются и требуют обновления, мониторинга и контроля сертификатов.
Эластичные узлы подключаются, когда очередь превышает установленный порог или появляются задания определённого профиля. Их можно использовать для нерегулярных релизов, параллельных тестов и временного роста команды. Верхняя граница должна быть задана заранее, чтобы неисправный webhook или повторная доставка событий не создали неконтролируемый расход.
Фиксированные подписывающие узлы нужны там, где процесс выпуска связан с особо чувствительными ключами, физическими интерфейсами или строгими требованиями к неизменяемости среды. Их не следует смешивать с обычными тестовыми Runner. Если задача не требует постоянной привязки к конкретному хосту, временный узел обычно проще удалить и выдать заново.
Какой режим выбрать для macOS Runner — постоянный или ephemeral?
Для производственного конвейера выбирайте ephemeral-модель, если задание может получить чистый узел и все нужные зависимости воспроизводимо устанавливаются из базового образа. Постоянный Runner допустим для тёплого пула и контролируемых внутренних задач, но после каждого задания всё равно нужны проверка рабочей директории, удаление временных файлов и контроль состояния Keychain. Документация GitHub прямо рекомендует автоматическое масштабирование прежде всего с ephemeral self-hosted runners, поскольку это ограничивает перенос состояния между заданиями; соответствующие правила описаны в документации GitHub по self-hosted runners.
Что собрать до первого изменения архитектуры
Зафиксируйте для каждого типа задания:
- требуемую архитектуру — Intel или Apple Silicon;
- версию Xcode и поддерживаемые SDK;
- необходимость доступа к сертификатам и профилям;
- допустимое время ожидания публикации;
- максимальный размер параллельной очереди;
- условия, при которых задача считается просроченной;
- допустимый максимум эластичных узлов;
- правило возврата или уничтожения Mac после ошибки.
Версии Xcode нельзя подбирать только по тегу Runner. Требования зависят от версии macOS и совместимости SDK; перед созданием образа сверяйте их с официальными системными требованиями Xcode. Это особенно важно для Apple Silicon: одинаковое имя задачи не означает одинаковое поведение зависимостей и инструментов на разных архитектурах.
В первый час: настройте маршрутизацию и доверие
Плохая маршрутизация превращает масштабирование в источник риска. Если все workflow используют общий label, тестовый Pull Request может попасть на узел с производственными ключами, а тяжёлая сборка — занять ресурс, предназначенный для срочного выпуска.
Создайте отдельные runner group по уровню доверия и назначению. Доступ группы ограничивается конкретными организациями или репозиториями, а не только названием label. При настройке проверьте официальные правила доступа к Runner group.
Разделяйте маршруты минимум по следующим признакам:
- среда: тестирование, предпродакшен, производство;
- архитектура: Apple Silicon и Intel, если обе используются;
- профиль Xcode и SDK;
- наличие чувствительных signing credentials;
- доверенность источника изменений;
- класс нагрузки: быстрые проверки, полная сборка, выпуск.
Пример минимального фрагмента workflow должен показывать только намерение маршрутизации, а не выдавать готовую production-конфигурацию:
jobs:
build:
runs-on:
- self-hosted
- macos
- apple-silicon
- xcode-release
Эти labels сами по себе не создают изоляцию. Реальный барьер задаётся разрешениями runner group, политикой репозитория и тем, какие секреты доступны конкретному workflow.
Для регистрации используйте GitHub App с минимальными необходимыми правами либо другой способ аутентификации, соответствующий официальной модели GitHub. Не храните долгоживущий регистрационный токен в образе Mac. Назначьте владельцев для выпуска, отзыва и ротации секретов, а события регистрации и отмены отправляйте в систему аудита. Полезные ограничения и типовые риски собраны в руководстве GitHub по безопасному использованию self-hosted Runner.
Публичные репозитории и workflow, которые могут выполнять непроверенный код из Pull Request, нельзя направлять на Mac с производственными сертификатами, приватными ключами, доступом к внутренней сети или постоянными учётными данными. Разделяйте доверенные и недоверенные задания на уровне групп, сетевых правил и профилей узлов, а не только условием в YAML.
Может ли Runner Scale Set Client напрямую управлять удалёнными Mac?
Нет. Он помогает связать GitHub Actions с вашим контроллером масштабирования и жизненным циклом Runner, но не выступает поставщиком Mac-инфраструктуры. Запуск хоста, получение IP или учётных данных, установка Runner, подготовка Xcode, удалённая перезагрузка и уничтожение узла должны выполняться вашей системой управления ресурсами или через доступный вам интерфейс удалённого Mac.
В день подключения: соберите цепочку состояний
Не начинайте с подключения рабочего репозитория. Сначала опишите конечный автомат, в котором каждое состояние имеет идентификатор запроса, срок действия и безопасный повтор.
Рекомендуемая последовательность выглядит так:
Потребность появилась. Событие workflow_job или сигнал от очереди сообщает, что заданию нужен Runner. При повторной доставке события контроллер должен найти уже существующий запрос, а не создать второй Mac.
Запрос ресурса создан. Планировщик выбирает профиль — архитектуру, Xcode, уровень доверия и лимит времени ожидания. На этом этапе ещё нет зарегистрированного Runner.
Хост готовится. Система запускает или выделяет Mac, применяет базовый образ, проверяет свободное место, доступность SSH и состояние системных сервисов. Повторный запрос должен ссылаться на тот же ресурс либо корректно отменять неиспользованный экземпляр.
Runner регистрируется. Контроллер получает краткоживущие данные JIT-регистрации и передаёт их подготовленному узлу. API GitHub для операций с self-hosted runners описан в официальной документации REST API. JIT-регистрация не должна превращаться в постоянный секрет, записанный в образ.
Задание получено. GitHub Actions направляет workflow на Runner по группе и labels. Контроллер фиксирует связь между идентификатором задания, узлом и профилем, чтобы отмена или повтор могли обработать именно этот экземпляр.
Работа завершена. Даже успешное завершение не означает, что Mac безопасно возвращать в общий пул. Сначала удалите рабочую директорию, временные артефакты, логи с секретами и созданные во время сборки учётные данные.
Runner отключён и ресурс возвращён. Для ephemeral-узла регистрация удаляется после задания. Хост либо проходит проверку для тёплого пула, либо уничтожается. Если очистка не подтверждена, ресурс должен перейти в карантин, а не снова принимать код.
Для интеграции используйте разные механизмы по назначению:
workflow_jobWebhook сообщает о появлении и изменении задания;- REST API помогает проверять состояние Runner, удалять устаревшие регистрации и строить аудит;
- JIT-конфигурация подходит для краткоживущего подключения;
- Runner Scale Set Client связывает управляющий слой GitHub с вашим контроллером ресурсов.
Минимальный псевдокод регистрации должен отражать порядок, но не скрывать инфраструктурные операции:
получить событие задания
проверить идемпотентный ключ
выбрать профиль Mac
запросить хост у планировщика
дождаться проверки базового образа
получить JIT-конфигурацию
запустить ephemeral Runner
передать labels и runner group
отследить завершение задания
очистить узел и отправить логи
удалить регистрацию
вернуть или уничтожить хост
Обрабатывайте отдельно четыре сбоя: повторное событие, невозможность запустить Mac, истечение времени регистрации и отмену задания до готовности узла. Во всех случаях нужен безопасный результат: отменённый запрос не должен оставлять работающий Mac, а недоступный Runner не должен бесконечно числиться свободным.
Первая сборка: проверьте одноразовый контур
Создайте отдельный тестовый репозиторий без production signing credentials. Его задача — доказать не успешность приложения, а прохождение полного жизненного цикла.
Проведите проверку по шагам:
- [ ] Workflow использует только нужную runner group и набор labels.
- [ ] Задание на неподходящей архитектуре не получает ресурс.
- [ ] Контроллер создаёт один запрос при повторной доставке одного события.
- [ ] Mac проходит проверку базового образа до регистрации Runner.
- [ ] JIT или ephemeral Runner регистрируется без постоянного токена в образе.
- [ ] Задание стартует только после подтверждения готовности узла.
- [ ] После завершения Runner удаляется или переводится в карантин.
- [ ] Рабочая директория очищается, включая временные файлы и кэш, который нельзя переиспользовать.
- [ ] Секреты signing не попадают в общий кэш и журналы.
- [ ] Логи контроллера, Runner и жизненного цикла Mac сохраняются вне узла.
- [ ] Прерванное задание не оставляет активный ресурс без владельца.
- [ ] Ошибка подготовки приводит к повторной поставке либо понятному отказу, а не к бесконечному циклу.
Кэш требует отдельного решения. Кэш пакетов и неизменяемых зависимостей можно переиспользовать, если вы контролируете его происхождение и права доступа. Сертификаты, профили, временные ключи, файлы конфигурации и результаты подписи должны уничтожаться после задания. Нельзя считать очисткой простой перезапуск shell-процесса.
Проверяйте доступность Xcode и SDK по хэшу базового образа или другому воспроизводимому идентификатору. Если образ меняется вручную, следующая сборка может использовать другую версию инструмента, хотя labels workflow останутся прежними. При расхождении базовой линии узел лучше вывести из пула и пересоздать.
Логи отправляйте во внешнее хранилище до удаления Mac. Минимальный набор включает события очереди, запрос поставки, переходы состояний, регистрацию Runner, начало и конец задания, причину уничтожения и результат очистки. Рекомендации GitHub по мониторингу и устранению неисправностей Runner помогают определить, какие признаки нужно наблюдать, но бизнес-связь между заданием и хостом вы должны сохранять самостоятельно.
Первая неделя: откалибруйте пул и восстановление
Не задавайте размер тёплого пула по числу разработчиков. Спрос создают одновременно запущенные workflow, длительность сборки, релизные окна, повторные попытки и доля задач, которым требуется редкий профиль Xcode или архитектура.
Начните с журнала, где для каждого задания фиксируются:
- время постановки в очередь;
- время запроса Mac;
- время готовности хоста;
- время регистрации Runner;
- время начала и завершения работы;
- причина ожидания;
- результат очистки;
- факт повторной поставки после сбоя.
После накопления собственных наблюдений задайте:
- минимальный тёплый пул для обычной очереди;
- порог запуска эластичных узлов;
- максимальное число одновременно поставляемых Mac;
- период охлаждения перед сокращением пула;
- отдельные лимиты для подписывающих и тестовых задач;
- правило аварийного отказа при превышении бюджета или лимита безопасности.
Фиксированная ёмкость проще для прогнозирования, но оплачивается и обслуживается даже при низкой загрузке. Эластичная ёмкость снижает постоянное содержание, однако добавляет время доставки, зависимость от доступности ресурсов и необходимость корректной идемпотентности. Гибридная схема обычно рациональна, когда обычная нагрузка предсказуема, а релизные пики нерегулярны.
В расчёт включайте не только тариф Mac:
- время простоя тёплого узла;
- сопровождение образов и обновлений;
- работу инженера при неисправностях;
- хранение внешних логов;
- повторные сборки после загрязнения среды;
- задержку публикации при нехватке ёмкости;
- резерв для редких профилей Xcode и Apple Silicon.
Сколько Mac Runner оставлять в тёплом пуле на пике iOS-сборок?
Универсального числа нет. Оставляйте столько узлов, сколько покрывает согласованную базовую параллельность до начала поставки новых Mac, а пиковую разницу закрывайте эластичными ресурсами. Решение принимайте по журналу очереди и времени доставки, а не по размеру команды. Если редкий релизный профиль появляется редко, держать его постоянно может быть дороже, чем запрашивать по требованию.
Проведите отдельные учения:
- отказ управляющего контроллера;
- потеря связи с Mac после регистрации;
- неудачное обновление Runner;
- неправильный label или runner group;
- отмена workflow во время подготовки;
- завершение задания без подтверждённой очистки;
- недоступность внешнего хранилища логов.
Каждое учение должно заканчиваться ответом на три вопроса: кто обнаружил проблему, какой ресурс был заблокирован и как доказать, что секреты не остались на узле.
Перед продакшеном: проведите поэтапный допуск
Не считайте Runner готовым только потому, что он отображается онлайн. Производственная приёмка должна проверять одновременно маршрут задания, изоляцию, пределы ёмкости, полноту журналов и результат удаления ресурса.
Используйте такую последовательность допуска:
- [ ] Сначала разрешены только сборки без подписи и доступа к производственным системам.
- [ ] Затем включены доверенные репозитории с тестовыми сертификатами.
- [ ] После этого проверены отказ, повторная поставка и восстановление после потери Mac.
- [ ] Отдельно подтверждено, что публичные или непроверенные Pull Request не достигают подписывающих узлов.
- [ ] Проверено, что labels не дают обхода runner group.
- [ ] Зафиксирована верхняя граница эластичной ёмкости.
- [ ] Проверены JIT-регистрация, автоматическое удаление и карантин после ошибки.
- [ ] Внешние логи позволяют восстановить путь задания после удаления хоста.
- [ ] Согласованы владельцы ротации токенов, сертификатов и базовых образов.
- [ ] Зафиксировано решение: тёплый пул, эластичная аренда Mac или смешанная архитектура.
Только после этого подключайте реальные задачи выпуска. Сначала ограничьте долю производственных workflow и наблюдайте, совпадает ли фактическая причина ожидания с той, которую вы использовали при проектировании. Если очереди исчезли, но выросло время доставки Mac, масштабирование перенесло узкое место, а не устранило его.
Для удалённых Mac заранее подготовьте внутренний лист поставки: требуемое число узлов, архитектура, профиль Xcode, допустимое время выдачи, период аренды, правила удалённой перезагрузки и критерии очистки. На этом этапе можно изучить сценарии использования KVMFLUX, а затем сопоставить фактическую потребность с вариантами аренды и сроками доступа KVMFLUX. Это не заменяет проверку вашей интеграции: Runner Scale Set Client по-прежнему не отвечает за поставку Mac.
Что делать с текущей инфраструктурой
Если у вас уже есть постоянно включённые общие Mac, не заменяйте их одномоментно. Сначала переведите на новый маршрут тестовые задания без секретов, затем сравните очередь, время подготовки и количество загрязнённых рабочих сред. Фиксированные подписывающие узлы оставьте отдельно, если их изоляция и доступ к ключам действительно нужны.
Постоянный общий Runner имеет три системных недостатка: состояние накапливается между заданиями, секреты сложнее доказуемо удалить, а один неисправный хост может принимать задачи до момента обнаружения. Эластичный узел не устраняет все риски, но делает жизненный цикл явным: создать, зарегистрировать, выполнить, очистить, удалить.
Поэтому не рассматривайте текущую схему как автоматически лучшую только потому, что Mac уже куплены. Покупка оставляет вам капитальные затраты, простой при недозагрузке, обновление образов, ремонт и ручное расширение парка. При этом аренда удалённых Mac не является универсальным ответом: физические интерфейсы, долгий постоянный тяжёлый процесс и особые требования к размещению могут оправдать собственные узлы.
Если после расчёта вам нужны временные эластичные ресурсы, а не постоянная замена оборудования, KVMFLUX может быть практичнее для такой части пула: вы заранее сравниваете срок аренды, время поставки и требуемую ёмкость, не перенося подписывающие узлы без отдельной проверки. Сначала оформите список дефицита Mac-узлов и критерии готовности, затем решайте, какой объём стоит вынести наружу. Так аренда остаётся управляемым элементом гибридной архитектуры, а не непрозрачной заменой всей CI-системы.
Читайте также
- Настройка собственного runner на удалённом Mac для CI/CD
- Облачный CI для сборок macOS и iOS: практическое сравнение подходов
- Гибридный CI/CD с вебхуками и временными средами сборки
Масштабируйте macOS-инфраструктуру с KVMFLUX
Арендуйте удалённые Mac, чтобы гибко увеличивать число узлов сборки без постоянного расширения собственного парка оборудования. Подбирайте конфигурации и сроки аренды под нагрузку мобильной разработки, тестирования и непрерывной интеграции. Используйте выделенные ресурсы KVMFLUX для стабильной работы корпоративных процессов сборки и проверки приложений. Свяжитесь с KVMFLUX, чтобы обсудить подходящую схему подключения Mac и поэтапный запуск в вашей инфраструктуре.