- Check-in voordat we aan bugfix beginnen te werken.
- Introductie van static-files serving met standaard nginx (niet ons docker nginx image), en een rsync service om static files te synchroniseren. Nog niet volledig afgewerkt!
This commit is contained in:
202
documentation/evie_object_storage_governance.md
Normal file
202
documentation/evie_object_storage_governance.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Evie Object Storage Governance (Optie 3)
|
||||
|
||||
**Doel:** 1 bucket per omgeving (staging / prod), met **prefixen per
|
||||
tenant**. Duidelijke scheiding van datatypes (documents vs assets), lage
|
||||
beheerlast, goed schaalbaar.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 1) Structuur & naamgeving
|
||||
|
||||
### Buckets (per omgeving)
|
||||
|
||||
- **staging:** `evie-staging`
|
||||
- **prod:** `evie-prod`
|
||||
|
||||
> Buckets zijn S3-compatibel op Scaleway
|
||||
> (`https://s3.<regio>.scw.cloud`). Houd buckets "plat" (alle tenants
|
||||
> als prefix).
|
||||
|
||||
### Prefix layout (per tenant)
|
||||
|
||||
<bucket>/
|
||||
tenant-<tenantId>/
|
||||
documents/
|
||||
<subfolders naar keuze>...
|
||||
assets/
|
||||
<subfolders naar keuze>...
|
||||
|
||||
**Conventies** - **Tenant prefix:** `tenant-<tenantId>` (tenantId =
|
||||
interne stabiele sleutel; geen PII). - **Datatypes:** `documents/` en
|
||||
`assets/` (harde scheiding). - **Bestandsnamen:** `snake-case` of
|
||||
`kebab-case`; voeg optioneel datum/uuid toe bij uploads die kunnen
|
||||
conflicteren.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 2) Toegang & secrets
|
||||
|
||||
### IAM-model
|
||||
|
||||
- **Één IAM Application per omgeving**
|
||||
- `evie-staging-app` → keys in **staging** k8s Secret\
|
||||
- `evie-prod-app` → keys in **prod** k8s Secret\
|
||||
- Toegang **alleen** tot het eigen bucket (`evie-staging` of
|
||||
`evie-prod`).
|
||||
|
||||
### App-side secrets (env)
|
||||
|
||||
- `S3_ENDPOINT=https://s3.<regio>.scw.cloud`
|
||||
- `S3_BUCKET=evie-<env>`
|
||||
- `S3_ACCESS_KEY=***`
|
||||
- `S3_SECRET_KEY=***`
|
||||
- `S3_REGION=<regio>` (bv. `fr-par`)
|
||||
- (optioneel) `S3_FORCE_PATH_STYLE=false`
|
||||
|
||||
> **Presigned uploads**: genereer **server-side** presigned URL's per
|
||||
> tenant/prefix; geef nooit de master-keys aan de client.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 3) Policies (conceptueel)
|
||||
|
||||
- **Bucket policy**: sta alleen requests toe met geldige credentials
|
||||
van de Evie-app van die omgeving.
|
||||
- **Prefix scope** (in app-logica): alle reads/writes **moeten** met
|
||||
pad beginnen op `tenant-<tenantId>/...`.
|
||||
- **Optioneel** (later): extra policy-groepen voor specifieke
|
||||
workflows (vb. tijdelijke ingest job).
|
||||
|
||||
> **Belangrijk:** autorisatie op tenantniveau afdwingen in **je
|
||||
> applicatie** (context = `tenantId`). Nooit paden samenstellen vanuit
|
||||
> user input zonder whitelisting/validation.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 4) Lifecycle & retentie
|
||||
|
||||
**Doel:** kosten beheersen, assets sneller "kouder", documenten langer
|
||||
bewaren.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Scope (Filter) Regel
|
||||
----------------------------------- -----------------------------------
|
||||
`tenant-*/assets/` → One Zone-IA na 30 dagen
|
||||
|
||||
`tenant-*/assets/` → Glacier/Archive na 180 dagen
|
||||
(optioneel)
|
||||
|
||||
`tenant-*/documents/` → Standard (geen transition) of IA
|
||||
na 180d
|
||||
|
||||
`tenant-*/documents/` (tijdelijke Expire (delete) na 7--14 dagen
|
||||
previews)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
> Lifecycle definieer je **per bucket** met **prefix filters**, zodat
|
||||
> regels verschillend zijn voor `assets/` en `documents/`.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 5) CORS & distributie
|
||||
|
||||
- **CORS**: indien browser direct upload/download doet, whitelist de
|
||||
domeinen van je app (origin), en methodes `GET, PUT, POST`. Alleen
|
||||
benodigde headers toestaan.
|
||||
- **Publieke distributie** (indien nodig):
|
||||
- Kleine public-reads via presigned URL's (aanbevolen).\
|
||||
- Of activeer publieke read op een **specifieke** `public/`-prefix
|
||||
(niet op de hele bucket).\
|
||||
- Overweeg een CDN/edge-lag via Scaleway Edge Services voor
|
||||
veelgevraagde assets.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 6) Observability & beheer
|
||||
|
||||
- **Logging/metrics**:
|
||||
- App: log alle S3 calls met `tenantId` + object key.\
|
||||
- Platform: gebruik Scaleway Cockpit voor capacity & request
|
||||
metrics.
|
||||
- **Quota & limieten**:
|
||||
- 1 bucket per omgeving beperkt "bucket-sprawl".\
|
||||
- Objecten en totale grootte zijn praktisch onbeperkt; plan wel
|
||||
lifecycle om groei te managen.
|
||||
- **Monitoring**:
|
||||
- Alerts op snelgroeiende **assets**-prefixen, high error rates
|
||||
(4xx/5xx), en mislukte lifecycle-transities.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 7) Operationele workflows
|
||||
|
||||
### Tenant aanmaken
|
||||
|
||||
1. DB schema provisionen.
|
||||
2. (S3) **Geen nieuwe bucket**; enkel **prefix**:
|
||||
`tenant-<id>/documents/` en `tenant-<id>/assets/` zijn impliciet.
|
||||
3. (Optioneel) Init bestanden/placeholder objecten.
|
||||
4. App-config linkt de tenant aan zijn prefix (centrale mapping).
|
||||
|
||||
### Upload (app -\> S3)
|
||||
|
||||
1. App valideert `tenantId` en datatype (`documents|assets`).\
|
||||
2. App construeert **canonical path**: `tenant-<id>/<datatype>/<...>`\
|
||||
3. App genereert **presigned PUT** (tijdelijk) en geeft terug aan
|
||||
frontend.\
|
||||
4. Frontend uploadt rechtstreeks naar S3 met presigned URL.
|
||||
|
||||
### Download / Serve
|
||||
|
||||
- Interne downloads: app signed GET of server-side stream.\
|
||||
- Externe/public: **presigned GET** met korte TTL of via public-only
|
||||
prefix + CDN.
|
||||
|
||||
### Opruimen & lifecycle
|
||||
|
||||
- Tijdelijke artefacten: app scheduled cleanup (of lifecycle
|
||||
"Expiration").\
|
||||
- Archivering: lifecycle transitions per prefix.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 8) Beveiliging
|
||||
|
||||
- **Least privilege**: IAM-keys enkel voor het bucket van de
|
||||
omgeving.\
|
||||
- **Encryptie**: server-side encryption (default) volstaat vaak;
|
||||
overweeg KMS als apart key-beleid nodig is.\
|
||||
- **Auditing**: log alle **write**-operaties met gebruikers- en
|
||||
tenantcontext.\
|
||||
- **Backups**: documenten zijn de "bron"? Zo ja, S3 is primaire opslag
|
||||
en RAG-index kan herbouwd worden. Anders: definieer
|
||||
export/replica-strategie.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 9) Migratie van MinIO → Scaleway
|
||||
|
||||
1. **Freeze window** (kort): pauzeer uploads of werk met **duale
|
||||
write** (MinIO + S3) gedurende migratie.\
|
||||
2. **Sync**: gebruik `rclone` of `mc mirror` om
|
||||
`minio://bucket/tenant-*/{documents,assets}/` →
|
||||
`s3://evie-<env>/tenant-*/...`.\
|
||||
3. **Verifieer**: random checksums / sample reads per tenant.\
|
||||
4. **Switch**: zet `S3_ENDPOINT` en keys naar Scaleway; laat nieuwe
|
||||
writes enkel naar S3 gaan.\
|
||||
5. **Decom**: na grace-periode MinIO uitfaseren.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## 10) Checklist (TL;DR)
|
||||
|
||||
- [ ] Buckets: `evie-staging`, `evie-prod`.\
|
||||
- [ ] Prefix: `tenant-<id>/{documents,assets}/`.\
|
||||
- [ ] IAM: 1 Application per omgeving; keys in k8s Secret.\
|
||||
- [ ] Policy: alleen app-toegang; app dwingt prefix-scope per tenant
|
||||
af.\
|
||||
- [ ] Lifecycle: assets sneller koud, docs langer.\
|
||||
- [ ] CORS: alleen noodzakelijke origins/methods.\
|
||||
- [ ] Presigned URLs voor browser interacties.\
|
||||
- [ ] Logging/metrics/alerts ingericht.\
|
||||
- [ ] Migratiepad van MinIO uitgewerkt en getest.
|
||||
Reference in New Issue
Block a user