
Molti conoscono e utilizzano Terraform nel loro lavoro quotidiano, ma non sono ancora emerse le migliori pratiche. Ogni team deve inventare i propri approcci e metodi.
La tua infrastruttura inizia quasi sicuramente in modo semplice: alcune risorse + qualche sviluppatore. Col tempo, cresce in ogni direzione. Trovi modi per raggruppare risorse in moduli Terraform, organizzare il codice in cartelle, e cosa potrebbe mai andare storto qui? (le famose ultime parole)
Passa del tempo e ti senti come se la tua infrastruttura fosse un nuovo animale domestico, ma perché? Vengono preoccupazioni per cambiamenti inspiegabili nell'infrastruttura, hai paura di toccare l'infrastruttura e il codice — alla fine ritardi nuove funzionalità o abbassi la qualità…
Dopo tre anni di gestione su Github di una collezione di moduli community Terraform per AWS e di un supporto a lungo termine di Terraform in produzione, Anton Babenko è pronto a condividere la sua esperienza: come scrivere moduli TF per evitare futuri dolori.
Entro la fine della presentazione, i partecipanti avranno una comprensione migliore dei principi di gestione delle risorse in Terraform, delle migliori pratiche relative ai moduli in Terraform e alcuni principi di integrazione continua legati alla gestione dell'infrastruttura.
Disclaimer: Voglio notare che questa presentazione è datata novembre 2018 – sono già passati 2 anni. La versione di Terraform trattata nella presentazione, 0.11, non è più supportata. Negli ultimi 2 anni sono stati rilasciati 2 nuove versioni, con numerose novità, miglioramenti e cambiamenti. Vi prego di tenerne conto e di consultare la documentazione.

Link:
- +
- — formattazione automatica del codice e della documentazione
- — generatore di moduli Terraform (WIP)
- — generatore di codice Terraform da diagrammi visivi (WIP)
- www.terraform-best-practices.com
- (I nuovi post si trovano sul sito personale www.antonbabenko.com/)
- @antonbabenko – Twitter, e una miriade di diversi Slacks
Mi chiamo Anton Babenko. Alcuni di voi hanno sicuramente utilizzato il codice che ho scritto. Adesso ne parlerò con maggiore sicurezza che mai, perché ho accesso alle statistiche.
Mi occupo di Terraform e sono un attivo partecipante e contributore in molti progetti open source legati a Terraform e Amazon dal 2015.
Da allora ho scritto abbastanza codice da poterlo presentare in modo interessante. E ora cercherò di raccontarvi a riguardo.
Parlerò delle sottigliezze e delle specificità nell'uso di Terraform. Ma in realtà questo non è un argomento per un HighLoad. E ora capirete perché.
Col passare del tempo ho iniziato a scrivere moduli Terraform. Gli utenti ponevano domande e io le riformulavo. Poi ho scritto diverse utility per formattare il codice utilizzando pre-commit hook, ecc.
Ci sono stati molti progetti interessanti. Mi piace dedicarmi alla generazione di codice, perché mi piace che il computer faccia sempre più lavoro per me e per i programmatori; perciò attualmente sto lavorando a un generatore di codice Terraform a partire da diagrammi visuali. Forse alcuni di voi li hanno visti. Sono scatole belle con frecce. E penso sia fantastico poter premere un pulsante 'Esporta' e ottenere tutto questo come codice.
Vengo dall'Ucraina. Vivo da molti anni in Norvegia.
Inoltre, le informazioni per questa presentazione sono state raccolte da persone che conoscono il mio nome e mi trovano sui social media. Ho quasi sempre lo stesso nickname.

Come ho accennato, sono il maintainer principale dei moduli Terraform AWS, che è uno dei più grandi repository su GitHub, dove ospitiamo moduli per le attività più comuni: VPC, Autoscaling, RDS.

E ciò che avete appena sentito è la base assoluta. Se dubitate di capire cos'è Terraform, sarà meglio passare il vostro tempo altrove. Qui ci saranno molti termini tecnici. E non ho esitato a dichiarare il livello della presentazione come il massimo possibile. Questo significa che posso parlare utilizzando tutti i termini senza particolare spiegazione.

Terraform è nato nel 2014 come uno strumento che permette di scrivere, pianificare e gestire l'infrastruttura come codice. Il concetto chiave qui è "infrastruttura come codice".
Tutta la documentazione, come ho detto, è scritta in . Spero che la maggior parte di voi conosca questo sito e abbia letto la documentazione. Se è così, siete nel posto giusto.

Ecco come appare un normale file di configurazione Terraform, dove iniziamo definendo alcune variabili.

