[infra] Installation de MinIO, buckets du médaillon et rétention #28

Closed
opened 2026-09-01 10:35:24 +00:00 by lenaic · 9 comments
Owner

Exigence couverte

ENF-07, ENF-14

Épreuve servie

EC05 · Data, ETL et BI

Charge estimée

1 j.h

Ce qu'on veut obtenir

Installer MinIO sur le serveur et le configurer pour porter les trois zones du médaillon et les artefacts MLflow, sans qu'il soit joignable depuis le réseau de la salle.

Comment : en conteneur Docker, comme la pile de la forge. PostgreSQL reste en paquet système puisqu'il y est déjà, mais tout nouveau composant passe par Docker, sinon le playbook Ansible du #41 doit gérer deux façons de faire et on se retrouve avec deux manuels d'exploitation.

Critères d'acceptation

  • MinIO est installé en conteneur et redémarre automatiquement au démarrage de la machine.
  • Le service répond sur 127.0.0.1:9000, la console sur 127.0.0.1:9001, et rien ne répond depuis un poste tiers.
  • Les buckets bronze, argent, or et mlflow existent, avec un nommage d'objet documenté.
  • Une politique de rétention est posée sur bronze et argent, et écrite dans la documentation.
  • Les identifiants sont générés, jamais choisis, et stockés hors du dépôt, illisibles pour qui n'est ni root ni le groupe de déploiement (0600 root:root ou 0640 root:deploy)

Comment on le vérifie

Commande mc ls local/ depuis le serveur, puis curl depuis un autre poste
Attendu les quatre buckets listés en local, connexion refusée depuis l'extérieur
Preuve les deux sorties collées à la fermeture

Manuel d'exploitation à mettre à jour

docs/runbooks/minio.md, création et sauvegarde des buckets

Risque et retour arrière

Un bucket exposé par erreur rendrait la mesure brute lisible par les quatre autres groupes. Retour arrière : arrêt du service, la zone or en base reste servie.

### Exigence couverte ENF-07, ENF-14 ### Épreuve servie EC05 · Data, ETL et BI ### Charge estimée 1 j.h ### Ce qu'on veut obtenir Installer MinIO sur le serveur et le configurer pour porter les trois zones du médaillon et les artefacts MLflow, sans qu'il soit joignable depuis le réseau de la salle. **Comment** : en conteneur Docker, comme la pile de la forge. PostgreSQL reste en paquet système puisqu'il y est déjà, mais tout nouveau composant passe par Docker, sinon le playbook Ansible du #41 doit gérer deux façons de faire et on se retrouve avec deux manuels d'exploitation. ### Critères d'acceptation - [x] MinIO est installé en conteneur et redémarre automatiquement au démarrage de la machine. - [x] Le service répond sur 127.0.0.1:9000, la console sur 127.0.0.1:9001, et rien ne répond depuis un poste tiers. - [x] Les buckets bronze, argent, or et mlflow existent, avec un nommage d'objet documenté. - [x] Une politique de rétention est posée sur bronze et argent, et écrite dans la documentation. - [x] Les identifiants sont générés, jamais choisis, et stockés hors du dépôt, illisibles pour qui n'est ni root ni le groupe de déploiement (0600 root:root ou 0640 root:deploy) ### Comment on le vérifie Commande mc ls local/ depuis le serveur, puis curl depuis un autre poste Attendu les quatre buckets listés en local, connexion refusée depuis l'extérieur Preuve les deux sorties collées à la fermeture ### Manuel d'exploitation à mettre à jour docs/runbooks/minio.md, création et sauvegarde des buckets ### Risque et retour arrière Un bucket exposé par erreur rendrait la mesure brute lisible par les quatre autres groupes. Retour arrière : arrêt du service, la zone or en base reste servie.
gabriel added this to the EnerVision project 2026-09-01 11:27:05 +00:00
lenaic changed title from [infra] MinIO, médaillon et politique de rétention to [infra] Installation de MinIO, buckets du médaillon et rétention 2026-09-01 11:50:00 +00:00
Author
Owner

Ticket précisé : le titre dit maintenant qu'il s'agit d'une installation, un critère a été ajouté pour le redémarrage automatique de la machine, et le moyen est tranché — conteneur Docker, comme la pile de la forge, pour que le playbook Ansible du #41 n'ait qu'une seule façon de faire à rejouer.

Le libellé Kind/Data a été retiré : MinIO est du stockage objet, donc de l'infrastructure.

