В 2026 году, когда Mac mini M4 объединяют в параллельный кластер между регионами, узкое место чаще оказывается не в CPU, а в планировании Nomad, едином писателе артефакта и дисковых порогах расширения. Три опоры — метки клиента, build lock и матрица «1 ТБ / 2 ТБ».

Почему одного Nomad мало для «параллельной» фермы

Двойная запись в общий том ломает деревья артефактов; при трансграничной задержке порядок синхронизации может «переворачиваться», и вы получите обрывки бинарников. Сочетайте build lock на уровне ОС с политикой fan-out и promotion — параметры rsync и дисковые пороги разобраны ниже в разделе о стыке с rsync и в связанной статье блога по той же линейке.

  • Дрейф размещения: без meta тяжёлый batch случайно попадает на «лёгкий» узел, IO становится зубчатым.
  • Два писателя: если несколько job’ов одновременно promote в один каталог, приёмник rsync оказывается повреждённым.
  • Обрыв диска: даже на 1 ТБ DerivedData и симуляторы быстро загоняют том в жёлтую зону; конфигурация 2 ТБ лишь отодвигает ту же проблему без ротации.

Матрица решений: роль Nomad × хранилище

Топология Цель на стороне Nomad Хранилище и синхронизация
Один «золотой» узел + fan-out воркеры promote — count = 1 или отдельная очередь; остальное — batch. После фиксации золотого каталога — rsync на чтение/инкремент; bwlimit по профилям региона.
Золотой на каждый регион meta region_lane в constraint; аффинити ведёт тяжёлую компиляцию на выделенные Mac mini M4. Больше сверок консистентности и времени. Split DNS и реестр — по чек-листу из статьи про split DNS и реестр.
Полная локальная сборка на каждом узле spread по node.datacenter; артефакты уводите в объектное хранилище или собирайте только через promote. Пороги диска срабатывают раньше; планируйте линию 2 ТБ и агрессивную чистку кэшей.

На практике наименьше инцидентов даёт правило: «компиляция параллельна, запись в канонический каталог и rsync-promote — однопоточны».

Исполняемые ограничения job: смысл фрагментов HCL (без полного файла)

На каждом клиенте задайте meta — например ci_tier (heavy/light), artifact_lane (golden/worker) и disk_class (1tb/2tb). В спецификации job уровень job обычно получает type = "batch" для одноразовых сборок; блоки constraint с оператором = или distinct_hosts отсекают неподходящие узлы (обязательные условия). Блоки affinity с весом задают «мягкое» предпочтение: например чаще выбирать узлы с meta.disk_class = 2tb, не ломая планирование, если таких мало.

Внутри group поле count для promote держите равным единице; для воркеров — по числу параллельных слотов. Секция spread по node.datacenter или по произвольному атрибуту равномерно распределяет batch, чтобы один датацентр не съел всю очередь. Для задач с чувствительным SLA поднимайте priority и сузьте restart, чтобы «зацикленный» promote не забивал очередь. Интерактивный SSH/Mosh для операторов держите отдельно от этой плоскости пакетной выкладки, иначе смешиваются SLA и блокировки.

Элемент constraint affinity
Назначение Жёсткий фильтр: job не стартует, если условие не выполнено. Предпочтение с весом: планировщик старается выполнить, но может отступить.
Типичный кейс на Mac mini M4 Только узлы с artifact_lane = golden для promote. Предпочесть disk_class = 2tb для тяжёлого Xcode batch.
Риск Слишком узкие правила → pending без явной причины в UI. Слишком высокий вес → неочевидный перекос по одному пулу.

Мини-пример смысла (не полный HCL): для группы компиляции добавьте пару constraint на ${meta.ci_tier} и ${node.class}; для promote — отдельный job с единственной группой, constraint «только golden», без spread по воркерам.

Build lock: два уровня — планировщик и ОС

Nomad разводит размещение, но разделяемое дерево APFS всё равно нужно защищать: короткий участок promotion оборачивайте flock. Batch пишет в локальный WORK_DIR; только после эксклюзивной секции — rsync в канонический путь. Поверх SSHFS advisory-lock считайте ненадёжным.

LOCK_FILE="/var/tmp/ci-artifact-promote.lock"
flock -n "$LOCK_FILE" bash -c '
  ./scripts/compile.sh
  rsync -az --delete ./out/ "/Volumes/Artifacts/promote/"
' || { echo "блокировка занята"; exit 17; }

Обертку вызывайте из задачи exec или raw_exec. Код выхода 17 трактуйте как метрику конкуренции за promote.

Пороги расширения: 1 ТБ и 2 ТБ (матрица)

Заполнение тома Линия 1 ТБ Линия 2 ТБ
до ~70% Рутинная чистка DerivedData и старых симуляторов; ротация логов Nomad. То же; запас больше, но политику не отменяет.
70–80% (жёлтая зона) В спринте закрепите апгрейд диска или вынос архивов; ограничьте новые «полные» сборки на всех узлах. Жёлтая зона наступает позже — заранее снизьте одновременность burst-batch.
80–90% Сузьте параллелизм исполнения и bwlimit fan-out rsync; при необходимости остановите всё, кроме promote, пока не отступит заполнение. На 2 ТБ снова наступит давление, если копятся версии симуляторов; связка с meta disk_class помогает Nomad не забивать «тонкие» узлы.
>90% (красная зона) Жёсткий стоп до касания скрытого объёма APFS и снимков. Расширение кластера или диска — в приоритете. Пороги — триггеры масштабирования; закрепите их на дашборде SRE.
70%
Ориентир для автоматической уборки.
80%
Жёлтая зона: план расширения в работу.
90%
Красная зона: новый fan-out и тяжёлый batch — стоп.

Сравнить конфигурации и шаг диска без аккаунта можно на странице «Тарифы» — удобно заложить запас до жёлтой зоны.

Стык с rsync-синхронизацией артефактов

Расписание и очередь оставьте в Nomad; после появления «золотого» снимка распространение делайте профилями rsync — так проще читать полосу, докачку и таймауты. Единственный писатель кладёт gate-файл (контрольная сумма или манифест); fan-out воркеры тянут дерево только после проверки. Смещайте периодические оценки диска и rsync, чтобы не бить по IO одним фронтом. Подробные флаги и runbook — в материале про rsync-матрицу; держите оба документа согласованными для команды эксплуатации.

FAQ: Nomad и параллельный Mac-кластер

Constraint против affinity: обязательные условия — в constraint; экономия и мягкое предпочтение узлов — в affinity.

flock постоянно «занят»: критическая секция слишком широкая; укоротите promote, компиляцию вынесите за пределы лока.

2 ТБ, а жёлтая зона снова близко: узкое место в политике симуляторов и кэшей; разведите «тяжёлые» и «лёгкие» узлы через meta и очереди Nomad.

Инженерные ориентиры. Проценты заполнения зависят от провайдера и профиля IO; это цели проектирования, а не договорной SLA. Перед боевым --delete в rsync прогоняйте dry-run.
Параллельные Mac-ресурсы

Стабильный Nomad + rsync на однотипных Mac mini M4

Без входа в аккаунт откройте тарифы и оформите узлы: выровняйте пул под Nomad, согласуйте класс диска и расширяйтесь до жёлтой зоны диска.

Купить узлы кластера Сравнить тарифы