In questo caso definiamo «aws_region».

Poi descriviamo quali risorse vogliamo creare.

Eseguiamo alcuni comandi, in particolare «terraform init» per caricare le dipendenze e i provider.

E lanciamo il comando «terraform apply» per verificare se la configurazione specificata corrisponde alle risorse che abbiamo creato. Poiché non abbiamo creato nulla prima, Terraform ci propone di creare queste risorse.

Confermiamo. In questo modo, creiamo un bucket chiamato seasnail.

Ci sono anche diverse utilità simili. Molti di voi che usano Amazon conoscono AWS CloudFormation, Google Cloud Deployment Manager o Azure Resource Manager. Ognuno di essi ha una propria implementazione per gestire le risorse all'interno di ciascuno di questi provider di cloud pubblico. Terraform è particolarmente utile in quanto consente di gestire oltre 100 provider. (Ulteriori dettagli )

Gli obiettivi che Terraform si è posto sin dall'inizio:
- Terraform fornisce una visione unificata delle risorse.
- Permette di supportare tutte le piattaforme moderne.
- Fin dall'inizio, Terraform è stato concepito come uno strumento per modificare l'infrastruttura in modo sicuro e prevedibile.
Nel 2014, la parola "prevedibile" suonava molto insolita in questo contesto.

Terraform è uno strumento versatile. Se hai un'API, puoi gestire praticamente tutto:
- Puoi utilizzare oltre 120 provider per gestire qualsiasi cosa ti interessi.
- Ad esempio, puoi usare Terraform per descrivere l'accesso ai repository di GitHub.
- Puoi persino creare e chiudere bug in Jira.
- Puoi gestire le metriche di New Relic.
- Puoi persino creare file in Dropbox, se è quello che desideri.
Tutto questo si ottiene attraverso i provider Terraform, che hanno un'API aperta e che possono essere descritti in Go.

Supponiamo che abbiamo iniziato a utilizzare Terraform, abbiamo letto della documentazione sul sito, guardato qualche video e iniziato a scrivere main.tf, come mostrato nelle diapositive precedenti.

E va tutto alla grande, hai creato un file che crea un VPC.
Se desideri creare un VPC, devi specificare circa queste 12 righe. Descrivi in quale regione vuoi crearlo e quale cidr_block di indirizzi IP utilizzare. E tutto qui.

Naturalmente, il progetto crescerà gradualmente.

E voi aggiungerete molte nuove risorse: fonti di dati, vi integrerete con nuovi fornitori, e magari userete Terraform per gestire gli utenti nel vostro account GitHub, e così via. Potreste voler utilizzare diversi fornitori di DNS, mescolando tutto quanto. Terraform facilita tutto ciò.

Consideriamo il seguente esempio.

Aggiungerete gradualmente un internet_gateway, perché volete che le risorse nel vostro VPC abbiano accesso a Internet. È una buona idea.

Il risultato sarà un main.tf come questo:

Questa è la parte superiore di main.tf.

Questa è la parte inferiore di main.tf.
Poi aggiungete una subnet. Quando arriverete a voler aggiungere NAT gateways, routes, routing tables e parecchie altre subnets, non avrete 38 righe, ma circa 200-300 righe.

Cioè, il vostro file main.tf crescerà gradualmente. E molto spesso le persone mettono tutto in un unico file. In main.tf possono esserci 10-20 Kb. Immaginate che 10-20 Kb siano contenuti testuali. E tutto è interconnesso. Lavorarci diventa sempre più complicato. 10-20 Kb è un buon caso d'uso, e può essere anche di più. E non sempre le persone considerano questo un problema.
Come nella programmazione tradizionale, cioè non infrastruttura come codice, siamo abituati a utilizzare un insieme di classi, pacchetti, moduli e raggruppamenti. Terraform consente di fare praticamente la stessa cosa.

- Il codice cresce.
- Anche le dipendenze tra le risorse crescono.

E sorge in noi una grande necessità. Comprendiamo che non possiamo continuare così. Il nostro codice diventa inestricabile. 10-20 Kb non è certo enorme, ma parliamo solo dello stack di rete, cioè avete aggiunto solo risorse di rete. Non stiamo ancora considerando Application Load Balancer, distribuzione del cluster ES, Kubernetes, ecc., dove è facile aggiungere altri 100 Kb. Se scrivete tutto questo, scoprirete presto che Terraform offre moduli Terraform.

I moduli Terraform sono una configurazione Terraform autosufficiente, gestita come un gruppo. Questo è tutto ciò che c'è da sapere sui moduli Terraform. Non sono particolarmente intelligenti, non permettono di fare connessioni complesse a seconda di qualcosa. Tutto questo ricade sulle spalle degli sviluppatori. Cioè, è semplicemente una configurazione Terraform che avete già scritto. E potete semplicemente richiamarla come un gruppo.

