4 motivi fondamentali per preferire AWS CDK a Terraform

4 motivi fondamentali per preferire AWS CDK a Terraform

If you're looking for the English version of this article, click here.

Negli ultimi mesi ho usato AWS CDK per alcuni progetti, e ogni volta che ho iniziato a parlarne, qualcuno chiedeva: perché dovrei abbandonare il tool che sto usando e passare a CDK? Che vantaggi offre?

In questo post non mi soffermo sui dettagli implementativi; online si possono trovare moltissime risorse utili, da tutorial per principianti fino ad articoli molto avanzati.

Io invece voglio sintetizzare quelli che secondo me sono caratteristiche molto interessanti del framework.

Sono un'appassionata sostenitrice dell'Infrastructure as Code e ne faccio larghissimo uso fin dalle prime primitive versioni dei tool che oggi sono diventati leader affermati di questo campo. Quello che impari con l'esperienza è che non esiste il tool perfetto che risolve ogni problema o che va bene per tutte le occasioni; esistono tool che si adattano a più situazioni diverse, o che vengono selezionati per alcune specifiche caratteristiche dell'azienda per cui lavori, dei suoi processi, dei rischi che si accetta di affrontare, dei problemi di cui ci si fa carico, e così via.

Per poter spiegare i vantaggi (e i limiti) che ho trovato in CDK, è necessario fare un passo indietro e ricordare le caratteristiche di alcuni dei tool di Infrastructure as Code più usati.

Cloudformation

