Infrastructure as code: smettere di cliccare e iniziare a governare 🌍
Infrastructure as Code, o IaC, significa definire infrastruttura e configurazioni operative come codice versionato, revisionabile e ripetibile. Traduzione pratica: meno click in console, meno “ma io avevo cambiato solo una regolina”, meno sorprese alle 18:47 del venerdì.
IaC non serve solo a creare VM o cluster. Serve soprattutto a rendere esplicito, ripetibile e verificabile ciò che prima viveva in ticket, screenshot, memoria storica e altri supporti noti alla scienza per essere poco affidabili.
Cosa rientra davvero in IaC 🧱
Con IaC puoi gestire come codice:
- rete, subnet, security group e firewall
- cluster, nodi, bilanciatori e storage
- identità tecniche, ruoli e permessi
- DNS, certificati e integrazioni cloud
- policy, tagging, naming convention e guardrail
Il punto non è “scrivere Terraform perché sì”. Il punto è trattare l’infrastruttura con la stessa disciplina che pretendi dal software applicativo.
Ciclo di vita di una modifica IaC 🔄
Quando IaC funziona bene, una modifica infrastrutturale smette di essere un gesto artigianale e diventa un flusso leggibile, revisionabile e ripetibile.
flowchart LR
A[Modifica modulo o stack] --> B[Lint e validate]
B --> C[Plan]
C --> D[Pull request e review]
D --> E[Merge]
E --> F[Apply controllato]
F --> G[Aggiornamento state remoto]
G --> H[Drift detection e osservabilità]
Se nel tuo processo mancano plan leggibile, review e stato remoto protetto, non stai facendo IaC in modo maturo: stai solo spostando il rischio da una console web a un repository Git.
Modelli principali: dichiarativo vs imperativo ⚖️
Nella pratica trovi due approcci principali:
- dichiarativo: descrivi lo stato desiderato e il tool calcola come arrivarci
- imperativo: descrivi i passaggi da eseguire in sequenza
Per provisioning e gestione dello stato, il dichiarativo vince spesso in leggibilità e governance. Per bootstrap, configurazioni puntuali o orchestrazione procedurale, l’imperativo può ancora avere un ruolo. Il trucco è non usare il martello per aprire ogni tipo di vite.
Tool comuni e differenze utili 🛠️
- Terraform / OpenTofu: standard de facto per provisioning infrastrutturale dichiarativo multi-cloud.
- Pulumi: approccio IaC tramite linguaggi general purpose, utile quando vuoi composizione più espressiva.
- Ansible: ottimo per configurazione e automazione operativa, meno ideale come unica fonte di verità per tutto il provisioning cloud.
- Crossplane: interessante quando vuoi portare modelli IaC dentro ecosistemi Kubernetes.
Scegliere uno strumento giusto è utile. Sceglierlo e poi usarlo senza convenzioni, policy e review è un modo elegante per creare caos versionato.
Vale anche il contrario: passare mesi a discutere il tool “perfetto” mentre il team continua a fare click in console è solo procrastinazione con vocabolario tecnico.
Come separare layer e responsabilità 🏗️
Uno dei modi più efficaci per evitare caos è non buttare tutto nello stesso stack. Un modello semplice e robusto è dividere per layer di responsabilità:
flowchart TD
A[Foundation layer] --> B[Platform layer]
B --> C[Application layer]
A --> A1[Rete, account, IAM, state backend]
B --> B1[Cluster, shared services, observability]
C --> C1[Configurazioni specifiche app e integrazioni]
Questa separazione riduce blast radius, chiarisce ownership e impedisce che una modifica applicativa tocchi per sbaglio metà fondazione cloud.
Best practice che fanno la differenza ✅
1. Versiona tutto ciò che conta 📚
Non solo i file principali: anche moduli, policy, variabili condivise, workflow di validazione e documentazione operativa. Se una modifica infrastrutturale è importante ma non è in Git, prima o poi diventerà una storia triste.
2. Separa bene ambienti e responsabilità 🧭
Produzione, staging e sviluppo non dovrebbero differire per magia o memoria orale. Definisci convenzioni chiare per:
- struttura dei repository
- naming delle risorse
- promozione tra ambienti
- ownership dei moduli
- confini tra piattaforma e team applicativi
3. Tratta lo state come un asset critico 🗃️
Se usi strumenti con state remoto, proteggilo bene. Locking, backup, cifratura, accesso minimo e audit non sono optional. Perdere o corrompere lo state è un modo molto efficace per trasformare un provisioning in archeologia digitale.
4. Progetta moduli piccoli e leggibili 🧩
Un buon modulo riduce duplicazione e chiarisce le responsabilità. Un modulo gigante che crea mezza regione cloud e 27 eccezioni ambientali è solo monolite con sintassi diversa. Preferisci moduli:
- con interfacce chiare
- con input limitati e ben documentati
- facili da testare
- facili da versionare e riusare
5. Valida, testa e fai plan review 🧪
IaC senza validazione è solo speranza con estensione diversa. Aggiungi sempre:
- lint e formattazione
- validate o check sintattici
- plan in pull request
- policy as code
- test dei moduli dove il tool lo consente
6. Gestisci il drift in modo esplicito 🛰️
Se qualcuno cambia una risorsa a mano, devi saperlo. Il drift va rilevato, analizzato e corretto in modo intenzionale. Non sempre il self-healing automatico è la scelta giusta, ma il drift silenzioso è quasi sempre una pessima idea.
7. Integra IaC con sicurezza e compliance 🔒
IaC è il posto perfetto per codificare controlli ripetibili:
- cifratura obbligatoria
- tagging coerente
- restrizioni di rete
- limiti di esposizione pubblica
- vincoli su region, SKU e configurazioni sensibili
8. Progetta una pipeline minima ma rigorosa ⚙️
Non serve una pipeline teatrale con 19 stage solo per sentirsi enterprise. Serve una pipeline sobria che faccia davvero le cose importanti:
- format e lint
- validate
- plan pubblicato in PR
- controlli di policy e security
- apply solo su branch o workflow autorizzati
- audit dei cambiamenti e notifica degli apply
Il valore non sta nel numero di step, ma nella loro affidabilità e nel fatto che siano sempre uguali, anche quando la fretta bussa alla porta.
9. Documenta input, output e assunzioni dei moduli 📝
Molti repository IaC degradano non perché il tool sia scarso, ma perché nessuno capisce più:
- quali input sono obbligatori
- quali output sono contratti riusabili
- quali convenzioni sono richieste
- quali vincoli di sicurezza o naming sono impliciti
Se un modulo funziona solo “perché lo sa chi l’ha scritto”, non hai standardizzato nulla. Hai solo spostato la dipendenza cognitiva da una console a un file.
IaC, GitOps e CI/CD: chi fa cosa 🔗
La distinzione utile è questa:
- IaC crea e governa l’infrastruttura
- CI/CD builda, testa e pubblica artefatti
- GitOps riconcilia configurazioni e stato desiderato degli ambienti operativi a partire da Git
In molti contesti il flusso migliore è: IaC per cluster, rete, database gestiti e identity; CI/CD per produrre immagini e pacchetti; GitOps per orchestrare la configurazione applicativa e il rollout continuo.
Detto in modo brutale ma utile:
- IaC crea e protegge il contesto operativo
- CI/CD produce il software
- GitOps governa ciò che deve girare dentro quel contesto
Errori comuni da evitare 🚫
Moduli troppo generici o troppo “smart”: se nessuno capisce quali risorse crea davvero, hai perso trasparenza.
State locale condiviso via speranza: se il coordinamento dipende dal fatto che “tanto oggi non lancia nessun altro”, stai già negoziando con il disastro.
Variabili senza governance: naming casuale, default oscuri e override ambientali infiniti sono la via breve verso errori difficili da tracciare.
Mix disordinato di provisioning e configurazione runtime: creare un cluster e installare mezzo mondo dentro lo stesso layer spesso rende tutto più fragile da evolvere.
Nessun controllo in pull request: se il primo momento in cui guardi il piano è dopo l’apply, non è review. È archeologia post-incidente.
In breve 🧾
IaC non è solo un modo più elegante per creare risorse cloud. È un modo per portare disciplina, review, sicurezza e ripetibilità nell’infrastruttura. Se fatto bene, riduce drift, click manuali e dipendenza dalla memoria dei singoli. Se fatto male, produce solo più YAML o più HCL da decifrare alle 2 di notte. Meglio la prima opzione.