In questo modo cerchiamo di capire come ottimizzare i nostri 10-20-30 Kb di codice. Comprendiamo gradualmente che è necessario utilizzare alcuni moduli.
Il primo tipo di moduli che incontriamo sono i moduli di risorsa. Non comprendono quali siano la tua infrastruttura, il tuo business e quali siano le condizioni. Questi sono i moduli che amministro insieme alla comunità open source e che proponiamo come i blocchi di base più iniziali per la tua infrastruttura.

Esempio di modulo di risorsa.

Quando chiamiamo un modulo di risorsa, indichiamo da quale percorso dobbiamo caricare il suo contenuto.

Indichiamo quale versione vogliamo caricare.

Passiamo un sacco di argomenti. E basta. È tutto ciò che dobbiamo sapere quando usiamo questo modulo.

Molti pensano che se usano l'ultima versione, tutto sarà stabile. Ma non è così. L'infrastruttura deve essere versionata, dobbiamo rispondere chiaramente a quale versione è stata distribuita quella o quella componente.

Di seguito il codice all'interno di questo modulo. Modulo security-group. Qui lo scroll arriva fino alla riga 640. Creare una risorsa security-group in Amazon in tutte le possibili configurazioni è un compito molto complesso. Non basta creare semplicemente un security-group e definire quali regole applicare. Questo sarebbe troppo facile. All'interno di Amazon ci sono milioni di diverse limitazioni. Ad esempio, se usi VPC endpoint, prefix list, vari API e cerchi di combinare tutto ciò, Terraform non ti permette di farlo. Né l'API di Amazon lo consente. Pertanto, è necessario nascondere tutta questa logica complessa nel modulo e fornire all'utente un codice che appaia solo in questo modo.

L'utente non deve sapere come è realizzato internamente.

Il secondo tipo di moduli, composto da moduli di risorse, affronta già compiti più applicabili per la tua azienda. Spesso si tratta di uno spazio che funge da estensione per Terraform e stabilisce valori fissi per i tag, in accordo con gli standard aziendali. Qui è possibile aggiungere funzionalità che Terraform attualmente non consente di utilizzare. Questo è il momento attuale. Attualmente la versione è 0.11, che presto diventerà obsoleta. Tuttavia, preprocessori, jsonnet, cookiecutter e una serie di altri strumenti rappresentano i meccanismi di supporto da utilizzare per un funzionamento completo.
Ora mostrerò alcuni esempi a riguardo.

Il modulo infrastrutturale viene invocato esattamente allo stesso modo.

Si specifica la fonte da cui caricare il contenuto.

Viene passato un insieme di valori che vengono forniti a questo modulo.

All'interno di questo modulo vengono invocati diversi moduli di risorse per creare VPC, Load Balancer applicativo, gruppi di sicurezza, o per un cluster Elastic Container Service.

Ci sono due tipi di moduli. È importante comprenderlo, poiché la maggior parte delle informazioni che ho raggruppato in questa presentazione non è scritta nella documentazione.
La documentazione di Terraform attualmente presenta molte difficoltà, poiché indica solo l'esistenza di determinate funzionalità senza spiegare come utilizzarle o il motivo per cui sia preferibile farlo in un certo modo. Di conseguenza, molte persone finiscono per scrivere delle soluzioni che poi si rivelano insostenibili.

Proseguiamo esaminando come scrivere questi moduli. Successivamente, vedremo come richiamarli e come lavorare con il codice.

Terraform Registry —
Consiglio n. 0 – non scrivere moduli per risorse. La maggior parte di questi moduli è già stata creata per te. Come ho già detto, sono open source, non contengono alcuna logica commerciale personale e non hanno valori hardcoded per indirizzi IP, password, ecc. Un modulo è molto flessibile e, probabilmente, esiste già. Ci sono circa 650 moduli per le risorse di Amazon, e la maggior parte di essi è di buona qualità.

In questo esempio, qualcuno è venuto da te e ha detto: «Voglio avere la possibilità di gestire un database. Crea un modulo, così posso creare un database». La persona non conosce i dettagli di implementazione né di Amazon né di Terraform. Sta semplicemente dicendo: «Voglio gestire MSSQL». Cioè, supponiamo che invocherà il nostro modulo, passerà il tipo di motore e indicherà il fuso orario.

E la persona non deve sapere che all'interno di questo modulo creeremo due risorse diverse: una per MSSQL e l'altra per il resto solo perché in Terraform 0.11 non è possibile specificare valori di fuso orario come opzionali.