Justine porte ce ticket. MinIO est le socle du médaillon, donc du data lake, et il conditionne son #33 pour la zone bronze. C'est son travail et sa preuve : elle installe, elle documente la rétention, elle écrit le manuel et elle colle la preuve à la fermeture.

Pas besoin d'ouvrir un second ticket pour le même travail, les commentaires ici valent trace.

Ticket précisé : le titre dit maintenant qu'il s'agit d'une installation, un critère a été ajouté pour le redémarrage automatique de la machine, et le moyen est tranché — conteneur Docker, comme la pile de la forge, pour que le playbook Ansible du #41 n'ait qu'une seule façon de faire à rejouer. Le libellé `Kind/Data` a été retiré : MinIO est du stockage objet, donc de l'infrastructure. Justine porte ce ticket. MinIO est le socle du médaillon, donc du data lake, et il conditionne son #33 pour la zone bronze. C'est son travail et sa preuve : elle installe, elle documente la rétention, elle écrit le manuel et elle colle la preuve à la fermeture. Pas besoin d'ouvrir un second ticket pour le même travail, les commentaires ici valent trace.
gabriel removed their assignment 2026-09-01 11:59:14 +00:00
lenaic added
EC05
and removed
EC04
labels 2026-09-01 12:31:37 +00:00
justine added the due date 2026-09-01 2026-09-01 13:02:08 +00:00
justine added reference justine/28-installation-MiniO 2026-09-01 14:27:44 +00:00
Member

