Come Distribuire Ambienti Multipli nel Tuo Progetto Terraform Senza Duplicare il Codice

L’autore ha selezionato il Fondo Open Source Libero per ricevere una donazione come parte del programma Scrivi per Donazioni.

Introduzione

Terraform offre funzionalità avanzate che diventano sempre più utili man mano che il progetto cresce in dimensione e complessità. È possibile alleviare il costo della manutenzione di definizioni di infrastruttura complesse per più ambienti strutturando il codice in modo da minimizzare le ripetizioni e introducendo flussi di lavoro assistiti da strumenti per un più facile test e deployment.

Terraform associa uno stato con un backend, che determina dove e come lo stato viene memorizzato e recuperato. Ogni stato ha un solo backend e è legato a una configurazione di infrastruttura. Alcuni backend, come local o s3, possono contenere più stati. In tal caso, la coppia di stato e infrastruttura al backend descrive un spazio di lavoro. Gli spazi di lavoro consentono di distribuire più istanze distinte della stessa configurazione di infrastruttura senza doverle memorizzare in backend separati.

In questo tutorial, inizierai deployando più istanze di infrastruttura utilizzando diversi spazi di lavoro. Successivamente, deployerai una risorsa stateful, che in questo tutorial sarà un Volume DigitalOcean. Infine, farai riferimento a moduli predefiniti presenti nel Registro Terraform, che puoi utilizzare per integrare il tuo.

Prerequisiti

Per completare questo tutorial, avrai bisogno di:

  • Un Token di Accesso Personale DigitalOcean, che puoi creare tramite il Pannello di Controllo DigitalOcean. Puoi trovare le istruzioni nei documenti del prodotto DigitalOcean, Come Creare un Token di Accesso Personale.
  • Terraform installato sulla tua macchina locale e un progetto configurato con il provider DO. Completa Passo 1 e Passo 2 del tutorial Come Utilizzare Terraform con DigitalOcean, e assicurati di chiamare la cartella del progetto terraform-advanced, invece di loadbalance. Durante Passo 2, non includere la variabile pvt_key e la risorsa della chiave SSH.

Nota: Questo tutorial è stato specificamente testato con Terraform 1.0.2.

Impiegare più istanze di infrastruttura utilizzando spazi di lavoro

Più spazi di lavoro sono utili quando si desidera distribuire o testare una versione modificata dell’infrastruttura principale senza creare un progetto separato e impostare nuovamente le chiavi di autenticazione. Una volta che hai sviluppato e testato una funzione utilizzando lo stato separato, puoi integrare il nuovo codice nel principale spazio di lavoro e forse eliminare lo stato aggiuntivo. Quando si init un progetto Terraform, indipendentemente dalla backend, Terraform crea un spazio di lavoro chiamato default. È sempre presente e non puoi mai cancellarlo.

Tuttavia, più spazi di lavoro non sono una soluzione adatta per la creazione di ambienti multipli, come per lo staging e la produzione. Perciò, i spazi di lavoro, che tracciano solo lo stato, non memorizzano il codice o le sue modifiche.

Poiché gli spazi di lavoro non tracciano il codice effettivo, dovresti gestire la separazione del codice tra più spazi di lavoro a livello di controllo della versione (VCS) combaciantoli con le loro varianti di infrastruttura. Come puoi ottenere questo dipende dall’strumento VCS stesso; per esempio, in rami Git sarebbe un’astrazione adatta. Per rendere più facile gestire il codice per più ambienti, puoi spezzettarlo in moduli riutilizzabili, in modo da evitare di ripetere lo stesso codice per ciascun ambiente.

Distribuzione delle Risorse negli Spazi di Lavoro

Ora creerai un progetto che distribuisce un Droplet, che applicherai da più spazi di lavoro.

Salverai la definizione del Droplet in un file chiamato droplets.tf.

Supponiamo che tu sia nella directory terraform-advanced, crealo e aprilo per la modifica eseguendo:

  1. nano droplets.tf

Aggiungi le seguenti righe:

resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "web-${terraform.workspace}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

Questa definizione creerà un Droplet che esegue Ubuntu 18.04 con un core CPU e 1 GB di RAM nella regione fra1. Il suo nome conterrà il nome dello spazio di lavoro corrente da cui viene distribuito. Una volta terminato, salva e chiudi il file.

Applicare il progetto per Terraform per eseguire le sue azioni con:

  1. terraform apply -var "do_token=${DO_PAT}"

L’output apparirà simile a questo:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web sarà creato + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-default" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ...

Inserisci yes quando viene richiesto per deployare il Droplet nel workspace default.