E all'uscita di questo modulo, la persona avrà semplicemente la possibilità di ottenere un indirizzo. Non saprà da quale database o da quale risorsa stiamo creando tutto questo. Questo è un elemento molto importante di astrazione. E si applica non solo ai moduli pubblici in open source, ma anche a quelli che scriverai nei tuoi progetti e team.

Questo è il secondo argomento, che è piuttosto importante se utilizzi Terraform da un po' di tempo. Hai un repository dove conservi tutti i tuoi moduli Terraform per la tua azienda. Ed è del tutto normale che nel tempo questo progetto cresca fino a una dimensione di uno o due megabyte. Va bene.
Ma il problema è come Terraform richiama questi moduli. Ad esempio, se chiami un modulo per creare ogni singolo utente, Terraform caricherà prima l'intero repository e poi accederà alla cartella dove si trova quel specifico modulo. In questo modo, caricherai ogni volta un megabyte. Se gestisci 100 o 200 utenti, scaricherai 100 o 200 megabyte, e solo dopo accederai a quella cartella. Quindi, naturalmente, non vuoi dover caricare tutto ogni volta che premi "Terraform init".

Ci sono due soluzioni a questo problema. La prima consiste nell'utilizzare percorsi relativi. In questo modo specifichi nel codice che la cartella è locale (./). E prima di avviare qualcosa, esegui un Git clone di questo repository localmente. Così lo fai solo una volta.
Certo, ci sono diversi svantaggi. Ad esempio, non è possibile utilizzare il versioning. E questo a volte può essere difficile da gestire.
La seconda soluzione. Se hai molti sottoprodotti e hai già un pipeline consolidato, esiste un progetto MBT che consente di assemblare molti pacchetti diversi da un monorepository e caricarli su S3. Questo è un metodo molto valido. In questo modo, il file iam-user-1.0.0.zip peserà solo 1 Kb, poiché il codice per generare questa risorsa è molto piccolo. E questo funzionerà in modo molto più veloce.

Parliamo di ciò che non può essere utilizzato nei moduli.

Perché nei moduli è una cattiva idea? La cosa più terribile è l'assunzione dell'utente. L'assunzione dell'utente è una forma di autenticazione nel provider che può essere utilizzata da persone diverse. Ad esempio, tutti noi assumeremo il ruolo. Questo significa che Terraform accetterà questo ruolo. E poi eseguirà le altre azioni con questo ruolo.

Il problema consiste nel fatto che se Vasya ama connettersi ad Amazon in un modo, ad esempio utilizzando una variabile d'ambiente predefinita, mentre Petya preferisce usare la sua chiave condivisa, che tiene in un luogo segreto, in Terraform non si possono specificare entrambe le cose. Affinché non soffrano, non è necessario indicare questo blocco nel modulo. Deve essere specificato a un livello superiore. Cioè, abbiamo un modulo di risorsa, un modulo infrastrutturale e una composizione in cima. E da qualche parte sopra, deve essere quindistabilito.

Il secondo problema riguarda il provisioner. Qui la questione non è così banale, perché se scrivete codice e per voi funziona, potreste pensare che se funziona, non c'è motivo di cambiarlo.

Il problema è che non controllate sempre quando questo provisioner verrà eseguito, in primo luogo. E in secondo luogo, non controllate cosa significhi aws ec2, cioè stiamo parlando ora di Linux o Windows. In questo modo, non potete scrivere qualcosa che funzioni allo stesso modo su diversi sistemi operativi o per diversi casi d'uso.

Il più comune esempio, menzionato anche nella documentazione ufficiale, è che se scrivi aws_instance e specifichi un insieme di argomenti, non c'è nulla di sbagliato nel includere il provisioner «local-exec» e avviare il tuo ansible-playbook.

In realtà – sì, non c'è nulla di sbagliato. Ma presto ti renderai conto che questa cosa del local-exec non esiste, per esempio, in launch_configuration.

E quando usi launch_configuration e desideri creare un autoscaling group da un'istanza, in launch_configuration non c'è il concetto di «provisioner». C'è il concetto di «user data».

Pertanto, una soluzione più universale è utilizzare user data. Questo verrà eseguito o nell'istanza stessa quando l'istanza si accende, oppure in questo stesso user data, quando l'autoscaling group utilizza questa launch_configuration.

