Pools de runners auto-hébergés
Faites tourner vos agents sur des machines que vous hébergez. FerrFleet confie chaque exécution à l’un de vos runners, et le code comme l’identifiant Claude restent de votre côté.
Un pool de runners est un ensemble de machines que vous hébergez et qui prennent les exécutions des agents qui pointent vers lui. L’agent garde tous ses déclencheurs sur FerrFleet : plannings, webhooks, tickets, exécution lancée à la main. Ce qui change, c’est l’endroit où l’exécution tourne. Au lieu d’un Job dans le cluster FerrFleet, elle attend qu’un de vos runners demande du travail, et tourne chez lui.
Pourquoi un pool
- Votre code reste sur votre infrastructure. Le runner clone le dépôt sur votre machine, et l’agent travaille sur ce checkout, sur place.
- Votre identifiant Claude aussi. Le runner lance Claude avec une clé d’API Anthropic lue dans son propre environnement. FerrFleet ne reçoit jamais cette clé.
- Uniquement des connexions sortantes. Chaque appel part du runner vers
https://api.ferrfleet.com. Un runner fonctionne derrière un pare-feu qui n’autorise que le HTTPS sortant, sans port entrant à ouvrir. - Votre propre capacité. Une exécution de pool ne prend jamais de place dans le cluster FerrFleet et n’en attend jamais. Le nombre d’exécutions simultanées, c’est le nombre de runners que vous démarrez.
Un pool n’est pas la même chose qu’un agent réglé pour tourner dans votre propre pipeline (la GitHub Action). Dans ce cas, c’est votre CI qui crée l’exécution. Avec un pool, FerrFleet crée l’exécution comme d’habitude et vos runners l’exécutent. Un agent est dans l’un ou l’autre cas, jamais les deux.
Créer un pool
Dans l’app, ouvrez Runner pools dans la section Operate, puis New pool, et donnez-lui un nom. Les noms sont uniques parmi les pools de votre organisation.
Le jeton d’enregistrement du pool, qui commence par ffrp_, n’est affiché qu’une fois, juste après la création. Copiez-le alors dans votre gestionnaire de secrets : FerrFleet n’en garde qu’une empreinte et ne peut plus l’afficher. S’il est perdu ou s’il fuite, Rotate token en émet un nouveau et l’ancien cesse aussitôt de fonctionner, sans toucher aux agents du pool.
Le jeton permet seulement à un runner de prendre les exécutions de ce pool-là et de lire combien attendent. Il n’ouvre rien d’autre dans votre organisation.
Démarrer des runners
Un runner, c’est le FerrFleet Runner open source lancé avec ferrfleet-runner agent. Il a besoin de :
FERRFLEET_API_URL:https://api.ferrfleet.comFERRFLEET_POOL_TOKEN: le jetonffrp_...du poolANTHROPIC_API_KEY: votre clé d’API Anthropic, voir L’identifiant ClaudeFERRFLEET_RUNNER_NAME, facultatif : le libellé affiché sur la page de l’exécution, le nom d’hôte par défaut
Un runner exécute une exécution à la fois. Pour en faire tourner plusieurs en même temps, démarrez plusieurs runners.
Kubernetes avec KEDA
Le chart Helm fait passer un pool de zéro à la demande avec KEDA, qui doit déjà être installé dans le cluster. Il lit toutes les 10 secondes combien d’exécutions du pool attendent et démarre un Job par exécution en attente. Chaque Job prend une exécution puis s’arrête, donc chaque exécution démarre sur un pod propre. Quand rien n’attend, rien ne tourne.
kubectl create namespace ferrfleet
kubectl -n ferrfleet create secret generic ferrfleet-pool \
--from-literal=pool-token="$FERRFLEET_POOL_TOKEN" \
--from-literal=anthropic-api-key="$ANTHROPIC_API_KEY"
helm install ferrfleet-runner oci://ghcr.io/ferrlabs/charts/ferrfleet-runner \
--namespace ferrfleet \
--set poolToken.existingSecret=ferrfleet-pool \
--set claudeCredential.existingSecret=ferrfleet-pool
scaledJob.maxReplicaCount plafonne le nombre d’exécutions simultanées, 10 par défaut. Les pods tournent avec un utilisateur non root, un système de fichiers racine en lecture seule et aucune capability, et leur service account n’a aucune permission Kubernetes. Toutes les valeurs du chart sont listées dans le README du runner.
Kubernetes sans KEDA
Le même chart peut faire tourner un nombre fixe de runners de longue durée :
helm install ferrfleet-runner oci://ghcr.io/ferrlabs/charts/ferrfleet-runner \
--namespace ferrfleet \
--set mode=deployment \
--set deployment.replicas=3 \
--set poolToken.existingSecret=ferrfleet-pool \
--set claudeCredential.existingSecret=ferrfleet-pool
Docker Compose
Sur un hôte sans Kubernetes, l’exemple compose fait tourner un nombre fixe de runners avec le même durcissement. Copiez-en docker-compose.yml et .env.example, puis :
cp .env.example .env
$EDITOR .env
docker compose up -d
.env contient le jeton du pool et la clé d’API, gardez-le hors du contrôle de version. RUNNER_REPLICAS fixe le nombre de runners démarrés.
Un seul conteneur
docker run -d --restart unless-stopped \
-e FERRFLEET_API_URL=https://api.ferrfleet.com \
-e FERRFLEET_POOL_TOKEN \
-e FERRFLEET_RUNNER_NAME=build-farm-07 \
-e ANTHROPIC_API_KEY \
ghcr.io/ferrlabs/ferrfleet/runner:1 agent
Arrêter un runner
Sur SIGTERM, un runner arrête de demander du travail et laisse se terminer l’exécution en cours. Donnez-lui un délai de grâce aussi long que le timeout de vos agents : le chart accorde 30 minutes, l’exemple compose aussi. Un runner tué avant est traité comme un runner qui ne répond plus, voir plus bas.
Diriger un agent vers un pool
Sur la page de l’agent, Edit, puis l’onglet Execution. Avec Runner sur FerrFleet, réglez Run on sur le pool. Le remettre sur FerrFleet cluster renvoie l’agent sur notre cluster.
Le changement s’applique aux exécutions créées ensuite. Celles qui attendent déjà restent au pool pour lequel elles ont été créées.
Ce que devient une exécution
Elle attend un runner. Une exécution de pool ne démarre jamais dans le cluster FerrFleet, même si aucun runner n’est en ligne. Les exécutions vont aux runners dans leur ordre d’arrivée, la plus ancienne d’abord, et deux runners n’obtiennent jamais la même. La page de l’exécution indique quel runner l’a prise.
Le runner donne signe de vie. Du moment où un runner prend une exécution jusqu’à sa fin, il se signale à FerrFleet toutes les 30 secondes. C’est aussi par là qu’une annulation ou un commit plus récent lui parvient : le signal suivant lui dit d’arrêter, donc il s’arrête en moins de 30 secondes.
Un runner qui ne répond plus. Quand les signaux cessent pendant 90 secondes, FerrFleet règle le sort de l’exécution dans la minute qui suit :
- Si le runner n’avait pas encore démarré l’exécution, elle retourne au pool et le prochain runner qui demande du travail la reçoit. Rien n’a tourné, donc rien n’est perdu.
- S’il l’avait démarrée, l’exécution échoue, avec le code de sortie
126et une ligne dans le transcript indiquant que le runner a cessé de répondre. Elle n’est pas redistribuée : elle a peut-être déjà poussé une branche ou commenté une pull request, et la relancer le referait une seconde fois.
Les exécutions de pool ne sont pas relancées automatiquement.
L’attente de 6 heures. Une exécution qu’aucun runner ne prend attend jusqu’à 6 heures après sa création, puis se termine en timeout, et la page de l’exécution indique qu’aucun runner n’est venu la chercher. Cela laisse le temps à un pool réduit à zéro de démarrer une machine, et à un pool arrêté pour la nuit de retrouver ses exécutions le matin. Une fois qu’un runner a démarré l’exécution, c’est le timeout habituel de l’agent qui s’applique.
Révoquer un pool. Un pool vers lequel des agents pointent encore ne peut pas être révoqué : déplacez-les d’abord vers un autre pool ou vers le cluster FerrFleet. Rien ne bascule tout seul sur notre cluster. Une fois le pool révoqué, son jeton ne fonctionne plus et ses exécutions en attente sont annulées. Une exécution déjà démarrée par un runner se termine là où elle est.
L’identifiant Claude
Les runners utilisent une clé d’API Anthropic lue dans leur propre environnement, dans ANTHROPIC_API_KEY. C’est le réglage par défaut du chart Helm, de l’exemple compose et de l’image, et c’est l’option que nous recommandons. Créez la clé dans un workspace de la console Anthropic réservé à ces exécutions, pour que leurs dépenses et leurs limites de débit apparaissent à part.
La clé reste sur vos machines. Le runner ne l’envoie jamais à FerrFleet, et FerrFleet ne la demande jamais. Pour la changer, mettez-la à jour dans votre gestionnaire de secrets et redémarrez les runners : rien ne change côté FerrFleet.
Référence
- Référence de l’API des pools, en anglais : les endpoints de lease, de heartbeat et de file d’attente qu’utilisent un runner et un autoscaler.
- FerrFleet Runner : le code source du runner, toutes les valeurs du chart et la vérification de la signature de l’image.