
Mi è capitato un progetto di ricerca ML in ambito accademico: due ambienti AWS, staging e produzione, da progettare quasi da zero. Un team, nessuna PII, nessun requisito di compliance, budget vicino al minimo. La documentazione AWS sull'isolamento ambienti propone soluzioni pensate per organizzazioni più strutturate. Capire dove fermarsi era il vero lavoro.
Cosa serviva davvero
Due ambienti cloud: staging e produzione. Il dev resta locale, gira in docker-compose sulla macchina di chi sviluppa. Tre ambienti su AWS sarebbero stati pagati per nulla, perché il ciclo di feedback è già rapido sulla macchina locale e il deploy passa da CI/CD.
I requisiti, in ordine di importanza:
- I dati di staging e produzione non devono mai mescolarsi.
- Lo staging deve costare vicino a zero quando non gira.
- L'infrastruttura definita in Terraform, parametrizzata sull'ambiente.
- Un team singolo deve poter gestire tutto senza overhead organizzativo.
- Possibilità di evolvere verso un isolamento più forte se il progetto cambia profilo.
Niente di esotico. Nessun catalogo da copiare, però. La risposta giusta dipendeva dal capire dove il rischio era reale e dove no.
Cosa AWS propone, e per quali scenari
Il menu di isolamento che AWS mette a disposizione è pensato per coprire un ampio spettro di contesti. La trappola, se non si è attenti, è prendere il pattern enterprise e adattarlo a un progetto piccolo. Vale la pena passarlo in rassegna, brevemente, per capire dove ogni pezzo serve.
- Account AWS separati (tramite Organizations) sono il livello più alto di isolamento. Blast radius zero fra ambienti, billing segregato, IAM completamente indipendente. Servono quando ci sono più team da proteggere l'uno dall'altro, requisiti di compliance che impongono audit trail separati, o tenant a contratto che richiedono boundary contrattuali rigidi.
- VPC separate nello stesso account isolano la rete. Utili quando si vuole impedire qualsiasi comunicazione non voluta fra ambienti, o quando un ambiente serve un perimetro di rete specifico (per esempio una DMZ).
- Subnet private con NAT Gateway isolano i workload dall'ingresso pubblico, lasciando l'egress controllato. Standard quando l'esposizione diretta a internet è inaccettabile per policy, o quando ci sono endpoint sensibili che non devono apparire in alcuna route table pubblica.
- AWS Control Tower e le Service Control Policies governano l'evoluzione di molti account su scala organizzativa. Servono quando gli account sono molti e crescono in modo non controllato.
Ognuno di questi strumenti ha un costo, in soldi o in complessità di gestione. Per il progetto in questione, i requisiti che li giustificherebbero non c'erano. Il lavoro è stato accorgersene presto, prima di scrivere il primo modulo Terraform.
Le decisioni
Una volta deciso quali rischi erano reali (mescolare i dati, perdere il controllo del costo) e quali non lo erano (esposizione cross-team, compliance, audit), il setup si è semplificato in fretta.
| Decisione | Scelta | Motivazione |
|---|---|---|
| Ambienti | 2: staging + produzione. Dev resta in docker-compose locale. | Dev non ha bisogno di AWS per il ciclo di feedback. Due ambienti cloud bastano per coprire le fasi che contano. |
| Account AWS | Singolo, separazione via prefix di naming (stg-, prod-) e tag Environment su tutte le risorse. | Un solo team a gestire. Senza requisiti di audit cross-account, due account aggiungerebbero gestione senza beneficio proporzionato. |
| Networking | 1 VPC condivisa, 2 subnet pubbliche (una per AZ). | La VPC in sé non costa. Le subnet pubbliche evitano la necessità di un NAT Gateway per l'egress, che costerebbe circa 35 dollari al mese per ambiente. |
| Load balancer | 1 ALB condiviso, listener rules host-based per instradare staging e produzione a target group diversi. | Un ALB costa circa 20 dollari al mese. Le listener rules aggiuntive hanno costo trascurabile. Due ALB raddoppierebbero questa voce senza un beneficio funzionale. |
| Compute | ECS Fargate in subnet pubbliche, IP pubblico assegnato al task. | Pay per use sul compute. Niente NAT, perché il task esce in internet direttamente. L'ingresso è controllato dal Security Group. |
| Isolamento rete | Un Security Group per ambiente, restrittivo in ingresso. | Il Security Group è gratuito e sufficiente per il livello di rischio di questo progetto. La combinazione subnet privata + NAT Gateway risolverebbe scenari diversi, a un costo che qui non si giustifica. |
| Container registry | 1 ECR repo condiviso, differenziazione via image tag (stg-v1.2, prod-v1.2). | Le immagini sono artefatti immutabili. Il tag indica la destinazione, il contenuto è lo stesso. |
| Storage dati | 2 bucket S3 separati per ambiente. | Qui si separa. I dati sono l'unica cosa che non deve mai finire nel posto sbagliato. La separazione fisica è esplicita e visibile in console. |
| Secrets | 1 secret JSON per ambiente in AWS Secrets Manager. | Separazione logica con naming convention rigoroso. Ogni ambiente ha le sue credenziali, connection string, configurazioni. |
I tre meccanismi di isolamento che hanno fatto il lavoro: account-level naming convention, Security Group per il traffico, separazione fisica dei bucket S3. Tre, su un catalogo molto più ampio.
Il costo, ambiente per ambiente
I numeri raccontano meglio di qualsiasi principio perché questo setup ha senso in questo contesto.
- ALB: condiviso. Lo staging aggiunge solo il costo trascurabile delle listener rules.
- ECS Fargate: pay per use. Lo staging quando non gira costa zero compute.
- S3: pochi centesimi finché i dati sono pochi, perché paghi lo storage effettivo.
- NAT Gateway: zero, perché non esiste in questa architettura.
- Totale staging, idle: vicino a zero.
Per confronto, lo stesso staging fatto con account separato, VPC dedicata e NAT Gateway avrebbe avuto un costo fisso di circa 50-70 dollari al mese anche da spento, prevalentemente per le risorse che restano accese a prescindere dall'uso. Su un progetto con budget al minimo, è una voce che pesa.
Dove questo setup smette di funzionare
Ogni scelta architetturale ha confini, e fingere che non li abbia è il modo più rapido per ritrovarseli addosso in produzione. Questo approccio funziona finché valgono le condizioni che lo hanno reso adatto. Cambia anche una sola e va rivisto.
- Quando entrano compliance e regolamentazione. GDPR con DPA stringenti, HIPAA, PCI-DSS richiedono isolamento misurabile, audit trail per ambiente, e in generale Organizations con Service Control Policies. Le Naming convention non sostituiscono un audit segregato.
- Quando il team si allarga. Un singolo team con disciplina su naming e tag tiene il setup pulito. Più team sullo stesso account introducono il rischio sistemico che basti un errore di prefix per toccare risorse di un altro ambiente. Account separati proteggono i team l'uno dall'altro.
- Quando in produzione entrano dati personali su scala. Un misconfiguration di Security Group o di policy IAM, in un setup logicamente separato ma fisicamente condiviso, può esporre dati che non avrebbero mai dovuto attraversare il perimetro. Isolamento fisico vale più di isolamento logico, in questo scenario.
- Quando il downtime ha un costo economico diretto. Per produzione business-critical, l'isolamento infrastrutturale serve come assicurazione, non come ottimizzazione di costo. Un VPC condivisa che ha un problema di routing porta giù entrambi gli ambienti insieme.
Questo è il punto di evoluzione naturale del setup: tenere il pattern attuale finché vale, sapere già dove rompere lo schema quando una di queste condizioni cambia.
I trade-off che mi tengo
Niente è gratis. Le scelte che ho fatto comprano risparmio e semplicità, e in cambio caricano altre forme di rischio. Vale la pena tenerle in vista.
- Rischio sul naming. Un prefix sbagliato, e una risorsa di staging finisce a interagire con una di produzione. Il livello tecnico di mitigazione è il modulo Terraform: il pattern di naming non lo decide la persona, lo decide il codice. Il livello operativo è il tag
Environmentobbligatorio su ogni risorsa, e una review IaC su ogni PR. - Rischio sulla rete. Le subnet pubbliche espongono i task ECS a internet sulle porte aperte dal Security Group. La regola è che il Security Group resta restrittivo per default e si apre solo dove serve. Se un domani diventa necessario un perimetro più chiuso, il piano è subnet private dietro NAT Gateway. Va riarchitettato, non è un cambio cosmetico.
- Rischio culturale. "Funziona così, va bene per questa fase" tende a diventare "funziona così e basta". Vale solo se ricordo, quando il progetto cambia, che il setup è esplicitamente datato. La rivalutazione non è opzionale: è la contropartita di averlo costruito stretto.
Il filo comune
Una parte del lavoro è scritta a fianco in un altro appunto sui moduli Terraform per ambienti multipli, che è la versione pratica di queste decisioni in IaC. Stessi sei moduli per staging e produzione, parametrizzati. Il vero problema, lì come qui, non è scrivere il codice. È decidere cosa condividere e cosa separare, e poi tenere la disciplina di non fare eccezioni.
C'è un pattern più ampio che ricorre in un altro intervento sui costi cloud: il cloud non è caro, è non governato. Qui il principio gira di un quarto: il cloud non è caro, ma è dimensionato per scenari che potrebbero non essere i tuoi. La documentazione AWS è scritta per il caso enterprise, perché lì il costo dell'errore è alto. Su un progetto piccolo, lo stesso pattern diventa peso morto.
Se hai un progetto piccolo che si trova davanti al menu di servizi AWS e non sa dove fermarsi, o se uno staging che ti costa quanto la produzione e vorresti capire dove è il margine... parliamone. Ti dico cosa serve, e cosa puoi togliere.
Questo caso l'ho documentato in modo più strutturato come Architecture Decision Record, con contesto reale, trade-off valutati e risultati osservati.
ADR260331: Isolamento ambienti tramite condivisione infrastrutturale e separazione dati →
In sintesi (TL;DR)
- Un progetto di ricerca ML in ambito accademico aveva bisogno di due ambienti AWS (staging e produzione) con budget vicino al minimo, un team, nessuna PII e nessun requisito di compliance.
- Dei meccanismi di isolamento che AWS offre (account separati, VPC dedicate, NAT Gateway, Control Tower) la maggior parte risolve scenari diversi da questo. Il lavoro è stato capire cosa serviva davvero.
- Account singolo, VPC condivisa con subnet pubbliche, ALB condiviso, ECS Fargate con IP pubblico, Security Group per ambiente. Separazione solo dove conta: bucket S3 e Secrets Manager per ambiente.
- Lo staging costa quasi zero quando non è in uso. Il setup ha confini precisi: smette di funzionare quando entrano compliance, più team, PII su scala, o produzione business-critical.