Provisionnement
Ce que le moteur installe à l'étape Infrastructure.
L'étape Infrastructure est celle où tout est assemblé sur l'hôte. Le moteur installe, en séquence, avec une progression transmise en direct :
- k3s — Kubernetes léger et de qualité production (s'étend au multi-nœud par la suite).
- Ingress (Traefik) + cert-manager — routage et TLS automatique via Let's Encrypt.
- PostgreSQL et Redis in-cluster — la base de données définitive et la file/pub-sub de logs.
- Le registre d'artefacts et les Runners de CI.
- Le runtime serverless du Déploiement.
- Les images définitives de api et web (déploiement + migrations + seed du super administrateur en tant que Jobs in-cluster).
equantic-space-* (namespace equantic-space, Deployments equantic-space-api / equantic-space-platform, base de données equantic-space-db).Runners de CI
Les jobs de pipeline s'exécutent comme des pods isolés sur le cluster — un pod par job, avec ses propres limites CPU/mémoire, si bien qu'un job lourd ne peut jamais affamer la plateforme ni ses voisins. La capacité est dérivée du cluster lui-même (en réservant toujours de la marge pour le control plane) : les jobs au-delà du plafond attendent dans la file, et ajouter un nœud à la fleet augmente automatiquement la capacité de CI. Un job pour lequel le cluster n'a toujours pas de place à la création de son pod attend lui aussi, en l'indiquant dans son log, au lieu d'échouer. Son timeout-minutes ne commence à compter qu'une fois le pod créé.
Chaque conteneur du pod d'un job est borné — le job lui-même, ses sidecars services: et le daemon Docker propre au job portent tous des plafonds explicites, et le disque du job a sa propre taille (ci-dessous), de sorte qu'un job qui s'emballe s'évince lui-même au lieu de mettre le nœud sous pression. Le timeout-minutes du job est lui aussi estampillé sur le pod : même si le processus de la plateforme meurt en plein job, le cluster retire le pod de lui-même.
docker build (ou de Testcontainers) dans les jobs ? Passez EQS_RUNNER_DIND=true à l'installateur — EQS_RUNNER_DIND=true bash install.sh, à la première installation ou lors d'une mise à jour. Chaque job reçoit alors son propre daemon Docker privé, jamais partagé entre jobs ni workspaces. Cela vaut pour tous les jobs de l'installation, et le daemon est privilégié : activez-le délibérément.Ajuster la capacité
Le calcul est un bon défaut, pas un verdict : dans Paramètres → Plateforme → Capacité CI, vous décidez quelle part de la machine le runner peut prendre, et chaque modification montre ce qu'elle donnerait sur ce cluster avant d'être enregistrée.
Le panneau à côté des champs répond à la question que les chiffres seuls n'ont jamais tranchée : pourquoi seulement autant ? Pour le nœud qu'il lit, il montre ce que le nœud possède, ce que prend la plateforme (son usage mesuré plus la marge de la réserve, pas seulement le pourcentage), ce qui reste au CI, la part de chaque job, et la limite qui a décidé du nombre, que ce soit le CPU cible par job, le plancher mémoire, le plafond fixe, une taille fixe ou le plancher d'admission. Avec plusieurs nœuds, choisissez lequel lire, et le total de la flotte s'affiche à côté.
Deux réglages comptent le plus. La réserve de la plateforme est la part de chaque nœud que le CI ne touche jamais : la baisser donne plus au CI au total, mais davantage de créneaux se partagent alors la mémoire, et chaque job peut finir plus petit. Et le « ne pas démarrer en dessous de » est un plancher d'admission : le plafond d'un job est figé à la création de son pod, si bien qu'une baisse passagère de mémoire libre peut imposer à un build de deux heures une limite sous laquelle il n'aboutit pas. Sous ce plancher, le nœud n'offre aucun créneau et le job attend dans la file — tard vaut mieux qu'infirme.
La réserve a aussi un plancher absolu — au moins 2 cœurs et 3 Gio restent au control plane, quoi qu'en dise le pourcentage (il se réduit de lui-même sur les hôtes minuscules). Un nœud dédié aux runners, où ne tourne rien de la plateforme, peut ramener ce plancher à zéro via EQS_RUNNER_MIN_PLATFORM_RESERVE_CPU / EQS_RUNNER_MIN_PLATFORM_RESERVE_MEMORY_GI.
EQS_RUNNER_* ne fait qu'amorcer une installation qui n'a jamais enregistré ici. Le changement s'applique en un cycle de budget (30 s), sans redémarrage. Videz un champ pour rendre cette décision à la plateforme, et la ligne sous le libellé dit toujours d'où vient la valeur.Une mémoire qui grandit avec le job
Un job recevait une part de mémoire décidée à la création de son pod et figée pour toute sa vie. Ce nombre est une supposition sur une courbe : une build est petite pendant l'installation, grosse pendant qu'elle vérifie les types de tout à la fois, et petite à nouveau pendant qu'elle empaquette. Visez haut et le nœud est gaspillé ; visez bas et une build de deux heures meurt à 95%.
Avec la mémoire élastique activée (elle l'est par défaut), la plateforme surveille chaque job en cours et relève sa mémoire à chaud quand il approche de son plafond et que le nœud a de la place. La requête et la limite montent ensemble, donc le pod garde sa classe de QoS et l'ordonnanceur sait toujours la vérité, et le budget voit la nouvelle taille, donc le job suivant n'est pas admis dans la mémoire que celui-ci vient de prendre.
Il ne grandit que dans la place que la même arithmétique d'admission voit : jamais dans la réserve de la plateforme, jamais dans la part d'un autre job. Le plafond de croissance borne un job sur un gros nœud. Les deux sont dans Paramètres → Plateforme → Capacité du CI.
exit 137 : une allocation unique plus grande que la place restante tue toujours le conteneur entre deux lectures, et un nœud sans rien de libre n'a rien à donner. Il faut Kubernetes 1.33 ou plus récent pour le redimensionnement à chaud — un cluster plus ancien garde la part fixe de toujours.Un disque par job
Un job a un seul disque, comme sur un runner GitHub : son workspace, les images et le cache de build Docker, et tout ce qu'il écrit d'autre partagent le même espace. C'est au moins 14 Go, ce que GitHub documente pour son runner, et généralement plus : la plateforme mesure le disque libre de chaque nœud, garde le plancher d'espace libre que défend le stockage de la CI (Paramètres → Plateforme → Stockage de la CI, 15 % par défaut) et répartit le reste entre les jobs qui tournent. Quand le disque est ce qui s'épuise en premier, c'est lui qui décide combien de jobs tournent, et le panneau à côté des champs l'indique.
Un job qui écrit au-delà de son disque est évincé par le nœud, et son log dit quelle limite il a dépassée et où elle se règle. Paramètres → Plateforme → Capacité du CI fixe le plancher auquel un job est compté, ou le disque de chaque job.
Des exécutions qui ne finissent jamais
Le plafond s'applique aussi de l'extérieur. Quand le cluster n'a jamais de place — le plus souvent une taille de job épinglée au-delà de ce qu'un nœud peut offrir — les exécutions derrière elle attendraient des jours dans la file, et un job dont l'exécuteur a disparu resterait en cours pour toujours.
La plateforme abandonne donc d'elle-même. Une exécution qui attend un runner au-delà du plafond en file (24 h par défaut), et une exécution en cours au-delà du plafond d'exécution (12 h), se terminent en expiration ; de même pour un job isolé au-delà du plafond par job (6 h), une fois que ce qui l'exécutait a cessé de compter. Le timeout-minutes du job lui-même l'emporte toujours sur ce dernier. Les trois se règlent dans Paramètres → Plateforme → Capacité du CI, et 0 en désactive un.
Et quand la file n'avance pas parce que rien ne peut démarrer, l'écran des exécutions le dit, avec la taille qu'il faudrait à un job.
Éteindre une machine de runner
Un runner Windows ou macOS est une VM que cette installation exécute, et tant qu'on ne lui demande rien ce sont 8 Gio qui ne font rien. Sur l'installation pour laquelle ceci a été écrit, les deux ont retenu 14,2 Gio et environ 2,4 cœurs pendant seize heures sans un seul job.
Paramètres → Plateforme → Machines de runner dispose maintenant d'un interrupteur pour chaque machine que la plateforme exécute elle-même. L'éteindre demande d'abord l'arrêt au système invité et ne stoppe la VM qu'ensuite, ce qui est plus propre et plus sûr que tuer le processus, et la mémoire revient aussitôt au reste de l'installation.
Une machine que vous avez enregistrée par son adresse n'est pas concernée : la plateforme s'y connecte, elle n'éteint pas votre matériel.
Une machine qui s'éteint toute seule
Chaque machine que la plateforme exécute a le réglage Éteindre après … min d'inactivité, à côté de son interrupteur. 0 est la valeur par défaut et signifie jamais : une VM qui met des minutes à démarrer n'est pas ce que toute installation veut voir s'arrêter après un déjeuner calme.
Avec un plafond défini, la plateforme arrête la machine quand rien n'y tourne pendant ce temps, et la redémarre d'elle-même quand un job demande ce système d'exploitation. Le job attend dans son propre journal pendant le démarrage, au lieu d'échouer sur une connexion vers quelque chose qui ne tourne pas.
Logs et rétention
Un même step peut stocker jusqu'à 50 000 lignes de log (EQS_RUNNER_MAX_LOG_LINES_PER_STEP ; 0 supprime le plafond). Au-delà du plafond, le step continue de tourner jusqu'à sa conclusion réelle — un marqueur de troncature bien visible est écrit et le reste de la sortie est ignoré, ce qui protège la base de données et le stream en direct d'un set -x qui s'emballe.
Les logs de step sont purgés au bout de 90 jours, réglés dans l'écran Stockage de la CI ci-dessous (0 les garde pour toujours). Les exécutions, les jobs, les conclusions et les annotations sont conservés — l'historique reste consultable, seule la transcription brute expire. Le garbage collector de blobs du registre et l'exécuteur de rétention sont eux aussi activés par défaut (chacun se désactive par son EQS_REGISTRY_*_ENABLED=false) : les blobs sans référence sont récupérés d'eux-mêmes, et une politique de rétention enregistrée dans l'écran Artefacts s'exécute tout simplement.
Stockage de la CI
Le cache d'Actions et les artefacts des exécutions vivent sur le stockage de la plateforme, et sur une installation à un seul serveur ce stockage est le disque même du serveur. Paramètres → Plateforme → Stockage de la CI les maintient dans une politique, appliquée toutes les heures :
- Cache : les règles de GitHub. Une entrée que personne n'a restaurée depuis plus de 7 jours est supprimée, et un dépôt qui dépasse 10 Go perd d'abord les entrées utilisées il y a le plus longtemps.
- Artefacts : conservés 90 jours au maximum (de 1 à 400). Le
retention-daysd'un workflow est respecté quand il demande moins, jamais plus. Baisser la valeur raccourcit aussi les artefacts déjà stockés. - Limite totale : le cache et les artefacts réunis peuvent occuper un cinquième du disque par défaut (ou un nombre de Go ;
0pour aucune). Au-delà, ce qui a servi il y a le plus longtemps part en premier, cache ou artefact, et les artefacts d'une exécution en cours ne partent jamais. Les règles d'ancienneté ne suffisent pas à tenir un disque : un dépôt qui envoie un gros paquet à chaque build garde tout sous les 90 jours et le remplit quand même. Avec un stockage S3, il n'y a pas de disque à mesurer : fixez donc la limite en Go. - Garder libre : 15 % du disque par défaut. Quand le disque passe sous cette marge, pour quelque raison que ce soit, la CI rend exactement ce qui manque, avant que Kubernetes ne commence à évincer des pods. Vérifié toutes les cinq minutes.
L'écran montre ce que la CI occupe face à la limite, qui occupe le plus et ce que les derniers balayages ont supprimé, échecs compris avec leur raison ; un nombre saisi est prévisualisé sur ce disque avant d'être enregistré. Balayer maintenant applique une limite qu'on vient de baisser sans attendre l'heure. Les variables EQS_CI_CACHE_IDLE_DAYS, EQS_CI_CACHE_REPO_LIMIT_GB, EQS_CI_ARTIFACT_RETENTION_DAYS, EQS_CI_LOG_RETENTION_DAYS, EQS_CI_STORAGE_LIMIT_GB, EQS_CI_DISK_FLOOR_PERCENT ne servent qu'à amorcer une installation qui n'a jamais enregistré cet écran.
La part de la plateforme elle-même
La plateforme dimensionne ses propres pods d'après l'hôte — base de données, api et web déclarent des resource requests dérivées à l'installation (et complétées après coup par les mises à jour), si bien que sous charge le noyau arbitre en faveur de la plateforme au lieu de mettre un job de CI et la base de données sur un pied d'égalité. Chaque composant se surcharge via des variables du style EQS_PG_CPU_REQUEST, quand vous connaissez votre machine mieux que la formule.