Perché usiamo Terraform e non Chef, Puppet, Ansible, SaltStack o CloudFormation

Update, November 17, 2016: Abbiamo preso questa serie di post sul blog, l’abbiamo ampliata e trasformata in un libro chiamato Terraform: Up& In esecuzione!

Update, July 8, 2019: Abbiamo aggiornato questa serie di post del blog per Terraform 0.12 e rilasciato la 2nd edition di Terraform: Up & In esecuzione!

Questa è la parte 1 della Guida completa alla serie Terraform. Nell’introduzione alla serie, abbiamo discusso perché ogni azienda dovrebbe utilizzare infrastructure-as-code (IAC). In questo post, stiamo andando a discutere il motivo per cui abbiamo scelto Terraform come il nostro strumento IAC di scelta.

Se cerchi in Internet “infrastructure-as-code”, è abbastanza facile trovare un elenco degli strumenti più popolari:

  • Chef
  • Puppet
  • Ansible
  • SaltStack
  • CloudFormation
  • Terraform

Ciò che non è facile è capire quale di questi dovresti usare. Tutti questi strumenti possono essere utilizzati per gestire l’infrastruttura come codice. Tutti sono open source, supportati da grandi comunità di contributori e lavorano con molti fornitori di cloud diversi (con la notevole eccezione di CloudFormation, che è closed source e solo AWS). Tutti offrono supporto aziendale. Tutti sono ben documentati, sia in termini di documentazione ufficiale che di risorse comunitarie come post di blog e domande StackOverflow. Così come si fa a decidere?

Ciò che rende questo ancora più difficile è che la maggior parte dei confronti che trovi online tra questi strumenti non fa altro che elencare le proprietà generali di ciascun strumento e farlo sembrare come se potessi avere altrettanto successo con uno di essi. E mentre questo è tecnicamente vero, non è utile. È un po ‘ come dire a un principiante della programmazione che potresti avere altrettanto successo nella costruzione di un sito Web con PHP, C o Assembly — una dichiarazione tecnicamente vera, ma che omette un’enorme quantità di informazioni che sarebbero incredibilmente utili nel prendere una buona decisione.

In questo post, stiamo andando a tuffarsi in alcuni motivi molto specifici per cui abbiamo scelto Terraform rispetto agli altri strumenti IAC. Come per tutte le decisioni tecnologiche, è una questione di compromessi e priorità, e mentre le tue priorità particolari possono essere diverse dalle nostre, speriamo che condividere il nostro processo di pensiero ti aiuti a prendere la tua decisione. Ecco i principali compromessi che abbiamo considerato:

  • la Gestione della Configurazione vs Provisioning
  • Mutevole Infrastrutture vs Immutabile Infrastrutture
  • Procedurale vs Dichiarativa
  • Master vs senza padrone
  • Agente vs Agentless
  • Grande Comunità vs Piccola Comunità
  • Mature vs Taglio Bordo
  • Utilizzo di Più Strumenti Insieme

Chef, Puppet, Ansible, e SaltStack sono tutti strumenti di gestione della configurazione, il che significa che essi sono progettati per installare e gestire il software su server esistenti. CloudFormation e Terraform sono strumenti di provisioning, il che significa che sono progettati per eseguire il provisioning dei server stessi (così come il resto dell’infrastruttura, come bilanciamento del carico, database, configurazione di rete, ecc.), lasciando il compito di configurare tali server ad altri strumenti. Queste due categorie non si escludono a vicenda, poiché la maggior parte degli strumenti di gestione della configurazione può eseguire un certo grado di provisioning e la maggior parte degli strumenti di provisioning può eseguire un certo grado di gestione della configurazione. Ma l’attenzione sulla gestione della configurazione o provisioning significa che alcuni degli strumenti stanno per essere una misura migliore per alcuni tipi di attività.

In particolare, abbiamo scoperto che se si utilizza Docker o Packer, la stragrande maggioranza delle esigenze di gestione della configurazione sono già state curate. Con Docker e Packer, è possibile creare immagini (come contenitori o immagini di macchine virtuali) con tutto il software necessario al server già installato e configurato. Una volta che hai una tale immagine, tutto ciò che serve è un server per eseguirlo. E se tutto ciò che devi fare è eseguire il provisioning di un gruppo di server, uno strumento di provisioning come Terraform sarà in genere più adatto di uno strumento di gestione della configurazione (ecco un esempio di come utilizzare Terraform per distribuire Docker su AWS).

