Files
ENI-projet-piscine/docs/adr/0009-deux-environnements-compose-sur-la-vm-eni.md
Johan LEROY 9ee0de9d55 docs: réaligne la documentation sur l'état livré au gel
Trois environnements et un frontal SNI au lieu de deux, certificats Let's
Encrypt par DNS-01, sept DAGs, index des ADR complété jusqu'à 0020. Les
exemples de l'ETL passent en bash et n'utilisent plus l'option --limit,
retirée. L'adresse de la machine est masquée dans l'arbre, les ADR 0009 et
0014 portent une note datée sur l'approbation de la production.
2026-09-24 15:55:08 +02:00

5.3 KiB

0009 - Deux environnements sur la VM ENI, un projet Compose chacun, déployés par un runner auto-hébergé

  • Statut : accepté
  • Date : 2026-09-21
  • Complété par : ADR 0017, troisième environnement dev
  • Note du 24/09 : l'approbation annoncée avant la production n'a jamais été activée. L'environnement GitHub prod n'accepte que main, sans relecteur requis.

Contexte

La grille note EC03 à EC06 sur ce qui est déployé et fonctionnel au J10. Au 21/09, rien ne l'est : la CI s'arrête au merge (issue #21), la topologie Compose avec reverse proxy (ADR 0007) n'a jamais quitté le poste, et le module Terraform k3s n'a jamais été appliqué. L'école met à disposition une seule VM, eadl-2025-nantes-g3, sur une adresse privée que les runners hébergés par GitHub ne joignent pas, sans DNS public.

Il faut deux environnements, recette et production, parce que la stratégie de branches en a déjà deux, dev et main, et qu'un déploiement direct en production à chaque merge sur dev n'est pas défendable.

La branche feat/deploy tentait de déployer par provisioners Terraform : nginx système et copie du build Angular. La revue postée sur #21 relève huit points bloquants, dont des racines rec et prod qui ne passent pas terraform validate.

Décision

Un projet Docker Compose par environnement, sur la même machine. Deux clones du dépôt, /srv/enervision/rec sur dev et /srv/enervision/prod sur main, chacun avec son .env et son COMPOSE_PROJECT_NAME. Le nom de projet préfixe volumes, réseau et conteneurs : les deux stacks ne partagent rien.

Les ports du proxy et l'origine publique deviennent des variables de docker-compose.prod.yml. La production garde 80 et 443. La recette publie 8443 et ramène sa redirection HTTP sur la boucle locale, faute de quoi elle renverrait vers la production. Base, Mailpit et Airflow restent sur 127.0.0.1, décalés d'un port.

Deux noms d'hôte, enervision.local et rec.enervision.local, sur la même IP. Le cookie de rafraîchissement est posé par hôte, pas par port : un seul nom ferait se déconnecter la production à chaque connexion en recette.

Un runner GitHub Actions auto-hébergé sur la VM exécute deploy.yml : un push sur dev déploie la recette, un push sur main déploie la production après approbation dans l'environnement GitHub prod. Le job aligne le clone sur la branche puis lance make stack-up. Les images sont construites sur la machine.

Les secrets vivent dans le .env de chaque dossier, générés sur la machine par scripts/provision-host.sh, jamais dans git ni dans GitHub. Le runner n'a besoin d'aucun secret.

Alternatives écartées

  • k3s avec un namespace par environnement : le cluster serait vide, sans manifeste, sans registre, sans stockage persistant. C'est la cible de 10-infra.md, pas celle de la semaine.
  • Provisioners Terraform de feat/deploy : voir la revue sur #21. Terraform reste l'outil de provisionnement de la machine, pas de livraison applicative.
  • Deux machines, VM Proxmox et VM Azure ENI : une deuxième infrastructure à justifier devant le jury et à provisionner, pour un bénéfice nul sur la grille.
  • Un seul proxy frontal routant par nom d'hôte vers les deux stacks : des URL sans port, mais le proxy devrait joindre deux réseaux Compose où les services portent les mêmes noms. La complexité dépasse le gain.
  • Images publiées sur GHCR et déployées par digest : la bonne pratique, remise à plus tard. Un registre à authentifier sur la machine, alors que le runner y construit déjà.

Conséquences

  • Deux TimescaleDB sur une machine de 8 Go : sans réglage, chacune se réserverait 25 % de la RAM au premier démarrage. L'overlay fixe TS_TUNE_MEMORY à 2 Go et TS_TUNE_NUM_CPUS à 2 par base. Airflow 3 n'a rien à régler de ce côté : son api-server lance un seul worker par défaut, là où le webserver d'Airflow 2 en lançait quatre. La montée à 32 Go prévue par les consignes est à demander.
  • Un runner auto-hébergé sur un dépôt public exécute le code qu'on lui envoie. deploy.yml ne se déclenche jamais sur pull_request, le runner tourne sous un utilisateur dédié, et le dépôt doit exiger une approbation pour les workflows des PR externes.
  • Les deux environnements construisent leurs images séparément à partir du même commit : ce qui tourne en production a été construit deux fois, pas promu. Le passage à GHCR lèvera cette limite.
  • Le make stack-up du runner reconstruit l'image Airflow, qui copie ml/ et apps/backend/, à chaque push : plusieurs minutes par déploiement, acceptable pour la cadence du projet.
  • environments/prod de Terraform reste vide. Le provisionnement de la machine est porté par scripts/provision-host.sh, que Terraform pourra appeler par remote-exec le jour où une racine visant la VM existera. Cette racine existe depuis l'ADR 0010, sous le nom environments/vm-eni, et environments/prod a disparu avec elle.
  • L'image frontend quitte dhi.io/nginx, registre authentifié dont personne n'a l'accès, pour nginx:1.28-alpine, la même image que le proxy. Elle n'avait jamais été construite.