Un utilisateur MinIO dédié va apparaître dans le service, pour le registre MLflow (#30)

Justine, comme MinIO est ton service : le registre MLflow ne consommera pas
les identifiants racine
, il crée son propre utilisateur. Je l'ai posé hors de
ton périmètre — aucun de tes scripts n'est modifié, aucun bucket n'est créé,
aucune rétention n'est touchée.

Ce qui est ajouté, par infra/compose/mlflow/genere-identifiants.sh :

  • un utilisateur mlflow-<8 hexa>, tiré au sort ;
  • une politique mlflow-artefacts, attachée à cet utilisateur.

Ce que la politique autorise : lire, écrire et supprimer dans le bucket
mlflow, plus le téléversement en plusieurs parties — un artefact de modèle
dépasse vite le seuil où boto3 découpe l'envoi. bronze, silver et gold
sont refusés, et le script éprouve ce refus avant d'écrire quoi que ce
soit : s'il arrive à lister une des trois zones, il s'arrête et n'écrit pas le
fichier de secrets. Le test d'intégration rejoue ce contrôle
(tests/integration/test_registre_mlflow.py).

Où vivent les identifiants : /etc/enervision/mlflow.env, en 0600 root,
jamais dans le dépôt. Tes identifiants racine restent dans
/etc/enervision/minio.env et ne sont lus que le temps de créer l'utilisateur
— par la variable MC_HOST_, et non par mc alias set, pour ne pas laisser
une seconde copie du secret racine dans ~/.mc/config.json. C'est la remarque
de ton manuel, « le compte d'administration mériterait à terme un utilisateur
MinIO dédié », appliquée au premier consommateur du bucket mlflow.

Rotation et retrait de cet utilisateur : docs/runbooks/mlflow.md, section 6.

Si tu préfères que ce geste vive dans init-buckets.sh plutôt que dans la pile
MLflow, dis-le et je déplace — je l'ai mis chez moi pour ne pas empiéter, pas
par principe.

Rien à faire de ton côté sur ce ticket : c'est une information, pas une demande.

### Un utilisateur MinIO dédié va apparaître dans le service, pour le registre MLflow (#30) Justine, comme MinIO est ton service : le registre MLflow ne consommera **pas les identifiants racine**, il crée son propre utilisateur. Je l'ai posé hors de ton périmètre — aucun de tes scripts n'est modifié, aucun bucket n'est créé, aucune rétention n'est touchée. **Ce qui est ajouté**, par `infra/compose/mlflow/genere-identifiants.sh` : - un utilisateur `mlflow-<8 hexa>`, tiré au sort ; - une politique `mlflow-artefacts`, attachée à cet utilisateur. **Ce que la politique autorise** : lire, écrire et supprimer dans le bucket `mlflow`, plus le téléversement en plusieurs parties — un artefact de modèle dépasse vite le seuil où boto3 découpe l'envoi. `bronze`, `silver` et `gold` sont **refusés**, et le script *éprouve* ce refus avant d'écrire quoi que ce soit : s'il arrive à lister une des trois zones, il s'arrête et n'écrit pas le fichier de secrets. Le test d'intégration rejoue ce contrôle (`tests/integration/test_registre_mlflow.py`). **Où vivent les identifiants** : `/etc/enervision/mlflow.env`, en `0600 root`, jamais dans le dépôt. Tes identifiants racine restent dans `/etc/enervision/minio.env` et ne sont lus que le temps de créer l'utilisateur — par la variable `MC_HOST_`, et non par `mc alias set`, pour ne pas laisser une seconde copie du secret racine dans `~/.mc/config.json`. C'est la remarque de ton manuel, « le compte d'administration mériterait à terme un utilisateur MinIO dédié », appliquée au premier consommateur du bucket `mlflow`. Rotation et retrait de cet utilisateur : `docs/runbooks/mlflow.md`, section 6. Si tu préfères que ce geste vive dans `init-buckets.sh` plutôt que dans la pile MLflow, dis-le et je déplace — je l'ai mis chez moi pour ne pas empiéter, pas par principe. Rien à faire de ton côté sur ce ticket : c'est une information, pas une demande.
Member

Ton déploiement débloque les deux derniers critères du #30

Justine, constat fait sur ml-stagiaire-02 aujourd'hui : MinIO est fusionné
dans develop mais n'est pas déployé sur le serveur.

$ sudo docker ps -a --format '{{.Names}}'   -> pas de conteneur MinIO
$ sudo ss -ltnp | grep -E ':(9000|9001)'    -> (aucun)
$ sudo ls /etc/enervision                   -> le répertoire n'existait pas
$ command -v mc                             -> mc absent

Le registre MLflow du #30 est installé et tourne, mais il ne peut pas écrire
d'artefact : il n'y a ni bucket ni identifiants. Le serveur journalise
NoCredentialsError, ce qui est le comportement correct.

Ce qu'il me faut, et rien de plus — ce sont tes propres critères
d'acceptation, il n'y a rien à ajouter pour moi :

  1. les conteneurs démarrés depuis infra/compose/docker-compose.yml ;
  2. le bucket mlflow créé (ton init-buckets.sh le fait déjà) ;
  3. /etc/enervision/minio.env produit par ton genere-identifiants.sh ;
  4. le client mc posé sur le serveur, comme le décrit ton manuel.

Ensuite je joue mon genere-identifiants.sh, qui crée l'utilisateur MinIO
dédié — voir mon commentaire plus haut — et le #30 se ferme.

Deux choses à savoir avant de déployer, tirées de l'installation du jour :

  • /etc/enervision/ existe maintenant, en 0700 root : je l'ai créé pour
    le fichier de secrets du registre. Ton genere-identifiants.sh fait
    install -d dessus, donc il est idempotent et ne cassera pas.
  • Ta composition publie MinIO en réseau bridge (127.0.0.1:9000:9000). Le
    journal du 31 août dit « aucun conteneur ne démarre en réseau bridge sur ce
    LXC », et c'est pour ça que la pile PostgreSQL et la mienne sont en réseau
    hôte. Je ne sais pas si ça vaut encore — Docker est en 29.1.3 sur la machine
    — mais c'est à éprouver au démarrage plutôt qu'à découvrir après. Si le
    bridge ne porte pas, network_mode: host avec l'écoute bornée par la
    configuration MinIO donne le même résultat côté ENF-14. Dans les deux cas la
    vérification qui compte est celle de ton manuel : curl depuis un autre
    poste.

Je ne touche pas à ta pile. Dis-moi quand c'est en service et je finis le #30
dans la demi-heure.

### Ton déploiement débloque les deux derniers critères du #30 Justine, constat fait sur `ml-stagiaire-02` aujourd'hui : **MinIO est fusionné dans `develop` mais n'est pas déployé sur le serveur.** ``` $ sudo docker ps -a --format '{{.Names}}' -> pas de conteneur MinIO $ sudo ss -ltnp | grep -E ':(9000|9001)' -> (aucun) $ sudo ls /etc/enervision -> le répertoire n'existait pas $ command -v mc -> mc absent ``` Le registre MLflow du #30 est installé et tourne, mais il ne peut pas écrire d'artefact : il n'y a ni bucket ni identifiants. Le serveur journalise `NoCredentialsError`, ce qui est le comportement correct. **Ce qu'il me faut, et rien de plus** — ce sont tes propres critères d'acceptation, il n'y a rien à ajouter pour moi : 1. les conteneurs démarrés depuis `infra/compose/docker-compose.yml` ; 2. le bucket `mlflow` créé (ton `init-buckets.sh` le fait déjà) ; 3. `/etc/enervision/minio.env` produit par ton `genere-identifiants.sh` ; 4. le client `mc` posé sur le serveur, comme le décrit ton manuel. Ensuite je joue mon `genere-identifiants.sh`, qui crée l'utilisateur MinIO dédié — voir mon commentaire plus haut — et le #30 se ferme. **Deux choses à savoir avant de déployer**, tirées de l'installation du jour : - `/etc/enervision/` **existe maintenant**, en `0700 root` : je l'ai créé pour le fichier de secrets du registre. Ton `genere-identifiants.sh` fait `install -d` dessus, donc il est idempotent et ne cassera pas. - Ta composition publie MinIO en **réseau bridge** (`127.0.0.1:9000:9000`). Le journal du 31 août dit « aucun conteneur ne démarre en réseau bridge sur ce LXC », et c'est pour ça que la pile PostgreSQL et la mienne sont en réseau hôte. Je ne sais pas si ça vaut encore — Docker est en 29.1.3 sur la machine — mais **c'est à éprouver au démarrage** plutôt qu'à découvrir après. Si le bridge ne porte pas, `network_mode: host` avec l'écoute bornée par la configuration MinIO donne le même résultat côté ENF-14. Dans les deux cas la vérification qui compte est celle de ton manuel : `curl` depuis un autre poste. Je ne touche pas à ta pile. Dis-moi quand c'est en service et je finis le #30 dans la demi-heure.
justine added spent time 2026-09-02 13:45:33 +00:00
8 hours
Member

image

![image](/attachments/68c3bcb9-4b20-4e95-ab29-7f8610844485)
6.6 KiB
Member

image

![image](/attachments/346f56fb-1078-4f2f-b383-7cdd6dc1d19d)
102 KiB
Member

Merci — le #30 est bouclé. Deux relevés pour toi

MinIO en service, j'ai enchaîné dans la demi-heure : utilisateur MinIO dédié
mlflow-7ffe27e5 créé avec la politique mlflow-artefacts, artefacts écrits et
relus dans le bucket mlflow, test d'intégration du registre à 14 / 14. Preuves
sur le #30.

Deux choses relevées au passage, sur ton périmètre :

1. /etc/enervision/minio.env est en 640 root:deploy.

$ sudo stat -c '%a %U:%G %n' /etc/enervision/minio.env
640 root:deploy /etc/enervision/minio.env

Ton critère d'acceptation dit « droits 600 hors du dépôt », et ton propre test
l'affirme :

assert resultat.stdout.strip() == "600 root"

Donc test_les_identifiants_sont_hors_du_depot_en_600 doit être rouge chez toi.
Deux lectures possibles et je ne veux pas trancher à ta place : soit c'est
volontaire pour le compte deploy du #41, et c'est le critère et le test qu'il
faut corriger — en disant pourquoi le groupe deploy a le droit de lire ; soit
c'est un accident, et c'est le fichier. Je n'y ai pas touché.

2. J'ai installé le client mc en /usr/local/bin/mc
(RELEASE.2025-08-13T08-35-41Z), par la commande de ton manuel — il n'était pas
là et mon générateur en dépend. Ton alias local existait déjà pour root, je
n'ai rien changé à ~/.mc.

Et une bonne nouvelle qui contredit le journal du 31 août : ton réseau
bridge fonctionne sur ce LXC. MinIO écoute bien sur 127.0.0.1:9000 et
9001 via docker-proxy, et depuis mon poste les deux ports sont refusés,
comme 5000 et 5433. Docker est en 29.1.3 sur la machine — le constat du 31 août
ne vaut plus, ce qui mériterait une ligne au journal parce que trois piles ont
été écrites en réseau hôte pour cette raison.

$ nc -z 10.105.200.41 9000  -> refusé
$ nc -z 10.105.200.41 9001  -> refusé
$ nc -z 10.105.200.41 22    -> ouvert   (contre-épreuve)
### Merci — le #30 est bouclé. Deux relevés pour toi MinIO en service, j'ai enchaîné dans la demi-heure : utilisateur MinIO dédié `mlflow-7ffe27e5` créé avec la politique `mlflow-artefacts`, artefacts écrits et relus dans le bucket `mlflow`, test d'intégration du registre à 14 / 14. Preuves sur le [#30](../30). Deux choses relevées au passage, sur ton périmètre : **1. `/etc/enervision/minio.env` est en `640 root:deploy`.** ``` $ sudo stat -c '%a %U:%G %n' /etc/enervision/minio.env 640 root:deploy /etc/enervision/minio.env ``` Ton critère d'acceptation dit « droits 600 hors du dépôt », et ton propre test l'affirme : ```python assert resultat.stdout.strip() == "600 root" ``` Donc `test_les_identifiants_sont_hors_du_depot_en_600` doit être rouge chez toi. Deux lectures possibles et je ne veux pas trancher à ta place : soit c'est volontaire pour le compte `deploy` du #41, et c'est le critère et le test qu'il faut corriger — en disant pourquoi le groupe `deploy` a le droit de lire ; soit c'est un accident, et c'est le fichier. Je n'y ai pas touché. **2. J'ai installé le client `mc`** en `/usr/local/bin/mc` (`RELEASE.2025-08-13T08-35-41Z`), par la commande de ton manuel — il n'était pas là et mon générateur en dépend. Ton alias `local` existait déjà pour root, je n'ai rien changé à `~/.mc`. **Et une bonne nouvelle qui contredit le journal du 31 août** : ton réseau bridge **fonctionne** sur ce LXC. MinIO écoute bien sur `127.0.0.1:9000` et `9001` via `docker-proxy`, et depuis mon poste les deux ports sont refusés, comme 5000 et 5433. Docker est en 29.1.3 sur la machine — le constat du 31 août ne vaut plus, ce qui mériterait une ligne au journal parce que trois piles ont été écrites en réseau hôte pour cette raison. ``` $ nc -z 10.105.200.41 9000 -> refusé $ nc -z 10.105.200.41 9001 -> refusé $ nc -z 10.105.200.41 22 -> ouvert (contre-épreuve) ```
Member

image
depuis un poste tiers pas d'accès

![image](/attachments/741df220-3194-467c-990b-0917b9b06c4b) depuis un poste tiers pas d'accès
Member

Le critère "Les identifiants sont générés, jamais choisis, et stockés en droits 600 hors du dépôt." devrait être modifié.
Actuellement les identifiants sont générés, jamais choisis, et stockés hors du dépôt dans un fichier appartenant à root, sans aucun accès pour les autres utilisateurs et en lecture seule pour les groupes de déploiement : 0600 root:root (en installation manuelle) et 0640 root:deploy (après Ansible).
Le 600 du critère initial fige la façon dont le composant est installé à la main, pas la propriété de sécurité. Le compte deploy doit lire le fichier puisque env_file est lu par le client Compose (infra/ansible/roles/app/tasks/main.yml:86).
Vous validez @lenaic @olivier ?

Le critère "**Les identifiants sont générés, jamais choisis, et stockés en droits 600 hors du dépôt**." devrait être modifié. Actuellement les identifiants sont générés, jamais choisis, et stockés hors du dépôt dans un fichier appartenant à root, sans aucun accès pour les autres utilisateurs et en lecture seule pour les groupes de déploiement : 0600 root:root (en installation manuelle) et 0640 root:deploy (après Ansible). Le 600 du critère initial fige la façon dont le composant est installé à la main, pas la propriété de sécurité. Le compte deploy doit lire le fichier puisque _env_file_ est lu par le client Compose (infra/ansible/roles/app/tasks/main.yml:86). Vous validez @lenaic @olivier ?
justine changed reference from justine/28-installation-MiniO to justine/28-droits-minio-env 2026-09-03 07:51:40 +00:00
justine changed reference from justine/28-droits-minio-env to justine/28-installation-MiniO 2026-09-03 07:51:52 +00:00
justine added spent time 2026-09-03 07:52:04 +00:00
10 hours
Member

Ok donc changement du critère en "Les identifiants sont générés, jamais choisis, et stockés hors du dépôt, illisibles pour qui n'est ni root ni le groupe de déploiement (0600 root:root ou 0640 root:deploy)."
Les modifications ont été ajoutées dans la branche justine/28-droits-minio-env

Ok donc changement du critère en "Les identifiants sont générés, jamais choisis, et stockés hors du dépôt, illisibles pour qui n'est ni root ni le groupe de déploiement (0600 root:root ou 0640 root:deploy)." Les modifications ont été ajoutées dans la branche justine/28-droits-minio-env
gabriel modified the due date from 2026-09-01 to 2026-09-04 2026-09-03 09:35:49 +00:00
gabriel removed the due date 2026-09-04 2026-09-03 09:40:35 +00:00
Sign in to join this conversation.
No project
No assignees
3 participants
Notifications
Total time spent: 18 hours
justine
18 hours
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
g2/enervision#28
No description provided.