Se c'è davvero il desiderio di avviare un provisioner, perché è un componente di collegamento, quando una risorsa viene creata e in quel momento è necessario avviare il proprio provisioner o comando. Ci sono molte situazioni come questa.
E la risorsa più appropriata per questo è chiamata null_resource. Null_resource è una risorsa fittizia che in realtà non viene mai creata. Non tocca nulla, non ha API, non ha autoscaling. Ma consente di regolare quando eseguire un comando. In questo caso, il comando viene eseguito al momento della creazione.

Collegamento
Ci sono diversi segnali. Non mi soffermerò su tutti i segnali in modo molto dettagliato. C'è un articolo su questo. Ma se hai lavorato con Terraform o hai utilizzato moduli altrui, hai spesso notato che molti moduli, come gran parte del codice open source, vengono scritti per esigenze personali. Qualcuno lo ha scritto, ha risolto il proprio problema. L'ha pubblicato su GitHub, lasciando che vivesse. Vivrà, ma se non ci sono documentazione e esempi, nessuno lo utilizzerà. E se non c'è funzionalità che consente di risolvere un po' più della propria specifica esigenza, nessuno lo utilizzerà comunque. Ci sono moltissimi modi per perdere utenti.
Se desideri scrivere qualcosa che le persone vorranno utilizzare, ti consiglio di seguire questi segnali.
Essi sono:
- Documentazione ed esempi.
- Funzionalità completa.
- Valori predefiniti ragionevoli.
- Codice pulito.
- Test.
I test – è una situazione a sé stante, perché è piuttosto difficile scriverli. Io credo di più nella documentazione e negli esempi.

Quindi, abbiamo esaminato come scrivere i moduli. Ci sono due argomenti. Il primo, il più importante, è: non scrivere se puoi, perché molte persone hanno già svolto questi compiti prima di te. E il secondo, se alla fine hai deciso di procedere, cerca di non utilizzare provider nei moduli e nel provisioner.
Questa è la parte grigia della documentazione. Potresti ora pensare: «Non è chiaro. Non mi ha convinto». Ma vediamo tra sei mesi.

Ora parliamo di come invocare questi moduli.
Comprendiamo che nel tempo il nostro codice cresce. Non abbiamo più un solo file, ma ne abbiamo già 20. Tutti si trovano in una sola cartella. O, forse, in cinque cartelle. Potremmo iniziare a dividerli in base alle regioni, ai componenti. Poi ci rendiamo conto che ora abbiamo delle anteprime di sincronizzazione, orchestrazione che devono sorgere. Cioè, dobbiamo capire cosa fare se abbiamo cambiato le risorse di rete, cosa fare con le nostre altre risorse, come invocare queste dipendenze, ecc.

Ci sono due estremi. Il primo estremo è tutto in uno. Abbiamo un file principale. Fino a un certo punto, era considerata la best practice ufficiale sul sito di Terraform.
Ma ora è scritto come deprecato ed è stato rimosso. Nel tempo, la comunità di Terraform ha capito che non si tratta affatto di una best practice, perché le persone iniziano a utilizzare il progetto in modi diversi. E ci sono problemi. Ad esempio, quando indichiamo tutte le dipendenze in un unico posto. Ci sono situazioni in cui clicchiamo su 'Terraform plan' e mentre Terraform aggiorna lo stato di tutte le risorse, può passare molto tempo.
Molto tempo significa, ad esempio, 5 minuti. Per qualcuno, questo è molto tempo. Ho visto casi in cui ci volevano 15 minuti. 15 minuti in cui l'API di AWS interrogava per capire lo stato di ogni risorsa. È un'area molto ampia.
E, naturalmente, si presenterà un problema correlato quando si desidera modificare qualcosa in un punto, poi si aspetta 15 minuti e vi esce un insieme di modifiche. Vi arrendete, scrivete «Yes» e qualcosa va storto. Questo è un esempio molto reale. Terraform non cerca di are da problemi. Cioè, scrivete ciò che volete. Se ci sono problemi, sono i vostri problemi. Fino a Terraform 0.11 non cerca di aiutarvi in alcun modo. In 0.12 ci sono alcuni punti interessanti che vi permettono di dire: «Vasja, lo desideri davvero, vuoi rifletterci?»

Il secondo modo consiste nel ridurre quest'area, cioè è possibile legare meno le chiamate di un posto da un altro.
L'unico problema è che è necessario scrivere più codice, cioè bisogna descrivere variabili in un gran numero di file, aggiornando questo. A qualcuno non piace. Per me va bene. E alcuni pensano: «Perché scriverlo in posti diversi, posso metterlo tutti in un unico posto». Si può fare anche così, ma è un'altra estremità.

Dove vive tutto ciò in un unico posto? Una, due, tre persone, cioè qualcuno lo utilizza.
E chi chiama un singolo componente, un blocco o un modulo infrastrutturale? Cinque o sette persone. È fantastico.