Infrastruttura mutabile vs infrastruttura immutabile

Strumenti di gestione della configurazione come Chef, Puppet, Ansible e SaltStack in genere predefiniti per un paradigma di infrastruttura mutabile. Ad esempio, se dici a Chef di installare una nuova versione di OpenSSL, verrà eseguito l’aggiornamento del software sui server esistenti e le modifiche avverranno sul posto. Nel corso del tempo, man mano che si applicano sempre più aggiornamenti, ogni server crea una cronologia unica delle modifiche. Questo spesso porta a un fenomeno noto come deriva di configurazione, in cui ogni server diventa leggermente diverso da tutti gli altri, portando a bug di configurazione sottili che sono difficili da diagnosticare e quasi impossibili da riprodurre.

Se si utilizza uno strumento di provisioning come Terraform per distribuire immagini macchina create da Docker o Packer, ogni “modifica” è in realtà una distribuzione di un nuovo server (proprio come ogni “modifica” a una variabile nella programmazione funzionale restituisce effettivamente una nuova variabile). Ad esempio, per distribuire una nuova versione di OpenSSL, si creerebbe una nuova immagine utilizzando Packer o Docker con la nuova versione di OpenSSL già installata, distribuire quell’immagine su un set di server totalmente nuovi e quindi annullare i vecchi server. Questo approccio riduce la probabilità di bug di deriva della configurazione, rende più facile sapere esattamente quale software è in esecuzione su un server e consente di distribuire banalmente qualsiasi versione precedente del software in qualsiasi momento. Naturalmente, è possibile forzare anche gli strumenti di gestione della configurazione a eseguire distribuzioni immutabili, ma non è l’approccio idiomatico per tali strumenti, mentre è un modo naturale per utilizzare gli strumenti di provisioning.

Procedurale vs Dichiarativo

Chef e Ansible incoraggiano uno stile procedurale in cui si scrive codice che specifica, passo dopo passo, come ottenere uno stato finale desiderato. Terraform, CloudFormation, SaltStack e Puppet incoraggiano tutti uno stile più dichiarativo in cui si scrive codice che specifica lo stato finale desiderato e lo strumento IAC stesso è responsabile di capire come raggiungere tale stato.

Ad esempio, supponiamo che tu voglia distribuire 10 server (“Istanze EC2” in AWS gergo) per eseguire v1 di un’app. Qui è un esempio semplificato di un Ansible modello che fa questo con un approccio procedurale:

- ec2:
count: 10
image: ami-v1
instance_type: t2.micro

E questo è un esempio semplificato di un Terraforma modello che fa la stessa cosa usando un approccio dichiarativo:

resource "aws_instance" "example" {
count = 10
ami = "ami-v1"
instance_type = "t2.micro"
}

Ora in superficie, questi due approcci possono sembrare simili, e quando inizialmente si esegue, con Ansible o Terraforma, essi producono risultati simili. La cosa interessante è cosa succede quando si vuole fare un cambiamento.

Ad esempio, immagina che il traffico sia aumentato e che tu voglia aumentare il numero di server a 15. Con Ansible, il codice procedurale che hai scritto in precedenza non è più utile; se hai appena aggiornato il numero di server a 15 e reran quel codice, distribuirebbe 15 nuovi server, dandoti 25 in totale! Quindi, invece, devi essere consapevole di ciò che è già distribuito e scrivere uno script procedurale completamente nuovo per aggiungere i 5 nuovi server:

- ec2:
count: 5
image: ami-v1
instance_type: t2.micro

Con il codice dichiarativo, poiché tutto ciò che fai è dichiarare lo stato finale che vuoi, e Terraform capisce come arrivare a quello stato finale, Terraform sarà anche a conoscenza di qualsiasi stato creato in passato. Pertanto, per distribuire altri 5 server, tutto ciò che devi fare è tornare allo stesso modello Terraform e aggiornare il conteggio da 10 a 15:

resource "aws_instance" "example" {
count = 15
ami = "ami-v1"
instance_type = "t2.micro"
}

Se hai eseguito questo modello, Terraform si renderebbe conto che aveva già creato 10 server e quindi che tutto ciò che doveva fare era creare 5 nuovi server. Infatti, prima di eseguire questo modello, è possibile utilizzare il comando plan di Terraform per visualizzare in anteprima le modifiche apportate:

$ terraform plan+ aws_instance.example.11
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.12
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.13
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.14
ami: "ami-v1"
instance_type: "t2.micro"+ aws_instance.example.15
ami: "ami-v1"
instance_type: "t2.micro"Plan: 5 to add, 0 to change, 0 to destroy.

Ora cosa succede quando si desidera distribuire v2 il servizio? Con l’approccio procedurale, entrambi i precedenti modelli Ansible non sono ancora utili, quindi devi scrivere un altro modello per rintracciare i server 10 che hai distribuito in precedenza (o era 15 ora?) e aggiornare attentamente ciascuno alla nuova versione. Con l’approccio dichiarativo di Terraform, si torna nuovamente allo stesso modello e si modifica semplicemente il numero di versione ami in v2:

resource "aws_instance" "example" {
count = 15
ami = "ami-v2"
instance_type = "t2.micro"
}

Ovviamente, gli esempi precedenti sono semplificati. Ansible ti consente di utilizzare i tag per cercare le istanze EC2 esistenti prima di distribuirne di nuove (ad esempio utilizzando i parametri instance_tags e count_tag), ma dover calcolare manualmente questo tipo di logica per ogni singola risorsa che gestisci con Ansible, in base alla cronologia passata di ogni risorsa, può essere sorprendentemente complicato trovare istanze esistenti non solo per tag, ma anche versione dell’immagine, zona di disponibilità, ecc.). Ciò evidenzia due problemi principali con gli strumenti procedurali IAC:

  1. Quando si tratta di codice procedurale, lo stato dell’infrastruttura non è completamente catturato nel codice. Leggere i tre modelli Ansible che abbiamo creato sopra non è sufficiente per sapere cosa viene distribuito. Dovresti anche conoscere l’ordine in cui abbiamo applicato quei modelli. Se li avessimo applicati in un ordine diverso, potremmo finire con un’infrastruttura diversa, e questo non è qualcosa che puoi vedere nella base di codice stessa. In altre parole, per ragionare su un codice Ansible o Chef, devi conoscere la storia completa di ogni cambiamento che sia mai accaduto.
  2. La riusabilità del codice procedurale è intrinsecamente limitata perché è necessario tenere conto manualmente dello stato corrente della base di codice. Poiché tale stato è in continua evoluzione, il codice utilizzato una settimana fa potrebbe non essere più utilizzabile perché è stato progettato per modificare uno stato dell’infrastruttura che non esiste più. Di conseguenza, le basi di codice procedurali tendono a diventare grandi e complicate nel tempo.

D’altra parte, con il tipo di approccio dichiarativo utilizzato in Terraform, il codice rappresenta sempre lo stato più recente della tua infrastruttura. A colpo d’occhio, puoi dire cosa è attualmente distribuito e come è configurato, senza doverti preoccupare della cronologia o dei tempi. Ciò semplifica anche la creazione di codice riutilizzabile, in quanto non è necessario tenere conto manualmente dello stato attuale del mondo. Invece, ti concentri solo sulla descrizione dello stato desiderato e Terraform capisce come passare automaticamente da uno stato all’altro. Di conseguenza, le basi di codice Terraform tendono a rimanere piccole e facili da capire.

Naturalmente, ci sono anche aspetti negativi delle lingue dichiarative. Senza l’accesso a un linguaggio di programmazione completo, la tua potenza espressiva è limitata. Ad esempio, alcuni tipi di modifiche all’infrastruttura, come una distribuzione rolling, zero-downtime, sono difficili da esprimere in termini puramente dichiarativi. Allo stesso modo, senza la capacità di fare “logica” (ad esempio if-statements, loop), la creazione di codice generico e riutilizzabile può essere complicata (specialmente in CloudFormation). Fortunatamente, Terraform fornisce una serie di potenti primitive, come variabili di input, variabili di output, moduli, create_before_destroy e count, che consentono di creare codice pulito, configurabile e modulare anche in un linguaggio dichiarativo. Discuteremo di questi strumenti più nella Parte 4, Come creare un’infrastruttura riutilizzabile con i moduli Terraform e nella Parte 5, Terraform tips & trucchi: loop, if-statements e insidie.

