S3 et compatibles
Le backend s3 range les fichiers comme objets d’un bucket AWS S3 ou d’un
stockage compatible (MinIO, Garage, Scaleway…).
[[backends]]
name = "archives"
type = "s3"
bucket = "archives"
region = "eu-west-3"
prefix = "sftp/"
endpoint_url = "https://minio.interne.example:9000" # sans la cle : AWS
[backends.credentials]
type = "static"
access_key_id = "AKIAEXEMPLE"
secret_access_key = "changez-moi"
[[roles]]
name = "archivistes"
[[roles.mounts]]
backend = "archives"
home_dir = "/{username}"
acl = [{ path = "/", rights = ["read", "write", "list"], recursive = true }]
alice envoie /in/x.txt : l’objet est la cle sftp/alice/in/x.txt.
Les cles
Toutes les cles : Reference [[backends]] type = “s3”.
iam_role : variables AWS_*, profil, role de l’instance ou du pod. Cles
communes : Les backends.
Fichiers et repertoires
| Ce que voit le client | Sur le stockage |
|---|---|
| un fichier | une cle |
| un repertoire | un marqueur <cle>/, ou toute cle sous <cle>/ |
un mkdir | ecrit le marqueur |
| parents manquants d’un envoi | un marqueur par niveau, chacun juge par l’ACL comme un mkdir |
| un repertoire sans marqueur | taille 0, sans date |
Une cle et un repertoire du meme nom peuvent coexister, sauf avec
refuse_upload_over_directory = true.
| Operation | Requetes S3 |
|---|---|
| lecture SFTP | un HeadObject a l’ouverture, puis un GetObject avec Range par lecture |
| telechargement REST | un GetObject lu en flux |
| envoi de moins de 8 Mio | un PutObject avec If-None-Match: *, a la fin |
| envoi de 8 Mio ou plus | un upload multipart, une part de 8 Mio a la fois |
| renommage d’un fichier | CopyObject avec If-None-Match: *, puis DeleteObject de la source |
| listage | ListObjectsV2 avec le delimiteur /, page apres page |
| suppression d’un arbre | ListObjectsV2 par 1 000 cles, puis DeleteObjects par lot |
Un objet s’ecrit en entier : ni reprise (reput), ni ajout. Seul un
fichier se renomme.
Les droits du bucket
Sur le bucket et <prefix>/* :
| Action | Pour |
|---|---|
s3:ListBucket | lister, distinguer un repertoire, trouver les parents manquants, mkdir, renommer, supprimer un arbre |
s3:GetObject | telecharger, stat, et l’examen qui precede une suppression ou un renommage |
s3:PutObject | envoyer, mkdir, renommer, l’auto-test des ecritures conditionnelles |
s3:DeleteObject | supprimer, renommer, nettoyer la cle de l’auto-test |
s3:AbortMultipartUpload | annuler un upload multipart qui ne sera pas complete |
s3:ListBucketMultipartUploads | balayer les uploads multipart abandonnes |
s3:ListMultipartUploadParts | dater la derniere part d’un candidat au balayage |
Un backend en lecture seule n’a besoin que de s3:ListBucket et s3:GetObject.
Les uploads multipart
Un upload multipart jamais complete reste facture jusqu’a son annulation :
| Quand | Annulation |
|---|---|
| un envoi finit sans completer | aussitot, quelle qu’en soit la cause |
| arret propre | ceux encore en vol, 5 s au plus |
| un processus tue | le balayage sous <prefix>/ : au demarrage, toutes les grace_secs et a chaque envoi, quand la derniere part a plus de grace_secs sur l’horloge du service |
- Donnez un
prefixa chaque backend : le balayage ne travaille que sous lui. - Un upload lent envoie une part vide toutes les 15 s, qui le date pour les
autres instances ; celles-ci ont le meme
uploads.idle_timeout_secs. - Une regle de cycle de vie reste conseillee :
{"Rules": [{"ID": "abort-incomplete-multipart", "Status": "Enabled", "Filter": {"Prefix": ""},
"AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 2}}]}
Son delai, compte depuis l’initiation, depasse le plus long envoi. MinIO
expire de lui-meme les uploads incomplets (stale_uploads_expiry).
Les ecritures conditionnelles
replaced dans l’audit et le marqueur de reservation reposent sur
If-None-Match: * et If-Match de PutObject. Derriere un endpoint_url (et
sur AWS avec cross_instance_reservation), le serveur les mesure au
demarrage, sur la cle <prefix>/.craftfilegate-upload-precondition.<16 hex>
ensuite supprimee ; le verdict tient jusqu’au redemarrage. MinIO : honoured.
Les cles communes sur S3
| Cle | Sur S3 |
|---|---|
home_dir (montage) | un prefixe : la cle est <prefix>/<home_dir>/<chemin>, parties vides omises |
create_home (montage) | sans effet : un prefixe existe des qu’une cle est dessous |
refuse_upload_over_directory | true : un envoi sur un nom qui est aussi un repertoire est refuse ; cout : un listage d’une cle a l’ouverture de chaque envoi |
cross_instance_reservation | un objet marqueur <lock_prefix><nom>, pose avec If-None-Match: * |
lock_prefix | le nom de ces marqueurs |
stale_partials | le balayage des uploads multipart abandonnes |
case_insensitive | false par defaut : les cles sont sensibles a la casse |
hidden_stores | sans objet : un objet n’apparait qu’une fois complet |
Performances et limites
- Chaque envoi en cours retient un tampon de 8 Mio (Memoire) ; ses ecritures sont sequentielles.
- Un envoi hors de la racine paie un listage par niveau parent.
- Le client adresse le bucket dans le chemin de l’URL (path-style), AWS compris.
- 10 000 parts au plus par objet, soit environ 78 Gio a 8 Mio la part.
- Sur un bucket versionne, l’auto-test laisse deux versions vides et un marqueur de suppression par demarrage.
Ce que vous verrez
| Quand | Ligne |
|---|---|
| demarrage | INFO S3 backend initialized, champs bucket, prefix, endpoint |
| demarrage, auto-test | INFO S3 upload precondition self-test, champs backend, verdict = honoured, probe_key |
| balayage | INFO aborted an abandoned multipart upload: ..., champs bucket, key, upload_id, age_secs |
| arret | INFO uncompleted S3 multipart uploads aborted before the shutdown completes, champ aborted |