La risposta più comune è che si trova da qualche parte nel mezzo. Se il progetto è grande, spesso ci si trova in una situazione in cui né una soluzione è valida né l'altra funziona completamente, quindi si finisce per mescolare. Non c'è nulla di sbagliato in questo, a patto che si comprenda che ci sono vantaggi in entrambi i casi.

Se c'è stato un cambiamento nello stack VPC e vuoi applicare queste modifiche a EC2, cioè vuoi aggiornare il gruppo di autoscaling perché hai una nuova subnet, questo tipo di dipendenze lo chiamo orchestrazione. Ci sono varie soluzioni: chi come utilizza?
Posso consigliarti quali soluzioni esistono. Puoi usare Terraform per fare magia, oppure usare file make per utilizzare Terraform. E se c'è qualche cambiamento, puoi avviarlo qui.

Come ti sembra questa soluzione? Qualcuno crede che sia una grande soluzione? Vedo un sorriso, forse ci sono dei dubbi.

Certo, non ripetetelo a casa. Terraform non è mai stato creato per essere eseguito da Terraform.
In una presentazione mi è stato detto: «No, questo non funzionerà». Il fatto è che non deve funzionare. Anche se sembra così sorprendente poter lanciare Terraform da Terraform, e poi ancora Terraform, non è necessario farlo. Terraform dovrebbe sempre essere avviato in modo molto semplice.

Se hai bisogno di orchestrare le chiamate quando qualcosa cambia in un unico posto, allora c'è Terragrunt.
Terragrunt è un'utilità, un'estensione di Terraform che consente di coordinare e orchestrare le chiamate ai moduli infrastrutturali.

Un tipico file di configurazione Terraform appare così.

Specifichi quale modulo specifico desideri chiamare.

Quali sono le dipendenze del modulo.

E quali argomenti accetta questo modulo. Questa è tutto ciò che devi sapere su Terragrunt.
C'è documentazione, ci sono 1.700 stelle su GitHub. Ma nella maggior parte dei casi, questo è tutto ciò che c'è da sapere. Ed è molto facile implementarlo in aziende che hanno appena iniziato a lavorare con Terraform.

Quindi, l'orchestrazione è Terragrunt. Ci sono altre opzioni.

Ora parliamo di come lavorare con il codice.
Se hai bisogno di aggiungere nuove funzionalità al codice, nella maggior parte dei casi è semplice. Devi solo scrivere una nuova risorsa, qui è tutto chiaro.

Se hai già una risorsa che hai creato in precedenza, ad esempio, se hai scoperto Terraform dopo aver aperto un account AWS e desideri utilizzare le risorse che hai già, è opportuno ampliare il tuo modulo in modo che supporti l'uso delle risorse esistenti.

E supportare la creazione di nuove risorse utilizzando il blocco risorsa.

In output restituiamo sempre l'output id in base a ciò che è stato utilizzato.

Un altro problema molto significativo in Terraform 0.11 è la gestione delle liste.

La complessità sta nel fatto che se abbiamo una lista di users.

E quando creiamo questi users utilizzando il blocco risorsa, tutto funziona normalmente. Passiamo attraverso l'intera lista, creiamo un file per ognuno. Tutto ok. E poi, ad esempio, se user3, che si trova nel mezzo, deve essere rimosso, tutte le risorse create dopo di lui verranno ricreate, poiché l'indice cambierà.

Lavorare con gli elenchi in un ambiente stateful. Cosa significa un ambiente stateful? È la situazione in cui si genera un nuovo valore quando viene creato questo risorsa. Ad esempio, la AWS Access Key o la AWS Secret Key, cioè quando creiamo un utente, riceviamo una nuova Access o Secret Key. E ogni volta che eliminiamo un utente, questo utente avrà una nuova chiave. Ma non è secondo il feng shui, perché l'utente non vorrà avere a che fare con noi se dobbiamo creare sempre un nuovo utente per lui quando qualcuno lascia il team.

La soluzione è questa. È un codice scritto in Jsonnet. Jsonnet è un linguaggio di creazione di modelli di Google.

Questo comando consente di accettare questo modello e restituisce un file json, che è stato creato secondo il tuo modello.

Il modello appare in questo modo.
Terraform permette di lavorare in modo equivalente sia con HCL che con Json, quindi se hai la possibilità di generare Json, puoi usarlo in Terraform. Un file con estensione .tf.json verrà caricato con successo.

E poi lavoriamo con questo come al solito: terraform init, terraform apply. E creiamo due utenti.
Ora non ci spaventa più se qualcuno lascia il team. Modifichiamo semplicemente il file json. Vasya Pupkin se n'è andato, Petya Pyatochkin è rimasto. Petya Pyatochkin non riceverà una nuova chiave.

L'integrazione di Terraform con altri strumenti non è fondamentalmente un compito per Terraform. Terraform è stato creato come piattaforma per generare risorse e basta. Tutto ciò che arriva dopo non riguarda Terraform. Non c'è bisogno di intrecciarci dentro. C'è Ansible, che fa tutto ciò che serve.
Tuttavia, ci sono situazioni in cui vogliamo integrare Terraform e invocare un comando dopo che qualcosa è stato eseguito.
Primo modo. Creiamo un output, in cui scriviamo questo comando.

E poi invochiamo questo comando dal shell terraform output e indichiamo il valore che desideriamo. In questo modo viene eseguito il comando con tutti i valori sostituiti. È molto comodo.

Secondo modo. Si utilizza null_resource in base alle modifiche nella nostra infrastruttura. Possiamo invocare lo stesso local-exec non appena cambia l'ID di qualche risorsa.

Naturalmente, tutto ciò è fluido sulla carta, perché Amazon, come tutti gli altri provider pubblici, ha un sacco di casi limite.
I casi limite più comuni riguardano il fatto che, quando hai aperto un account AWS, è importante quali regioni utilizzi; se quella funzionalità è attivata; potrebbe essere che tu l'abbia aperto dopo dicembre 2013; potrebbe essere che tu stia utilizzando le impostazioni predefinite in VPC, ecc. Ci sono molte limitazioni. E Amazon le ha disseminate in tutta la documentazione.

Ci sono alcune cose che ti consiglio di evitare.
Per cominciare, evita tutti gli argomenti non segreti all'interno di Terraform plan o Terraform CLI. Puoi raccoglierli in un file tfvars o in una variabile d'ambiente.
Ma non è necessario memorizzare tutto questo comando magico. Terraform plan – var e via. La prima variabile è var, la seconda variabile è var, la terza, quarta. Il principio più importante dell'infrastruttura come codice che utilizzo più spesso è che, semplicemente guardando il codice, dovrei capire perfettamente cosa è stato distribuito, in quale stato si trova e con quali valori. E quindi non ho bisogno di leggere la documentazione o chiedere a Vasya quali parametri ha usato per creare il nostro cluster. Mi basta aprire il file con estensione tfvars, che spesso corrisponde all'ambiente, e vedere tutto lì.
Non dovresti nemmeno utilizzare argomenti target per ridurre il campo d'azione. È molto più semplice utilizzare piccoli moduli infrastrutturali.
Non dovresti né limitare né aumentare il parallelism. Se ho 150 risorse e voglio aumentare il parallelism di Amazon da 10, che è il valore predefinito, a 100, è probabile che qualcosa vada storto. O potrebbe andare bene adesso, ma quando Amazon dirà che stai facendo troppe chiamate, inizieranno i problemi.
Terraform cercherà di riavviare la maggior parte di questi problemi, ma non otterrai praticamente nulla. Parallelism=1 è una cosa importante da utilizzare se ti sei imbattuto in un bug all'interno dell'API di AWS o all'interno del provider di Terraform. E allora devi specificare: parallelism=1 e aspettare che Terraform completi una chiamata, poi la seconda, poi la terza. Le eseguirà in sequenza.
Spesso mi chiedono: «Perché penso che i workspaces di Terraform siano un male?». Credo che il principio dell'infrastruttura come codice consista nel vedere quale infrastruttura è stata creata e con quali valori.
Workspaces è stato creato non per volontà degli utenti. Questo non significa che gli utenti abbiano scritto su GitHub issues che non possono fare a meno dei workspace di Terraform. No, non è così. Terraform Enterprise è una soluzione commerciale. Terraform di HashiCorp ha deciso che avevamo bisogno dei workspace, quindi lo implementeremo. Penso che sia molto più semplice metterlo in una cartella separata. In questo modo avremo un po' più di file, ma sarà più chiaro.

Come lavorare con il codice? In sostanza, lavorare con le liste è l'unico problema. E considerate Terraform in modo più semplice. Non è qualcosa che farà tutto bene per voi. Non dovete inserire tutto ciò che è scritto nella documentazione.

Nel titolo della relazione si parlava di 'futuro'. Ne parlerò brevemente. Per futuro si intende che presto verrà rilasciato 0.12.

0.12 porta un sacco di novità. Se provieni dalla programmazione tradizionale, ti mancano vari blocchi dinamici, cicli e operazioni di confronto corrette e condizionali, dove il lato sinistro e quello destro vengono calcolati non contemporaneamente, ma a seconda della situazione. Ti mancano molto, quindi 0.12 risolverà questo.