Master Versus Masterless

Per impostazione predefinita, Chef, Puppet e SaltStack richiedono l’esecuzione di un server master per memorizzare lo stato dell’infrastruttura e distribuire gli aggiornamenti. Ogni volta che si desidera aggiornare qualcosa nella propria infrastruttura, si utilizza un client (ad esempio, uno strumento da riga di comando) per emettere nuovi comandi al server master e il server master spinge gli aggiornamenti a tutti gli altri server o quei server estraggono gli ultimi aggiornamenti dal server master su base regolare.

Un server master offre alcuni vantaggi. Innanzitutto, è un unico luogo centrale in cui puoi vedere e gestire lo stato della tua infrastruttura. Molti strumenti di gestione della configurazione forniscono anche un’interfaccia Web (ad esempio, la Console Chef, Puppet Enterprise Console) per il server master per rendere più facile vedere cosa sta succedendo. In secondo luogo, alcuni server master possono essere eseguiti continuamente in background e applicare la configurazione. In questo modo, se qualcuno effettua una modifica manuale su un server, il server master può ripristinare tale modifica per impedire la deriva della configurazione.

Tuttavia, dover eseguire un server master presenta alcuni gravi inconvenienti:

  • Infrastruttura extra: è necessario distribuire un server aggiuntivo, o anche un cluster di server aggiuntivi (per alta disponibilità e scalabilità), solo per eseguire il master.
  • Manutenzione: è necessario mantenere, aggiornare, eseguire il backup, monitorare e scalare i server master.
  • Sicurezza: è necessario fornire un modo per il client di comunicare con i server master e un modo per i server master di comunicare con tutti gli altri server, il che in genere significa aprire porte aggiuntive e configurare sistemi di autenticazione aggiuntivi, il che aumenta la superficie per gli aggressori.

Chef, Puppet e SaltStack hanno diversi livelli di supporto per le modalità masterless in cui è sufficiente eseguire il loro software agente su ciascuno dei server, in genere su una pianificazione periodica (ad esempio, un lavoro cron che viene eseguito ogni 5 minuti) e utilizzarlo per estrarre gli ultimi aggiornamenti dal controllo della versione (piuttosto che da un server master). Ciò riduce significativamente il numero di parti in movimento, ma, come discusso nella sezione successiva, questo lascia ancora una serie di domande senza risposta, in particolare su come eseguire il provisioning dei server e installare il software agent su di essi in primo luogo.

Ansible, CloudFormation, Heat e Terraform sono tutti masterless per impostazione predefinita. Oppure, per essere più precisi, alcuni di loro possono fare affidamento su un server master, ma è già parte dell’infrastruttura che stai utilizzando e non un pezzo in più che devi gestire. Ad esempio, Terraform comunica con i provider cloud utilizzando le API del provider cloud, quindi in un certo senso i server API sono server master, tranne che non richiedono alcuna infrastruttura aggiuntiva o meccanismi di autenticazione aggiuntivi (ad esempio, basta usare le chiavi API). Ansible funziona collegandosi direttamente a ciascun server tramite SSH, quindi, ancora una volta, non è necessario eseguire alcuna infrastruttura aggiuntiva o gestire meccanismi di autenticazione aggiuntivi (ad esempio, basta usare le chiavi SSH).

Agent Versus Agentless

Chef, Puppet e SaltStack richiedono tutti di installare il software agent (ad esempio, Chef Client, Puppet Agent, Salt Minion) su ogni server che si desidera configurare. L’agente viene in genere eseguito in background su ciascun server ed è responsabile dell’installazione degli ultimi aggiornamenti di gestione della configurazione.

