Matrice de décision · Exploitation & collaboration 2026

2026 Petites équipes — Mac distant partagé : file type Nomad (ordonnanceur léger) vs éventail cron maison — latence, préemption, checklist conflits build

2026.04.10 Équipe Meshmac 8 min de lecture

« On met cinq scripts en cron chaque minute » : voilà comment un Mac build mutualisé devient une loterie — xcodebuild qui se chevauchent, deux pipelines sur le même cache CocoaPods, et personne ne sait qui tient le CPU. Une voie façon Nomad (job, allocation, politique de redémarrage, anti-chevauchement déclaratif) coûte plus cher le premier jour, mais achète une sémantique de préemption lisible et un historique auditable. Sur macOS, le plan de contrôle vit souvent hors de la machine (petite VM Linux, runner cloud) : le Mac reste le point d’exécution Xcode — c’est normal et sain. Cette matrice fixe les frontières, les chiffres d’exploitation et une checklist d’acceptation pour les équipes qui opèrent un pool type MeshMac.

Sommaire

Limites des scénarios

Éventail cron + scripts shell reste défendable lorsque (a) un seul compte ops possède toutes les entrées crontab, (b) les tâches sont courtes et idempotentes, (c) chaque ligne enveloppe une section critique avec flock et un plafond wall-clock, et (d) vous acceptez une jitter de planification à l’échelle de la minute. La frontière se franchit dès que plusieurs squads enfilent du travail, que la CI et les humains partagent les mêmes couloirs, ou que vous devez exprimer des priorités (release avant captures nocturnes) et de l’équité (aucun cron ne doit affamer les autres).

Ordonnancement façon Nomad (Nomad réel ou tout orchestrateur partageant les mêmes concepts : tâche paramétrée, politique de redémarrage, anti-chevauchement, étiquettes) vaut le coup lorsqu’il faut fixer un plafond de concurrence par clé — par exemple « au plus une voie codesign par hôte », « deux résolutions SwiftPM mais une seule archive » — et lorsque redémarrage et reschedule doivent être déclaratifs plutôt que du bash copié-collé dans six dépôts. Gardez le vocabulaire unique : un fichier HCL ou YAML lu par l’astreinte vaut mieux que douze README contradictoires.

Tracez une ligne dure : si deux jobs peuvent toucher le même répertoire mutable sans domaine de verrou documenté, vous êtes déjà en territoire file + flock, pas « juste du cron ». Les échecs « sociaux » (occupation fantôme, VNC par-dessus une archive) ne disparaissent pas avec un planificateur : croisez avec la FAQ fuseaux, réservations et files sur Mac partagé. Quand vous ajoutez un second nœud, alignez la synchronisation des étapes déployées et de la file avec le guide OpenClaw MeshMac — déploiement unifié et file de tâches.

Tableau comparatif des modèles de file

Lisez les colonnes comme des contrats d’exploitation : ce que l’astreinte peut inférer à 2 h du matin sans ouvrir toute la boîte mail. Le planificateur ne remplace pas macOS : il ordonne des processus ; le noyau et les ACL décident qui écrit où.

Dimension Cron + enveloppes shell File légère façon Nomad
Latence premier démarrage Bornée par la période cron (souvent 60 s) ; la réduire augmente le risque de ruée. Pilotée par événements ou file ; p50 souvent sous la minute si les workers sont chauds.
Contrôle de concurrence Manuel : flock par script, compteurs processus ou Redis — dérive facile. Déclaratif : groupes de tâches, count, spread, affinité ; un seul endroit pour les plafonds.
Préemption / isolation Aucune sans signaux maison ; « tuer le long job » reste du folklore. Politiques restart/reschedule et classes de priorité ; journal par allocation.
État et observabilité Journaux éparpillés ; corrélation rarement homogène. Historique central ; labels standard (job, alloc) pour métriques.
Charge ops Coût d’installation faible, coût de dérive quand l’équipe grossit. Investissement initial plus haut ; moins de surprises au cinquième développeur.
Mode d’échec typique Chevauchement silencieux + corruption de cache. Contraintes mal modélisées (mauvais spread) → famine — corrigeable dans le spec, pas dans le chat.

Extraits de configuration exécutables

Cron resserré : un couloir, attente de verrou bornée, refus d’empiler aveuglément.

# Fragment /etc/crontab — utilisateur buildlane uniquement
*/1 * * * * buildlane /usr/bin/flock -n /var/run/meshmac/build.lane.lock \
  timeout 45m /usr/local/bin/run-ci-dequeue.sh >>/var/log/meshmac/dequeue.log 2>&1

Au début de run-ci-dequeue.sh, vérifiez la profondeur en attente : si la liste Redis, la table SQLite ou l’API dépasse ~20 jobs, sortez avec un code non nul (ex. 77) et pagez — ne laissez pas les clients pendre sans nouvelle. Les recettes flock -n / flock -w sont détaillées dans la FAQ file de build, flock et sérialisation.

Lot périodique façon Nomad (HCL illustratif sur le plan de contrôle ; la charge réelle SSH vers le Mac reste dans le script) :

job "meshmac-mac-build" {
  datacenters = ["dc1"]
  type        = "batch"

  periodic {
    cron             = "*/2 * * * *"
    prohibit_overlap = true
  }

  group "lane" {
    count = 1

    task "dequeue" {
      driver = "exec"
      config {
        command = "/usr/local/bin/run-ci-dequeue.sh"
      }
      resources {
        cpu    = 500
        memory = 512
      }
      restart {
        attempts = 3
        interval = "30m"
        delay    = "30s"
        mode     = "delay"
      }
    }
  }
}

