Jobs à 4 Go de RAM : le lint typé d'ATLAS meurt à 3 Go (SIGABRT), et check bloque tout le reste #1
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Infrastructure/forgejo-runner#1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Demande
Passer la limite des jobs de 3 Go à 4 Go, sans swap comme aujourd'hui :
config.yml:options: "--memory=4g --memory-swap=4g --cpus=2.5 --pids-limit=512"docker-compose.yaml, servicedind:memory: 5getmemswap_limit: 5g. C'est la règle déjà écrite au-dessus : un job, plus dockerd, plus les conteneurs de service (Postgres d'integration).Si l'hôte ne peut pas les donner à tous les jobs, une seconde étiquette suffit, par exemple
node-22-4gà 4 Go, que seulcheckdemanderait.check.ymld'eqs-workflows prendrait alors une entréeruns-on.Pourquoi
ATLAS,
check.yml@v1, run du 2026-10-15 sur542d9ec:pnpm check --sequential→lint tuée par le système (SIGABRT), sans avoir pu rien dire. Le job tournait déjà avec les 3 Go du 2026-10-14. Ce n'est pas le noyau (ce serait SIGKILL) : c'est V8 qui abandonne, tas plein.Mesuré en local, même dépôt, ESLint 9.39, sans cache :
Le profil ESLint du socle (
projectService) charge un programme TypeScript complet partsconfig.json: chez ATLAS, trois (racine,tests/,worker/), chacun avec les types de Next 16 et de Prisma. Le tas seul dépasse 1,8 Go. À 3 Go de RAM au total, il ne reste pas la place pour le tas, le code de Node et le reste du processus.Conséquence aujourd'hui
checkest rouge à chaque push sur ATLAS.integration,contractetauditen dépendent (needs) et ne tournent jamais. Le pre-push local, sans plafond, passe.Lié
tsconfig), qui ne dispensent pas d'avoir la mémoire tant qu'elles n'existent pas.check.yml(« le runner donne 2 Go et 1,5 CPU ») est périmé depuis le 2026-10-14.Ouvert depuis une session de travail sur ATLAS.
Mesuré : ce n'est pas la RAM, c'est le plafond de tas de V8
Le job
checkd'ATLAS a été rejoué en conteneur aux limites exactes du runner :node:22-bookworm,--memory=3g --memory-swap=3g --cpus=2.5 --pids-limit=512, clone propre dea53d3ad, chaque tâche deeqs-checklancée seule avec--sans-cache. Le pic de mémoire anonyme du cgroup (memory.stat) est échantillonné chaque seconde : contrairement àmemory.peak, il ne compte pas le cache disque.oom_killNODE_OPTIONS=--max-old-space-size=2560Les autres tâches à 3 Go, réglage par défaut : types 1 386 Mo, types-tests 1 482 Mo, doctor 672 Mo, unit 466 Mo, format/knip/types-worker < 260 Mo. Toutes vertes.
Lecture. Node 22 dimensionne son tas à environ la moitié de la mémoire du conteneur : 1,58 Go pour 3 Go. Le lint en demande ~1,8 Go et V8 abandonne (SIGABRT), alors que le cgroup a encore plus d'un gigaoctet libre. Le noyau n'a jamais tué personne (
oom_kill 0).Ce que je propose à la place des 4 Go
Garder
--memory=3get donner aux jobs un tas à la mesure du conteneur, dansconfig.ymlà côté deoptions, pour que les deux valeurs bougent ensemble :Il reste ~550 Mo de marge au pic du lint. Le jour où le lint ou un build la mangera, passer à 4 Go et 3 584 Mo de tas, ensemble.
À noter : l'hôte Forge n'avait aucun swap (7,6 Go, 4,1 Go disponibles). Un fichier d'échange de 4 Go et
vm.swappiness=10y ont été ajoutés le 2026-10-15. Les jobs gardent zéro swap ; ce swap protège Forgejo et Coolify d'un pic dedind. Un redémarrage de l'hôte est en attente (mises à jour), sans lien avec ce réglage.Suite : le tas suffit au lint, mais les jobs qui construisent manquent de RAM à 3 Go
Run 14 d'ATLAS (après
376e8ad,NODE_OPTIONS=--max-old-space-size=2560) :checkest vert. En revanche :integration:next build, lancé par le test de conformité, meurt avec un codenull(signal) pendant « Running TypeScript » ;fuzzing(contract.yml) : le journal s'arrête net sur « Creating an optimized production build… ». Le job est resté affiché « running » alors que le run était terminé : le runner a perdu le job, sans rapporter sa fin.Mesuré en conteneur aux limites du runner (
--memory=3g --memory-swap=3g --cpus=2.5, clone propre,experimental.cpus: 3pour reproduire les 3 workers du VPS), pic de mémoire anonyme du cgroup :next buildà 3 Go, 3 workersSeul, le build passe de justesse. Dans le job
integration, il tourne en plus du processus vitest qui l'a lancé (Prisma, harnais) : la marge disparaît, et le noyau tue le build. LeNODE_OPTIONSn'y est pour rien : sans lui, la marge est même plus faible.Demande révisée
4 Go pour les jobs, comme demandé au départ,
dindà 5 Go, et zéro swap pour les jobs. LeNODE_OPTIONSreste utile au lint. Avec 4 Go, le monter à--max-old-space-size=3072laisserait la même marge au lint qu'aujourd'hui.L'hôte a désormais 4 Go de swap (2026-10-15) : un
dindà 5 Go ne mettrait plus Forgejo à la merci d'un pic.