Questo ha alcuni inconvenienti:

  • Bootstrap: Come si esegue il provisioning dei server e si installa il software agent su di essi in primo luogo? Alcuni strumenti di gestione della configurazione calcio può essere giù per la strada, assumendo alcune processo esterno che si prenderà cura di questo per loro (ad esempio, si utilizza prima di Modicare la distribuzione di un gruppo di server con una VM immagine che ha l’agente già installato); altri strumenti di gestione della configurazione hanno un particolare processo che si sta avviando in cui si esegue una tantum comandi a disposizione il server utilizzando il provider di servizi cloud Api e installare il software dell’agente su i server tramite SSH.
  • Manutenzione: È necessario aggiornare con attenzione il software agente su base periodica, facendo attenzione a tenerlo in sincronia con il server master se ce n’è uno. Devi anche monitorare il software dell’agente e riavviarlo se si blocca.
  • Sicurezza: se il software agent elimina la configurazione da un server master (o da un altro server se non si utilizza un master), è necessario aprire le porte in uscita su ogni server. Se il server master invia la configurazione all’agente, è necessario aprire le porte in entrata su ogni server. In entrambi i casi, devi capire come autenticare l’agente sul server con cui sta parlando. Tutto questo aumenta la superficie per gli aggressori.

Ancora una volta, Chef, Puppet e SaltStack hanno diversi livelli di supporto per le modalità agentless (ad esempio, salt-ssh), ma spesso si sentono come se fossero stati attaccati come un ripensamento e non sempre supportano l’intero set di funzionalità dello strumento di gestione della configurazione. Ecco perché in natura, la configurazione predefinita o idiomatica per Chef, Puppet e SaltStack include quasi sempre un agente e di solito anche un master.

Tutte queste parti mobili aggiuntive introducono un gran numero di nuove modalità di guasto nell’infrastruttura. Ogni volta che si ottiene un bug report alle 3 del mattino, si dovrà capire se è un bug nel codice dell’applicazione, o il vostro IAC codice, o la gestione della configurazione del client o il server master(s), o il modo in cui il client si racconta al master server(s), o il modo in cui altri server parlare al server master(s), o…

Ansible, CloudFormation, Calore, e Terraforma non richiede l’installazione di alcun extra agenti. Oppure, per essere più precisi, alcuni di essi richiedono agenti, ma in genere sono già installati come parte dell’infrastruttura che si sta utilizzando. Ad esempio, AWS, Azure, Google Cloud e tutti gli altri provider cloud si occupano dell’installazione, della gestione e dell’autenticazione del software dell’agente su ciascuno dei loro server fisici. Come utente di Terraform, non devi preoccuparti di nulla di tutto ciò: emetti solo comandi e gli agenti del provider cloud li eseguono per te su tutti i tuoi server. Con Ansible, i tuoi server devono eseguire
il demone SSH, che è comune per l’esecuzione sulla maggior parte dei server comunque.

Grande comunità vs Piccola Comunità

Ogni volta che si sceglie una tecnologia, si sta anche raccogliendo una comunità. In molti casi, l’ecosistema attorno al progetto può avere un impatto maggiore sulla tua esperienza rispetto alla qualità intrinseca della tecnologia stessa. La community determina quante persone contribuiscono al progetto, quanti plug-in, integrazioni ed estensioni sono disponibili, quanto è facile trovare aiuto online (ad esempio, post di blog, domande su StackOverflow) e quanto è facile assumere qualcuno che ti aiuti (ad esempio, un dipendente, un consulente o un’azienda di supporto).

È difficile fare un confronto accurato tra le comunità, ma puoi individuare alcune tendenze cercando online. La seguente tabella mostra un confronto popolare IAC strumenti, con i dati che ho raccolto durante il mese di Maggio 2019, tra cui se l’IAC strumento open source o closed source, cosa che i fornitori di cloud supporta, il numero totale di collaboratori e di stelle su GitHub, come molti si impegna e attiva i problemi ci sono stati più di un mese, nel periodo che va da metà aprile a metà Maggio, come molte librerie open source sono disponibili per lo strumento, il numero di domande per tale strumento su StackOverflow, e il numero di posti di lavoro che parlare lo strumento Indeed.com.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *