Helm Charts / Detect changed charts (push) Successful in 1m2s
Helm Charts / Library charts tool (push) Skipped
Helm Charts / Application charts chart (push) Skipped
Helm Charts / Application charts crowdsec (push) Skipped
Helm Charts / Application charts grafana (push) Skipped
Helm Charts / Application charts hashicorp-vault (push) Skipped
Helm Charts / Application charts pgbouncer (push) Skipped
Helm Charts / Application charts pgcat (push) Skipped
Helm Charts / Application charts prometheus (push) Skipped
Helm Charts / Application charts redis (push) Skipped
Helm Charts / Application charts minio (push) Successful in 11s
105 lines
4.5 KiB
Markdown
105 lines
4.5 KiB
Markdown
# `minio_app` — déclarer ses buckets depuis SON dépôt
|
|
|
|
Chacun son périmètre : les buckets d'une application appartiennent au dépôt de
|
|
cette application. Ce module **standardise** la déclaration, il ne la détient
|
|
pas — sans lui, chaque bucket de chaque app deviendrait une PR sur `tools`.
|
|
|
|
## Usage
|
|
|
|
Dans l'`iac/` de l'app :
|
|
|
|
```hcl
|
|
# Le provisionneur MinIO : des droits d'administration MINIMAUX (créer un
|
|
# bucket, un compte de service, une politique), jamais le root — qui, lui, ne
|
|
# sort pas du pipeline `minio`.
|
|
data "vault_kv_secret_v2" "minio_provisioner" {
|
|
mount = "kvv2"
|
|
name = "minio/provisioner"
|
|
}
|
|
|
|
provider "minio" {
|
|
minio_server = "s3.arcodange.fr"
|
|
minio_user = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_ACCESS_KEY"]
|
|
minio_password = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_SECRET_KEY"]
|
|
minio_ssl = true
|
|
}
|
|
|
|
module "stockage" {
|
|
source = "git::ssh://[email protected]:2222/arcodange-org/tools.git//minio/iac/modules/minio_app?depth=1&ref=main"
|
|
app = "mon-app" # = le nom de son rôle Vault
|
|
buckets = ["mon-app-fichiers"]
|
|
providers = { minio = minio }
|
|
}
|
|
```
|
|
|
|
Puis, côté chart : une `VaultStaticSecret` sur `kvv2/minio/<app>` et l'injection
|
|
des variables dans le Deployment.
|
|
|
|
## Ce que le module garantit
|
|
|
|
- les buckets sont **privés** — l'accès passe par des URL présignées ;
|
|
- les **téléversements abandonnés** sont ramassés au bout d'un jour (voir plus
|
|
bas : c'est de l'hygiène de protocole, pas un choix de l'app) ;
|
|
- le compte de service ne peut **rien** toucher d'autre que ces buckets-là ;
|
|
- le compte de service peut **refermer et abandonner un téléversement en
|
|
parts** — `ListMultipartUploadParts` et `AbortMultipartUpload`, les deux
|
|
actions que `PutObject` ne couvre pas (sans elles, l'assemblage rend 403 et
|
|
aucun objet de plus d'une part n'arrive jamais — mesuré le 2026-09-07) ;
|
|
- ses clés vont dans `kvv2/minio/<app>`, que le module Vault central autorise
|
|
déjà l'app à lire (règle **inconditionnelle** : le chemin porte le nom de
|
|
l'app, donc il ne peut exposer que ses propres clés).
|
|
|
|
## Plusieurs buckets
|
|
|
|
C'est le cas courant : deux contenus aux **cycles de vie différents** méritent
|
|
deux buckets. Il suffit de les lister — le compte de service existant gagne
|
|
l'accès, **sans nouvelle clé**.
|
|
|
|
## Ce que le module ne fait PAS
|
|
|
|
Il ne pose ni quota, ni **expiration de contenu**, ni versioning : ces choix
|
|
appartiennent à l'app et varient d'un bucket à l'autre. « Ces vidéos se purgent
|
|
à 90 jours » est une décision de produit, elle se prend dans le dépôt du
|
|
produit.
|
|
|
|
### ⚠ L'exception, et la ligne qu'elle trace
|
|
|
|
Ce module pose **une seule** règle de cycle de vie :
|
|
`AbortIncompleteMultipartUpload` à 1 jour, sur chaque bucket qu'il crée.
|
|
|
|
Elle a l'air de contredire le paragraphe ci-dessus. Elle ne le contredit pas —
|
|
elle en précise la frontière, et c'est la question « à QUOI cette connaissance
|
|
appartient-elle ? » qui tranche :
|
|
|
|
- une **expiration de contenu** porte sur des objets que l'app a voulus, qu'elle
|
|
montre, et dont elle seule sait combien de temps ils valent. Elle varie d'une
|
|
app à l'autre : elle est chez l'app ;
|
|
- un **téléversement en plusieurs parts jamais refermé** n'est le contenu de
|
|
personne. Ce sont des morceaux qu'aucune API ne montre — ni `mc ls`, ni la
|
|
console — laissés par un navigateur qui a fermé l'onglet. **Aucune app ne veut
|
|
les garder**, et aucune ne peut les voir depuis son propre code. C'est un
|
|
déchet de PROTOCOLE, produit par le mécanisme même du bucket : il est chez
|
|
celui qui crée les buckets.
|
|
|
|
Le test pratique : si la réponse à « combien de temps ? » demande de connaître le
|
|
produit, c'est chez l'app. Ici, la réponse ne demande que de connaître S3 — passé
|
|
l'expiration des URL signées, un téléversement en cours ne peut plus rien
|
|
recevoir, il occupe seulement.
|
|
|
|
⚠ Le délai n'est **pas** paramétrable, et c'est voulu (YAGNI) : un seul cas
|
|
existe. Le jour où une app signe des parts pour plus de 24 h, ce sera le
|
|
déclencheur pour en faire une variable — pas avant.
|
|
|
|
### Plancher de version
|
|
|
|
⚠ Ce module exige **`aminueza/minio >= 3.10.0`** : `abort_incomplete_multipart_upload`
|
|
y est apparu (mesuré en interrogeant le schéma du provider version par version —
|
|
3.9.0 ne l'a pas). Un appelant resté plus bas se verra dire, dès `tofu init` :
|
|
|
|
```
|
|
no available releases match the given constraints 3.3.0, >= 3.10.0
|
|
```
|
|
|
|
… ce qui NOMME la version à atteindre, au lieu d'un « unsupported block type »
|
|
au plan, qui ne l'aurait pas dite.
|