Cloudformation è il servizio di Infrastructure as Code di AWS. E' attivo sin dal 2011 (sembra ieri, ma nell'era del cloud parliamo di ere geologiche precedenti), gratuito e utilizza linguaggi descrittivi come JSON e YAML (quest'ultimo a partire dal 2016, con grande sollievo di molti) per creare template in cui vengono definite le risorse da creare su AWS. Questi template vengono elaborati dal servizio Cloudformation che crea le risorse così come sono descritte. Se vogliamo modificare la nostra infrastruttura, è sufficiente rieseguire il template modificato.

Vantaggi

L'imbattibile vantaggio di Cloudformation è la gestione automatica del rollback. Se il mio template contiene degli errori, Cloudformation ferma l'azione di update dell'infrastruttura e automaticamente ritorna allo stato precedente, ovvero all'ultima versione "funzionante" del mio template.

Limiti

  1. Nel corso degli anni Cloudformation ha subito molte evoluzioni, introdotto funzionalità, utilizzo cross-account e tanto altro... eppure, nessuno lo ama. Al più, viene tollerato. Perché? Per via dei linguaggi che utilizza. JSON e YAML sono essenzialmente formati per la serializzazione dei dati e funzionano bene con le macchine... meno bene con gli umani. Sono certamente semplici da leggere, ma estremamente noiosi da scrivere. Poiché non sono linguaggi di programmazione, non si hanno a disposizione meccanismi pratici (nonché basilari) come ad esempio i cicli per le operazioni ripetitive: se ho bisogno di creare 10 security group, devo elencarli tutti, uno per uno, senza scampo. Se hai mai usato Cloudformation, sai di cosa parlo.

  2. Funziona esclusivamente su AWS.

Terraform

Terraform è un tool opensource di Hashicorp per l'Infrastructure as Code, rilasciato inizialmente nel 2014. Utilizza il linguaggio dichiarativo HashiCorp Configuration Language (HCL) che fin dalle prime release è sembrato immediatamente più amichevole nella scrittura dell'infrastruttura. Una volta che un utente invoca Terraform su una determinata risorsa, Terraform esegue azioni CRUD tramite le API del cloud provider per ottenere lo stato desiderato. Il codice può essere fattorizzato in moduli, promuovendo riutilizzabilità e manutenibilità.

Vantaggi

  1. Terraform gestisce le risorse esterne con i "provider". Gli utenti possono interagire con i provider Terraform dichiarando le risorse o utilizzando datasource; esistono molti provider manutenuti sia da Hashicorp sia dalla community, e AWS è uno di questi. Il primo vantaggio è quindi che si tratta di un tool cross-platform.

  2. Con le evoluzioni del linguaggio HCL nel corso degli anni, Terraform consente di utilizzare diversi costrutti che funzionano come cicli per poter abbreviare la scrittura ripetitiva di risorse simili. Ad esempio, uno dei costrutti più comuni è ciclare su una lista:

resource "aws_ecr_repository" "ecr_repo" {
  count                = length(local.repo_list)
  name                 = local.repo_list[count.index]
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}

ma con le ultime versioni di Terraform è possibile utilizzare costrutti più complessi, come l'estrazione di chiavi e valori da una mappa per poterli usare secondo le proprie necessità:

...
  dynamic "predicates" {
    for_each = [for k, v in each.value["sets"] : {
      set = v
    } if contains(keys(aws_waf_ipset.waf_ipset), v)]
    content {
      data_id = aws_waf_ipset.waf_ipset[predicates.value.set].id
      negated = false
      type    = "IPMatch"
    }
  }
...

Probabilmente non il codice più chiaro del mondo, anche se comunque meglio degli infiniti elenchi di attributi in Cloudformation...

Limiti

  1. Il famigerato state file! Terraform salva lo stato dell'infrastruttura in un file JSON che viene generato ad ogni esecuzione. Conservare questo file è estremamente importante perché è la "fonte di verità"; Terraform infatti consulta questo file prima di ogni esecuzione per stabilire la discrepanza tra lo stato desiderato (cioè il codice che vogliamo eseguire) e lo stato attuale, e da questo confronto decide le azioni da intraprendere per colmare il divario. Se lo state file è perduto, Terraform non è in grado di accorgersi che parte dell'infrastruttura era già stata creata in precedenza, e vorrà ricominciare da zero.

    Inoltre, tenere tutto assieme il codice di un'infrastruttura molto grande è una bad practice, per svariati motivi: rischio operativo, gestione condivisa, passaggi di consegne, e generale manutenibilità del codice. Tipicamente ogni "stack" infrastrutturale viene creato con blocchi di codice eseguiti separatamente: questo significa che ogni stack avrà un suo state file, e di conseguenza la conservazione di questi state file, a lungo andare, con team numerosi e infrastrutture molto grandi, diventa una questione molto importante e delicata.

  2. Nessuna gestione del rollback. Le operazioni CRUD eseguite da Terraform, come accennavo prima, sono chiamate sequenziali alle API del cloud provider; se per qualche motivo a metà esecuzione una chiamata non va a buon fine... Terraform ti pianta in asso, si ferma e lascia all'utente l'onere di rimettere a posto le modifiche lasciate a metà. Non il miglior modo di comportarsi, specialmente per ambienti di produzione.

CDK

Okay, finalmente al punto: quali sono le caratteristiche di CDK che la rendono preferibile agli strumenti appen citati? Personalmente ne vedo almeno 4! Vediamoli in ordine di importanza.

Vantaggio #1: Rollback

CDK è un framework che, quando eseguito, “sintetizza” un template Cloudformation e poi lo applica. Di conseguenza, eredita tutte le caratteristiche positive di Cloudformation, e, in particolare, la capacità di effettuare automaticamente il rollback allo stato precedente. Questa è una caratteristica a mio avviso importantissima, soprattutto quando si effettuano modifiche su stack già creati in precedenza, in particolare se in ambiente di produzione. Il rollback è una fase troppo spesso sottovalutata… finché qualcosa va male.

Vantaggio #2: No state file

Come ho detto, trattandosi di template Cloudformation sintetizzati dal framework, la gestione dello stato dell’infrastruttura è demandata a Cloudformation stesso, e non esistono file di stato da dover gestire. In più, è molto più semplice consultare lo stato delle risorse dalla stessa console dell’account AWS. Visti i rischi che ho elencato prima riguardo alla gestione dello state file, è un vantaggio non da poco.

Vantaggio #3: Friendly/familiar programming language

AWS CDK è disponibile per i linguaggi più diffusi: TypeScript, Python, Java, .NET, e Go. Non ci sono particolari differenze tra queste implementazioni: la scelta può basarsi unicamente sulla familiarità che l’utente ha con un linguaggio o un altro. Nel mio caso, ho usato Python e la mia esperienza è stata piacevolmente semplice e senza intoppi, grazie anche a una documentazione estremamente completa e al supporto per i principali IDE.

L’uso di un linguaggio di programmazione vero e proprio ha anche il notevole vantaggio di poter effettuare qualsiasi tipo di operazione non necessariamente legata a CDK, come ad esempio richieste ad API esterne per recupero di informazioni o notifiche, manipolazione di stringhe, file, JSON o simili… il limite è la fantasia!

Vantaggio #4: Generazione automatica delle policy IAM

Per finire, non c’è necessità di scrivere quasi niente relativo a ruoli e policy IAM. Il framework, basandosi sulle relazioni tra le risorse dichiarare nel codice, è in grado di calcolare automaticamente i permessi necessari e di creare autonomamente ruoli e policy, seguendo il principio di assegnare solo i permessi strettamente necessari.

Non è affatto un vantaggio da poco, considerando che questo meccanismo assicura di non dimenticare qualche permesso e, soprattutto, di evitare di assegnare più permessi di quanti ne servano, per errore o per fretta.

Naturalmente è sempre possibile aggiungere dei permessi che il framework non è in grado di calcolare. Ad esempio, può succedere di creare una Lambda function che al suo interno effettua delle chiamate API a servizi AWS; in quel caso il codice della Lambda non è parte del codice CDK e quindi è escluso dal “calcolo”. I permessi necessari alla Lambda per le sue chiamate vanno quindi aggiunti in modo puntuale al ruolo che la CDK crea automaticamente.

Oltre al vantaggio dal punto di vista della sicurezza, c’è inoltre da considerare l’enorme risparmio di tempo nello sviluppo del codice infrastrutturale. Un esempio? La creazione di una risorsa CodePipeline con relativo repository CodeCommit e stage CodeBuild mi ha richiesto la scrittura di circa 500 righe di codice Terraform; in CDK la parte IAM è di una decina di righe. Impressionante.

Considerazioni finali

AWS CDK è un tool che risolve i problemi di Cloudformation senza perderne le caratteristiche positive, aggiungendo ulteriori vantaggi rispetto ad altri tool. Il suo maggior limite, invece, è nel fatto di poter essere usato, naturalmente, solo su AWS.

Esistono altri tool che utilizzano linguaggi di programmazione per la scrittura di codice infrastrutturale, e che sono disponibili per l’utilizzo su altri cloud provider: ad esempio, Pulumi o cdktf. Tuttavia, questi tool non hanno gli stessi vantaggi, in quanto continuano ad utilizzare chiamate API (quindi non c’è rollback) e a salvare lo stato dell’infrastruttura in appositi file che devono essere gestiti.

La persistenza di queste limitazioni mi ha sempre fatto desistere dall’idea di cambiare tool di Infrastructure as Code perché il cambio di abitudini, paradigma e soprattutto code base mi sembrava non ne valesse la pena. AWS CDK ha invece dei vantaggi tali da considerare seriamente l’abbandono di altri tool.

E voi cosa ne pensate? Avete provato AWS CDK? Considerereste di cambiare tool alla luce dei vantaggi esposti? Fatemelo sapere nei commenti!