Главная / Блог / GitHub Actions Runner Scale Set Client: стоит ли использовать для Mac CI в 2026
ENGINEERING_BLOG · 2026.09.20

GitHub Actions Runner Scale Set Client: стоит ли использовать для Mac CI в 2026

Симптом — очередь Mac-сборок растёт, а команда хочет включить GitHub Actions Runner Scale Set Client и автоматически добавлять узлы.

Быстрое решение — запустить ограниченный пилот для воспроизводимых PR-сборок, но не заменять им весь фиксированный Mac-пул: production-подпись и задачи с жёсткой задержкой должны остаться на прогретых или выделенных узлах. Такой подход оправдан только тогда, когда вы можете автоматически выдать реальный Mac, очистить его после задания, сохранить диагностические логи вне узла и переключиться на резервный Runner при сбое.

SECTION 01Кому нужен этот разбор

Материал рассчитан на команды, которые управляют несколькими репозиториями GitHub Actions Mac Runner и сталкиваются с очередями во время релизных пиков.

Он также нужен специалистам по безопасности, проверяющим остаточные данные после одноразового запуска, и руководителям, сравнивающим покупку Mac, удалённую эластичную ёмкость и смешанный пул по TCO.

Последнее обновление — 20 сентября 2026 года. Статус Public Preview, поддержку macOS, модель Scale Set API и обязанности владельца инфраструктуры следует повторно проверять по официальному объявлению GitHub о публичном предпросмотре, документации и репозиторию actions/scaleset.

SECTION 02Граница ответственности

GitHub Actions Runner Scale Set Client — это клиентская часть, которая взаимодействует с Scale Set API, получает сведения о назначенных заданиях и помогает управлять жизненным циклом Runner. Он не является фабрикой физических Mac.

Вы по-прежнему отвечаете за:

  • выделение или включение Mac-хоста;
  • установку и подготовку macOS;
  • установку Xcode, зависимостей и системных компонентов;
  • регистрацию Runner и выдачу JIT-конфигурации;
  • удаление рабочих файлов, кэшей и временных ключей;
  • отключение или уничтожение узла;
  • передачу логов до удаления хоста;
  • маршрут восстановления при недоступности клиента или провайдера.

Это принципиальное ограничение подтверждается описанием пользовательской инфраструктуры в официальном репозитории actions/scaleset. Если ваша команда рассчитывает, что клиент сам создаст Mac mini, разблокирует систему, настроит Keychain и гарантированно сотрёт диск, архитектура уже содержит ошибку ответственности.

Может ли Runner Scale Set Client сам создать Mac для сборки?

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

Матрица первого решения

Вариант Когда выбирать Основной риск Обязательное условие
Фиксированный Mac-пул Нужны предсказуемый запуск, production-подпись и постоянное состояние инструментов Платите за простаивающую ёмкость и обслуживаете узлы вручную Регулярное обновление, мониторинг и разграничение доступа
Эластичный пул Scale Set PR-сборки воспроизводимы, пики заметны, Mac можно быстро подготовить и очистить Холодный запуск может съесть выигрыш от расширения Автоматическая поставка Mac, JIT-регистрация, внешние логи и откат
Смешанный пул Нагрузка неоднородна, а подпись и релиз требуют доверенного контура Сложнее маршрутизация и расчёт TCO Явные labels, отдельные Runner groups и запасной маршрут

В качестве первого кандидата выбирайте повторяемую сборку pull request без production-сертификатов и долгоживущих секретов. Не переносите в первый пилот публикацию в App Store, ручное подписание и задания, которым критична каждая минута задержки.

SECTION 03Метрика эластичной ёмкости

Событие в очереди не равно одному новому Mac. Для решения о расширении нужно сопоставлять как минимум четыре состояния:

  • число назначенных заданий — TotalAssignedJobs;
  • число заданий, которые уже выполняются;
  • число ожидающих заданий;
  • число Mac, которые реально можно выдать в заданный момент.

В описании масштабирования actions/scaleset логика разделяет потребность в Runner и фактическое предоставление инфраструктуры. Это означает, что обработчик каждого сообщения не должен механически запускать новый хост. Один уже доступный Mac может принять следующее задание, несколько событий могут относиться к одной очереди, а provisioning может завершиться неудачей.

Соберите собственную запись для каждого задания:

  1. время появления задания в очереди;
  2. время назначения Runner;
  3. время готовности Mac;
  4. время запуска процесса Runner;
  5. время начала Job;
  6. время завершения и удаления окружения;
  7. причина повторного назначения или отказа.

Без этих отметок вы не сможете отделить нехватку Mac от задержки GitHub API, медленной загрузки образа, установки Xcode или ошибки регистрации.

Полностью по требованию и предварительный прогрев

При полностью по требованию вы экономите на простаивающих узлах, но каждый пик оплачивается задержкой поставки. Подход подходит для редких PR-сборок, если очередь может ждать, а среда действительно воспроизводима.

Минимально прогретая ёмкость держит небольшое число готовых Mac и добавляет новые узлы только после роста очереди. Это часто разумнее полного «нуля», когда релизные окна короткие, а запуск macOS-компонентов занимает заметную часть времени.

Фиксированный базовый пул нужен там, где задержка непредсказуема или где подготовка подписи не может выполняться в недоверенной временной среде. GitHub рекомендует использовать группы и labels для контроля назначения Runner; соответствующие ограничения доступа описаны в документации Runner groups.

Нужен ли Kubernetes для эластичного Mac Runner?

Нет, Kubernetes не является обязательным условием. Он может быть удобным управляющим слоем для части автоматизации, но сам по себе не создаёт физический Mac и не решает вопросы разблокировки macOS, Keychain, очистки и уничтожения узла. Вы можете построить поставщик Mac на другом оркестраторе или внутреннем сервисе, если он выдаёт Scale Set Client корректное состояние и надёжно обрабатывает повторные запросы.

SECTION 04Метрика изоляции задания

JIT Runner ограничивает срок регистрации Runner, но короткая регистрация не доказывает чистоту всей машины. Нужно отдельно проверять четыре жизненных цикла:

  • жизненный цикл регистрации Runner;
  • жизненный цикл macOS-хоста;
  • жизненный цикл workspace и кэшей;
  • жизненный цикл Keychain, сертификатов и signing identity.

В справочнике GitHub по self-hosted Runner и рекомендациях по безопасному использованию одноразовый запуск рассматривается как мера снижения риска, а не как автоматическая гарантия удаления каждого секрета.

Может ли JIT Runner изолировать Xcode workspace и сертификаты подписи?

JIT Runner помогает ограничить регистрацию и повторное использование Runner, но сам по себе не изолирует Xcode workspace, локальные кэши и Keychain. Если разные задания выполняются на одной Mac-системе, исходники, DerivedData, Swift Package Manager cache, provisioning profiles и временные токены могут пережить процесс Runner.

Для доверенной изоляции выбирайте один из вариантов:

  • новый или гарантированно очищенный Mac на каждое задание;
  • отдельный системный пользователь и уничтожаемый workspace;
  • отдельный Keychain с контролируемым временем жизни;
  • отсутствие production-секретов в эластичном пуле;
  • проверка диска и каталогов после выполнения;
  • блокировка маршрутизации непроверенных веток к подписывающему узлу.

Production-подпись по умолчанию должна идти в фиксированный или специально выделенный пул. PR из внешнего источника не должен получать доступ к тому же signing identity, который используется для выпуска продукта.

Важное ограничение: «Runner автоматически удалён» и «Mac очищен» — разные утверждения. В акте приёмки требуйте доказательство второго, иначе JIT-режим создаёт только видимость одноразовой среды.

SECTION 05Метрика задержки доставки

Разделите cold start на отдельные интервалы, иначе средняя величина будет скрывать узкое место:

  1. поставщик получил запрос на Mac;
  2. хост стал доступен по управляемому каналу;
  3. macOS завершила загрузку и разрешила нужный режим доступа;
  4. установлены или проверены системные компоненты;
  5. Runner получил регистрацию;
  6. Xcode и зависимости прошли инициализацию;
  7. первый Job был принят;
  8. после завершения запущены очистка и возврат узла.

Не подставляйте в финансовую модель время, взятое из чужого окружения. На него влияют версия macOS, Xcode, способ доставки зависимостей, локальный кэш, состояние FileVault, сетевой маршрут и доступность Apple-сервисов. Для своей оценки используйте журнал заданий и официальный раздел мониторинга и диагностики Runner.

Практический тест должен сравнить три режима:

  • полностью холодный запуск;
  • один или несколько прогретых Mac;
  • фиксированный базовый пул с эластичным расширением.

Сравнивайте не только время до зелёного статуса. Зафиксируйте долю заданий, которые начали выполняться после ожидаемого окна, частоту повторной постановки в очередь и количество неуспешных provisioning-операций.

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

SECTION 06Метрика контроля и восстановления

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

  • клиент получил сообщение, но упал до создания Mac;
  • Mac создан, но Runner не зарегистрирован;
  • Runner зарегистрирован, но Job не принят;
  • Job прерван потерей связи;
  • узел завершил работу, но очистка не подтверждена;
  • лог не успел уйти во внешнее хранилище;
  • провайдер не вернул узел после тайм-аута.

Для интеграции используйте минимально необходимые полномочия GitHub App или токена. Возможности и границы REST-интерфейса self-hosted Runner приведены в официальной документации API, а варианты аутентификации Scale Set Client — в разделе authentication официального репозитория.

Логи временного узла нужно отправлять во внешнюю систему до его уничтожения. Сохраняйте как минимум идентификатор задания, label, причину завершения, этап provisioning, версию образа, состояние очистки и диагностический вывод клиента. Секреты и содержимое исходников при этом не должны попадать в общий журнал.

Пошаговая процедура пилота

  1. Разделите классы заданий. Создайте отдельные labels для PR, регрессионных тестов, архивации и production-подписи. Не начинайте с единого маршрута для всех workflows.

  2. Определите источник ёмкости. Зафиксируйте, кто создаёт Mac, кто устанавливает системные компоненты и кто подтверждает доступность хоста. Если на один из вопросов нет владельца, эластичный пул ещё не готов.

  3. Ограничьте права. Создайте отдельную Runner group, минимальный набор разрешений и отдельный набор секретов для пилота. Доступ веток и репозиториев должен быть проверяемым правилом, а не устной договорённостью.

  4. Снимите базовую линию. В течение репрезентативного периода запишите очередь, длительность Job, cold start, долю повторных попыток и простой фиксированного пула. Число узлов не назначайте заранее — его нужно вывести из наблюдаемой очереди и времени поставки.

  5. Включите JIT-регистрацию. После выдачи Mac регистрируйте Runner только на нужный класс заданий, а после завершения удаляйте регистрацию, workspace, временные ключи и локальные артефакты.

  6. Проверьте негативные сценарии. Намеренно прервите provisioning, отключите Runner во время Job и смоделируйте недоступность внешнего хранилища логов. Успешным считается не восстановление процесса клиента, а возврат задания в разрешённый фиксированный или резервный пул.

  7. Проведите контрольный аудит. После уничтожения узла подтвердите отсутствие рабочего каталога, кэшей, профилей и signing identity, которые не должны были покинуть доверенный контур. Сохраните результат вместе с логом задания.

  8. Сравните стоимость по классам работ. Отдельно посчитайте фиксированную ёмкость, минимальный прогрев, создание по требованию, автоматизацию обслуживания и стоимость неудачных запусков. Не называйте экономией простое уменьшение числа купленных Mac: время команды, резерв и аварийный маршрут входят в TCO.

SECTION 07Метрика TCO и распределение задач

Удобная модель для одного периода выглядит так:

TCO = фиксированная ёмкость + прогретая ёмкость + созданные по требованию узлы + сопровождение + хранение логов + стоимость отказов.

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

Как разделить фиксированный Mac Runner и эластичный Scale Set?

Используйте фиксированный или выделенный пул для:

  • production-подписи;
  • публикации релизных артефактов;
  • заданий с коротким и жёстким SLA;
  • инструментов, требующих длительного локального кэша;
  • доверенных операций с постоянным Keychain.

Эластичный пул подходит для:

  • PR-проверок;
  • повторяемых сборок без production-секретов;
  • временной симуляторной регрессии;
  • непиковых задач, которые допускают задержку поставки;
  • кратковременного роста очереди.

Если команда пока не умеет автоматически удалять рабочую среду, не переносите туда чувствительные задания даже при наличии JIT. Если cold start стабильно превышает допустимое окно релиза, не увеличивайте число эластичных узлов вслепую — сначала оставьте минимальный прогретый резерв.

Для предварительного расчёта инфраструктуры используйте страницу тарифов MACNOX только вместе с вашим профилем загрузки: стоимость аренды Mac — лишь одна строка модели, а не готовый ответ о выгоде. Для пилота временной удалённой Mac-ёмкости можно рассмотреть доступные варианты заказа MACNOX, но проверяйте конкретные способы доставки, очистки и переключения по действующим условиям.

SECTION 08Итоговое решение

Оставляйте текущий фиксированный пул, если у вас нет владельца Mac provisioning, очистка не подтверждается артефактами, production-подпись смешана с PR-задачами или холодный запуск уже превышает допустимую задержку.

Запускайте ограниченный пилот, если есть воспроизводимый класс PR-сборок, внешний сбор логов, JIT-регистрация и понятный откат на фиксированные Runner. На первом этапе измеряйте не обещанную эластичность, а фактическое сокращение очереди без роста повторных запусков и инцидентов безопасности.

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

Если сейчас вы используете собственные Mac без автоматического восстановления, слабые места обычно находятся в трёх местах: оборудование простаивает между пиками, ручная очистка оставляет кэши и секреты, а отказ узла превращает очередь в ручную операцию. Аренда удалённых Mac у MACNOX может быть практичнее для ограниченного пилота и резервной ёмкости, потому что вы сначала проверяете запуск, доступ и возврат узла на реальной инфраструктуре, не покупая отдельный Mac под ещё не подтверждённую нагрузку. Но production-подпись всё равно следует подключать только после вашей проверки изоляции, журналирования и аварийного переключения.

SECTION 09Дополнительные материалы