Ma! Se scrivi in modo più semplice e utilizzi moduli già pronti e soluzioni di terze parti, non dovrai aspettare e sperare che la versione 0.12 arrivi a sistemare tutto per te.

Grazie per l'intervento! Hai parlato dell'infrastruttura come codice e hai accennato ai test in un'unica parola. Servono test nei moduli? Di chi è la responsabilità? Bisogna scriverli personalmente o è responsabilità dei moduli?
L'anno prossimo sarà pieno di interventi sul fatto che abbiamo deciso di testare tutto. Cosa testare è la domanda più grande. Ci sono molte dipendenze e diverse limitazioni dei vari fornitori. Quando parliamo e tu dici: 'Ho bisogno di test', io chiedo: 'Cosa intendi testare?'. Tu rispondi che testerai nel tuo territorio. Allora io dico che nel mio non funziona. Quindi, nemmeno su questo riusciremo a trovare un accordo. Per non parlare dei numerosi problemi tecnici. Cioè, come si scrivono questi test in modo che siano adeguati.
Sto attivamente esplorando questo tema, ovvero come generare automaticamente test sulla base dell'infrastruttura che hai scritto. In altre parole, se hai scritto questo codice, devo eseguirlo e da questo potrò creare i test.
È una delle librerie più frequentemente citate che consente di scrivere test di integrazione per Terraform. È uno degli strumenti disponibili. Preferisco di più il tipo DSL, ad esempio rspec.
Antonio, grazie per la presentazione! Mi chiamo Valeriy. Permettimi di porre una domanda un po' filosofica. C'è, in un certo senso, provisioning e deployment. Il provisioning crea la mia infrastruttura, nel deployment la riempiamo di contenuti utili, come server, applicazioni, ecc. Nella mia testa, penso che Terraform sia più per il provisioning, mentre Ansible sia più per il deployment, poiché Ansible consente di installare nginx e Postgres anche su infrastrutture fisiche. Tuttavia, Ansible sembra anche in grado di effettuare provisioning, per esempio, di risorse Amazon o Google. Ma Terraform permette anche di deployare software tramite i suoi moduli. Secondo te, c'è una linea di demarcazione tra Terraform e Ansible, dove e cosa sarebbe meglio usare? Oppure, pensi che Ansible sia ormai obsoleto e dovremmo cercare di usare Terraform per tutto?
Ottima domanda, Valery. Ritengo che Terraform dal 2014 non sia cambiato nel suo scopo. È stato creato per l'infrastruttura ed è rimasto per l'infrastruttura. Abbiamo sempre avuto e avremo bisogno di management della configurazione Ansible. La sfida è che ci sono user data all'interno della launch_configuration. E lì chiami Ansible e così via. Questa è la distinzione standard che mi piace di più.
Se parliamo di infrastruttura bella, ci sono strumenti come Packer, che crea quest'immagine. Poi Terraform utilizza il data source per cercare questa immagine e aggiornare la sua launch_configuration. Quindi, il pipeline consiste nel chiamare prima Tracker, poi chiamare Terraform. E se c'è stato un build, avviene una nuova modifica.
Salve! Grazie per la presentazione! Mi chiamo Misha, della compagnia RBS. È possibile chiamare Ansible tramite provisioner durante la creazione di una risorsa. Inoltre, in Ansible esiste una funzione chiamata inventario dinamico. Si può prima eseguire Terraform e poi chiamare Ansible, che prenderà le risorse dallo stato e le eseguirà. Cosa è meglio?
Entrambi gli approcci sono utilizzati con successo da diverse persone. Penso che l'inventario dinamico in Ansible sia utile, a meno che non stiamo parlando di un gruppo di autoscaling. Infatti, per i gruppi di autoscaling abbiamo già il nostro strumento chiamato launch_configuration. In launch_configuration annotiamo tutto ciò che deve essere avviato quando creiamo una nuova risorsa. Quindi, per Amazon, usare un inventario dinamico e leggere il file Terraform ts mi sembra superfluo. Tuttavia, se si utilizzano altri strumenti che non prevedono il concetto di "autoscaling group", ad esempio DigitalOcean o un altro fornitore che non ha gruppi di autoscaling, sarà necessario chiamare manualmente l'API, trovare gli indirizzi IP e generare il file di inventario dinamico su cui Ansible opererà. In altre parole, per Amazon c'è launch_configuration, mentre per tutto il resto esiste l'inventario dinamico.
Fonte: habr.com
