Se non è descritto non esiste

2025/04/14 · Marco Orlandin · 7 min · TL;DR

Perché un'infrastruttura non documentata non è un'infrastruttura: è un favore personale che diventa debito tecnico.

Rappresentazione visiva di un Architetto che mette in ordine l'infrastruttura

Ho ereditato troppi ambienti dove la conoscenza era orale: "Non toccare quel server", "Quella variabile funziona solo se...". Script con nomi assurdi, readme incompleti. Fragili e pronti a rompersi al primo cambio.

Il caso più educativo: un'azienda con tre ambienti (sviluppo, staging, produzione) che avrebbero dovuto essere identici. Non lo erano. Le differenze si erano accumulate in due anni di modifiche manuali, ognuna fatta "al volo" per risolvere un'urgenza. Nessuno sapeva più cosa fosse diverso e perché. Quando il sistemista di riferimento ha cambiato lavoro, la prima domanda è stata: "Ma tu come facevi a fare il deploy?" La risposta era nella sua testa. E nella sua testa è rimasta.

Questo tipo di debito non è solo infrastrutturale. Lo stesso meccanismo si applica ai costi cloud che nessuno sa spiegare: configurazioni fatte da qualcuno, mai documentate, che continuano a produrre effetti molto tempo dopo che la persona se n'è andata.

Documentare a posteriori? Tempo perso. Le cose evolvono troppo in fretta.

Docker ha risolto il "sul mio PC funziona": incapsula tutto, isola componenti, webserver, database, key-value store, applicativo. Trasportabile, ma sposta il caos, non lo elimina.

Terraform va oltre: ti obbliga a descrivere. Se non è nel codice, non esiste. Trasforma il "qualcuno lo sapeva far funzionare" in un sistema chiaro, versionato e ripetibile.

Il cambio di mentalità è questo: prima di Terraform, l'infrastruttura era il risultato di azioni fatte nel tempo, accumulate, mai riviste. Con Terraform, l'infrastruttura è una dichiarazione di intenti. Se qualcosa non è nel file .tf, non dovrebbe esistere. Se esiste ma non è dichiarata, è un problema da risolvere, non una feature.

Perché Terraform e non altro

Quando si decide di adottare Infrastructure as Code, la prima domanda è sempre: quale strumento? Le alternative non mancano, e ognuna ha i suoi punti di forza. Il punto è capire quali compromessi sei disposto ad accettare.

Pulumi, per esempio, è interessante: scrivi l'infrastruttura in Python, TypeScript, Go. Per un team di sviluppatori è attraente, perché usi un linguaggio che già conosci. Ma nella pratica aggiunge una dipendenza che non sempre serve. Se il tuo team include persone che non scrivono codice tutti i giorni (sistemisti, devops junior, project manager tecnici), un linguaggio di programmazione completo diventa una barriera. L'infrastruttura deve essere leggibile anche da chi non è uno sviluppatore. Con Terraform, un file .tf si legge quasi come un documento: c'è una risorsa, ha un nome, ha delle proprietà. Non serve sapere cosa sia un ciclo for o una callback.

AWS CloudFormation? Se lavori solo su AWS, funziona. Ma il giorno in cui il cliente decide di spostare un servizio su un altro provider (succede più spesso di quanto si pensi), riparti da zero. Lo stesso vale per AWS CDK, che sotto il cofano genera comunque template CloudFormation. Aggiungi un livello di astrazione sopra uno strumento già legato a un singolo vendor: il risultato è più complessità, non meno.

Terraform (e il suo fork open-source OpenTofu) è cloud-agnostico. Lo stesso linguaggio, la stessa logica, lo stesso flusso di lavoro funzionano su AWS, Azure, Google Cloud, Cloudflare, e decine di altri provider. Per un consulente che lavora con clienti diversi, questo è decisivo: non devo reimparare lo strumento ogni volta che cambia il cloud. E per il cliente, significa che la conoscenza infrastrutturale non è incatenata a un fornitore.

Il caso Portainer

Esempio concreto: cliente con infra gestita via Portainer (non il mio tool preferito, ma era lì). L'ho integrato senza stravolgere tutto.

Il team usava Portainer da un anno. Ci aveva costruito sopra il deploy di sei servizi, tutti configurati tramite l'interfaccia web. Funzionava, nel senso che i container giravano. Ma non c'era modo di sapere cosa fosse cambiato, quando, e perché. Ogni modifica era un click nell'interfaccia, non un commit nel repository. E quando qualcosa si rompeva, la domanda era sempre la stessa: "Chi ha toccato cosa?"

Proporre di buttare via Portainer sarebbe stato inutile. Il team ci si era affezionato, e in parte aveva ragione: per il monitoraggio e la visualizzazione rapida dei container, è comodo. Il punto non era sostituirlo, ma togliergli il ruolo di strumento di deploy e restituirlo al suo posto naturale: una dashboard.

Setup modulare:

  • Repo Git unico: sorgenti app + infrastruttura.
  • App containerizzata, build in AWS ECR.
  • Deploy semplice: push nuova immagine, terraform apply.
  • Stato remoto in S3: fonte di verità condivisa. Niente conflitti, tutto versionato.

La resistenza iniziale c'è stata, ed era comprensibile. "Ma prima facevo tutto con due click." Vero. I primi tre giorni sono stati i più faticosi. Ogni operazione che prima richiedeva trenta secondi nell'interfaccia di Portainer ora richiedeva di scrivere un blocco di configurazione, fare un commit, lanciare terraform plan, verificare l'output, poi terraform apply. Tempo triplicato, frustrazione alta. Qualcuno ha chiesto esplicitamente di tornare indietro.

Il momento di svolta è arrivato il quarto giorno. Un deploy in staging ha rotto qualcosa, un volume montato nel modo sbagliato. Con il vecchio sistema, sarebbe partita la caccia: chi ha toccato cosa, quando, con quale configurazione. Invece, il team ha aperto la cronologia dei commit, ha trovato la modifica in trenta secondi, ha fatto un revert e in cinque minuti era tutto ripristinato. Nessuna telefonata, nessun "ti ricordi come era prima?". La risposta era nel repository.

Da quel momento la resistenza è calata. Non è sparita subito, ci è voluta un'altra settimana prima che il flusso diventasse naturale. Ma nessuno ha più chiesto di tornare al vecchio modo. Quando vedi che un problema che prima ti rubava mezza giornata si risolve in cinque minuti, il costo della verbosità inizia a sembrarti accettabile.

Risultato: cambiamenti tracciati, zero sovrapposizioni. Chi subentra non deve pregare il predecessore. Conoscenza che resta anche quando le persone cambiano.

Terraform è verboso, sì. Ma è l'unico modo per avere chiarezza reale e ridurre il debito tecnico.

Come partire senza drammi

  • Containerizza prima (Docker o Podman).
  • Descrivi quello che cambi più spesso.
  • Backend remoto (S3) dal giorno uno.
  • Trattalo come abitudine, non come atto di eroismo.

Una cosa che ripeto spesso: non serve descrivere tutto il primo giorno. Parti da quello che rompi più spesso. Quel server che ogni tre mesi qualcuno configura a mano? Quello. Quel bilanciatore che ha regole che nessuno ricorda? Quello. Terraform si adotta per pezzi, non per rivoluzioni.

Quando Terraform non è la risposta

Non sempre serve. Se hai un singolo server con una configurazione che non cambia mai, Terraform è sovradimensionato. Se il tuo team è di due persone e il deploy è un scp su una macchina, non hai bisogno di stato remoto in S3.

E se il problema è la configurazione del software (non dell'infrastruttura), Ansible è probabilmente lo strumento giusto. Terraform descrive cosa esiste. Ansible descrive come è configurato. Sono complementari, non alternativi.

Un esempio concreto: devi mettere in piedi un server web. Terraform crea l'istanza EC2, configura il security group con le porte 80 e 443 aperte, associa un indirizzo IP elastico, collega il disco. Tutto quello che riguarda l'infrastruttura AWS. Poi entra in gioco Ansible: installa nginx sulla macchina, copia i file di configurazione dell'applicazione, imposta i cron job per i backup, gestisce i certificati SSL. Due strumenti, due responsabilità distinte.

Provare a fare tutto con uno solo porta a soluzioni goffe. Ho visto file Terraform con provisioner "remote-exec" lunghi cinquanta righe che installavano pacchetti, copiavano file, riavviavano servizi. Funziona? Tecnicamente sì. Ma è fragile, difficile da testare, e si rompe in modi imprevedibili. Allo stesso modo, gestire risorse cloud con Ansible è possibile, ma ti ritrovi a scrivere playbook che lottano contro un problema per cui non sono stati pensati. Ogni strumento ha il suo ambito: rispettarlo ti risparmia ore di debug.

Il punto non è adottare Terraform. Il punto è avere l'infrastruttura descritta in un posto leggibile, versionato e condiviso. Se un file README aggiornato basta per il tuo contesto, basta quello. Ma se il README non è aggiornato da sei mesi, il problema non è lo strumento. È che nessuno si è preso la responsabilità di descrivere quello che ha costruito.

Preferisci l'open-source? OpenTofu e passa la paura.

Hai ambienti che dipendono dalla memoria di qualcuno? Parliamone. Ti dico se Terraform è la soluzione o se serve altro.

In sintesi (TL;DR)

  • Un'infrastruttura non documentata non è un'infrastruttura: è conoscenza orale che se ne va quando le persone cambiano lavoro.
  • Terraform obbliga a descrivere: se non è nel codice, non esiste. Ogni deploy è un commit, ogni commit è reversibile.
  • Non serve descrivere tutto il primo giorno: parti da quello che rompi più spesso, adotta per pezzi.
  • Se il problema è la configurazione del software (non dell'infrastruttura), Ansible è lo strumento giusto. Sono complementari.