Activez prohibit_overlap pour les jobs périodiques qui matérialisent une seule voie d’archive physique : c’est l’équivalent planificateur de « ne jamais empiler deux archives Xcode sur le même DerivedData ». Loguez côté worker chaque tentative de dequeue avec jitter borné pour éviter les rafales synchrones après un redémarrage du plan de contrôle.

Permissions et verrous

Le planificateur planifie ; macOS applique. Utilisez un compte dédié buildlane (ou par équipe) pour le non interactif, distinct des sessions console humaines, et limitez l’accès trousseau aux identités de signature de ce compte. Les LaunchDaemon root doivent appeler sudo -u buildlane plutôt que lancer Xcode en root.

  • Granularité des verrous : un fichier .lock par ressource logique (Pods, cache npm, créneau Simulateur), pas un verrou géant pour tout le disque sauf si vous sérialisez volontairement l’intégralité des builds.
  • Métadonnées de file : stockez job_id, commit, runner_name dans un petit JSON à côté du verrou pour que l’astreinte sache qui devrait encore tourner.
  • Isolation lors d’une préemption : si vous tuez une allocation, des hooks trap doivent nettoyer les arbres .xcarchive partiels et relâcher les verrous — le planificateur relancera ; le disque ne doit pas se remplir d’orphelins.

Checklist d’acceptation — conflits de build

  • Deux jobs « dry-run » sur le même chemin de checkout n’entraînent aucun chevauchement d’écriture (ou il est confiné sous flock < 120 s).
  • La CI et les scripts manuels passent par le même point d’entrée dequeue — aucun cron « secret » ne contourne la file.
  • La médiane d’attente de verrou reste sous le SLA publié ; alerte si p95 > ~15 min.
  • Tuer le job en cours ne laisse aucun détenteur fantôme de flock (PID vérifié, procédure documentée avant suppression du .lock).
  • Après cinq archives nocturnes consécutives, l’espace libre reste > 15 % — sinon élargissez les couloirs ou ajoutez des nœuds.

Paramètres timeout et backoff

Copiez ces repères dans votre runbook interne puis ajustez à partir des p95 de durée de build mesurés sur votre monorepo — les chiffres ci-dessous sont des points de départ pour petites équipes sur Apple Silicon mutualisé.

Paramètre Base cron + shell Base façon Nomad
Wall-clock par job timeout 45m couloir léger ; 90m archive lourde. Alignez kill_timeout tâche sur les mêmes ordres de grandeur ; évitez le défaut ~30 s pour Xcode.
Attente de verrou flock -w 180 pour gestionnaires de paquets ; échec rapide + métrique si timeout. Encodez l’attente dans le worker ; le redémarrage planificateur ne doit pas boucler serré — minimum delay = "30s".
Backoff retry Exponentiel : 30 s, 60 s, 120 s plafonnés ; jitter multiplicateur 0,8–1,2. reschedule avec max_delay = "5m", delay_function = "exponential".
Plafond global en attente ~20 jobs en attente par couloir ; rejet avec code HTTP ou exit actionnable. Appliquez côté soumission + file ; Nomad ne devine pas votre SLA métier.

Exemple bash (bash 5+) avant un retry dequeue : sleep $((30 + RANDOM % 30)). Journalisez attempt, next_backoff_s et reason sur chaque branche pour que vos requêtes Grafana ou CloudWatch restent ennuyeuses — c’est le signe d’une exploitation mature sur Mac loués partagés.

FAQ

Dois-je absolument installer Nomad sur le Mac lui-même ?
Non. Beaucoup d’équipes exécutent le planificateur sur Linux et traitent chaque Mac comme exécuteur distant. L’important est un contrat déclaratif unique pour chevauchement, redémarrage et historique — pas la marque du binaire.
Le cron est « plus simple » — pourquoi ma file explose quand même ?
La simplicité à l’installation n’égale pas la simplicité en régime établi. L’éventail sans plafond central de profondeur crée une file cachée ; raccourcir la période cron ne fait qu’envoyer plus de processus vers les mêmes verrous.
Où doivent vivre les règles de préemption ?
Dans la couche planificateur pour le cycle de vie des allocations, et dans les runbooks pour les sessions humaines (VNC, pair programming). Ne comptez pas sur « tout le monde sait qu’on n’archive pas à midi ».
Cron resserré ou Nomad léger : que faire quand la checklist d’acceptation échoue encore ?
Si le p95 d’attente dépasse votre budget malgré verrous et plafonds, scalez horizontalement avant d’augmenter la concurrence YAML sur un seul disque : réservez un second Mac pour codesign ou nocturnes, gardez l’interactif sur un autre nœud, et laissez la politique de file honnête. Comparez les forfaits multi-nœuds et ressources build mutualisées sur Meshmac, parcourez l’accueil pour le contexte matériel, et ouvrez le centre d’aide pour SSH, VNC et onboarding — sans création de compte obligatoire.

En synthèse : l’éventail cron est un hack de couloir unique valable tant que flock, timeouts et caps de profondeur sont traités comme du code production. La file façon Nomad paie dès que les clés de concurrence, la politique de redémarrage et l’historique d’audit doivent refléter comment l’équipe partage réellement le temps Xcode. Dans les deux cas, permissions macOS et domaines de verrou restent non négociables.

Passer la matrice en capacité

Ajoutez des nœuds avant d’ajouter de la contention

Lorsqu’un seul Mac ne tient plus le p95 d’attente de votre checklist, enchaînez avec des offres multi-nœuds ou des builders partagés dédiés plutôt qu’une troisième archive concurrente sur le même SSD. La page d’achat publique compare les forfaits sans connexion ; l’accueil Meshmac résume le service ; le centre d’aide couvre la mise en route. Poursuivez ensuite dans l’index du blog (guides multi-nœuds, retry, TLS).

Acheter — sans connexion