Il nome del Droplet sarà web-default, perché il workspace con cui hai iniziato si chiama default. Puoi elencare i workspace per confermare che ne esiste solo uno disponibile:

  1. terraform workspace list

L’output apparirà simile a questo:

Output
* default

L’asterisco (*) significa che hai selezionato quel workspace.

Crea e passa a un nuovo workspace chiamato testing, che userai per deployare un Droplet diverso, eseguendo workspace new:

  1. terraform workspace new testing

L’output apparirà simile a questo:

Output
Created and switched to workspace "testing"! You're now on a new, empty workspace. Workspaces isolate their state, so if you run "terraform plan" Terraform will not see any existing state for this configuration.

Tu pianifichi il deploy del Droplet nuovamente eseguendo:

  1. terraform plan -var "do_token=${DO_PAT}"

L’output sarà simile all’esecuzione precedente:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web sarà creato + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-testing" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ...

Notare che Terraform pianifica di deployare un Droplet chiamato web-testing, che ha denominato diversamente da web-default. Questo perché i workspace default e testing hanno stati creati separatamente e non hanno conoscenza delle risorse l’uno dell’altro, anche se provengono dallo stesso codice.

Per confermare di essere nel workspace testing, mostra il workspace corrente eseguendo workspace show:

  1. terraform workspace show

L’output sarà il nome del workspace corrente:

Output
testing

Per eliminare un workspace, è necessario innanzitutto distruggere tutte le risorse distribuite al suo interno. Successivamente, se è attivo, è necessario passare a un altro utilizzando workspace select. Dato che il workspace testing qui è vuoto, puoi passare direttamente a default:

  1. terraform workspace select default

Riceverai l’output di Terraform che conferma il cambiamento:

Output
Switched to workspace "default".

Puoi poi eliminarlo eseguendo workspace delete:

  1. terraform workspace delete testing

Terraform eseguirà quindi l’eliminazione:

Output
Deleted workspace "testing"!

Puoi distruggere il Droplet distribuito nel workspace default eseguendo:

  1. terraform destroy -var "do_token=${DO_PAT}"

Digitare yes quando richiesto per completare il processo.

In questa sezione, hai lavorato in più workspace di Terraform. Nella prossima sezione, deployerai una risorsa con stato.

Deploying Stateful Resources

Le risorse senza stato non memorizzano dati, quindi puoi crearle e sostituirle rapidamente, poiché non sono uniche. Le risorse con stato, invece, contengono dati unici o non semplicemente ricreatibili; quindi, richiedono uno storage di dati persistente.

Dato che potresti finire per distruggere tali risorse, o più risorse richiedono i loro dati, è meglio memorizzarli in un’entità separata, come DigitalOcean Volumes.

I volumi forniscono spazio di archiviazione aggiuntivo. Possono essere collegati ai Droplet (server), ma sono separati da essi. In questo passaggio, definirai il Volume e lo collegherai a un Droplet in droplets.tf.

Apriilo per la modifica:

  1. nano droplets.tf

Aggiungi le seguenti righe:

resource "digitalocean_droplet" "web" {
  image  = "ubuntu-18-04-x64"
  name   = "web-${terraform.workspace}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

resource "digitalocean_volume" "volume" {
  region                  = "fra1"
  name                    = "new-volume"
  size                    = 10
  initial_filesystem_type = "ext4"
  description             = "New Volume for Droplet"
}

resource "digitalocean_volume_attachment" "volume_attachment" {
  droplet_id = digitalocean_droplet.web.id
  volume_id  = digitalocean_volume.volume.id
}

Qui definisci due nuove risorse, il Volume stesso e un allegato del Volume. Il Volume sarà di 10GB, formattato come ext4, chiamato new-volume e situato nella stessa regione del Droplet. Dato che il Volume e il Droplet sono entità separate, dovrai definire un oggetto di allegato del Volume per collegarli. volume_attachment prende gli ID del Droplet e del Volume e istruisce il cloud DigitalOcean per rendere il Volume disponibile al Droplet come un dispositivo disco.

Una volta terminato, salva e chiudi il file.

Pianifica questa configurazione eseguendo:

  1. terraform plan -var "do_token=${DO_PAT}"

Le azioni che Terraform pianificherà saranno le seguenti:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # digitalocean_droplet.web verrà creato + resource "digitalocean_droplet" "web" { + backups = false + created_at = (known after apply) + disk = (known after apply) + id = (known after apply) + image = "ubuntu-18-04-x64" + ipv4_address = (known after apply) + ipv4_address_private = (known after apply) + ipv6 = false + ipv6_address = (known after apply) + ipv6_address_private = (known after apply) + locked = (known after apply) + memory = (known after apply) + monitoring = false + name = "web-default" + price_hourly = (known after apply) + price_monthly = (known after apply) + private_networking = (known after apply) + region = "fra1" + resize_disk = true + size = "s-1vcpu-1gb" + status = (known after apply) + urn = (known after apply) + vcpus = (known after apply) + volume_ids = (known after apply) + vpc_uuid = (known after apply) } # digitalocean_volume.volume verrà creato + resource "digitalocean_volume" "volume" { + description = "New Volume for Droplet" + droplet_ids = (known after apply) + filesystem_label = (known after apply) + filesystem_type = (known after apply) + id = (known after apply) + initial_filesystem_type = "ext4" + name = "new-volume" + region = "fra1" + size = 10 + urn = (known after apply) } # digitalocean_volume_attachment.volume_attachment verrà creato + resource "digitalocean_volume_attachment" "volume_attachment" { + droplet_id = (known after apply) + id = (known after apply) + volume_id = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. ...

Dettagli di output che Terraform creerà un Droplet, un Volume e un Allegato del Volume, che collega il Volume al Droplet.

Ora hai definito e collegato un Volume (una risorsa con stato) a un Droplet. Nella prossima sezione, esaminerai moduli Terraform pubblici e preconfezionati che puoi incorporare nel tuo progetto.

Riferimento a moduli prefabbricati

Oltre a creare i propri moduli personalizzati per i propri progetti, è anche possibile utilizzare moduli e provider prefabbricati da altri sviluppatori, che sono disponibili pubblicamente su Terraform Registry.

Nella sezione moduli puoi cercare nel database dei moduli disponibili e ordinare per fornitore per trovare il modulo con la funzionalità necessaria. Una volta trovato, puoi leggere la sua descrizione, che elenca le input e le output fornite dal modulo, nonché le sue dipendenze esterni di modulo e provider.

Ora aggiungerai il modulo chiave SSH DigitalOcean al tuo progetto. Salverai il codice separato dalle definizioni esistenti in un file chiamato ssh-key.tf. Lo crei e aprilo in modo da modificarlo eseguendo:

  1. nano ssh-key.tf

Aggiungi le seguenti righe:

module "ssh-key" {
  source         = "clouddrove/ssh-key/digitalocean"
  key_path       = "~/.ssh/id_rsa.pub"
  key_name       = "new-ssh-key"
  enable_ssh_key = true
}

Questo codice definisce un’istanza del modulo clouddrove/droplet/digitalocean dal registro e imposta alcuni parametri che offre. Dovrebbe aggiungere una chiave SSH pubblica al tuo account leggendola da ~/.ssh/id_rsa.pub.

Una volta fatto, salva e chiudi il file.

Prima di pianificare questo codice, devi scaricare il modulo citato eseguendo:

  1. terraform init

riceverai output simile a questo:

Output
Initializing modules... Downloading clouddrove/ssh-key/digitalocean 0.13.0 for ssh-key... - ssh-key in .terraform/modules/ssh-key Initializing the backend... Initializing provider plugins... - Reusing previous version of digitalocean/digitalocean from the dependency lock file - Using previously-installed digitalocean/digitalocean v2.10.1 Terraform has been successfully initialized! ...

Ora puoi pianificare i cambiamenti del codice:

  1. terraform plan -var "do_token=${DO_PAT}"

riceverai output simile a questo:

Output
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: ... # module.ssh-key.digitalocean_ssh_key.default[0] will be created + resource "digitalocean_ssh_key" "default" { + fingerprint = (known after apply) + id = (known after apply) + name = "devops" + public_key = "ssh-rsa ... demo@clouddrove" } Plan: 4 to add, 0 to change, 0 to destroy. ...

L’output mostra che creerai la risorsa chiave SSH, che significa che hai scaricato e richiamato il modulo dal tuo codice.

Conclusione

Progetti più grandi possono utilizzare alcune funzionalità avanzate di Terraform per ridurre la complessità e facilitare il mantenimento. I workspace ti consentono di testare nuove aggiunte al tuo codice senza toccare le distribuzioni principali stabili. Puoi anche abbinare i workspace a un sistema di controllo di versione per tracciare i cambiamenti al codice. L’utilizzo di moduli pronti può anche abbreviare il tempo di sviluppo, ma potrebbe comportare costi aggiuntivi o tempi prolungati in futuro se il modulo diventa obsoleto.

Questo tutorial fa parte della serie Come gestire l’infrastruttura con Terraform. La serie copre una serie di argomenti di Terraform, dalla prima installazione di Terraform a gestire progetti complessi.

Source:
https://www.digitalocean.com/community/tutorials/how-to-deploy-multiple-environments-with-workspaces-in-your-terraform-project