Come professionista del software che gestisce Infrastruttura come Codice (IaC), molto probabilmente hai a che fare spesso con Terraform. Quando aiuti nuovi clienti a utilizzare IaC, è comune semplificare le cose, ma gestire un file di stato Terraform è la prima sfida che incontri. Fondamentalmente, lo stato Terraform contiene informazioni sensibili, che non dovrebbero essere memorizzate dalla gestione del codice sorgente, ma allo stesso tempo non si scala se hai più utenti che lavorano sullo stesso stato Terraform. La risposta a questo problema? Backends.
È importante notare che potresti memorizzare quel file di stato in un bucket S3 e utilizzare DynamoDB per gestire lo stato di blocco. Tuttavia, questo approccio ti costringerà a creare risorse aggiuntive, rendendolo un’opzione complicata, specialmente se il cliente utilizza GitLab. Recentemente, GitLab ha abbassato la barriera all’ingresso per l’integrazione di Terraform fornendo un modo per memorizzare e gestire lo stato Terraform, nonché un modo semplice per impostare un CI (Continuous Integration) intorno ad esso.
In questo articolo, spiegheremo cos’è un file di stato Terraform, come trasferirlo su GitLab e come impostare una pipeline CI per esso. Puoi visitare il nostro repository qui.
Indice
- Cos’è lo Stato Terraform?
- Come far gestire lo Stato Terraform a GitLab
- Come far eseguire il tuo IaC di GitLab attraverso una Pipeline CI
- Suggerimento Bonus: Infracost
- Conclusione
Cos’è lo Stato Terraform?
Terraform registra qualsiasi informazione sull’infrastruttura definita nel tuo codice tramite un file di stato. Scritto in JSON, essenzialmente registra una mappatura dal codice Terraform ai veri e propri risorse creati. Di seguito è riportato un esempio di come apparirebbe un terraform.tfstate
. Principalmente, ogni volta che si esegue Terraform, esso recupera lo stato più recente per la sua istanza EC2 e lo confronta con la configurazione Terraform per determinare quali modifiche devono essere applicate:
{
"version": 4,
"terraform_version": "0.12.0",
"serial": 1,
"lineage": "1f2087f9-4b3c-1b66-65db-8b78faafc6fb",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "example",
"provider": "provider.aws",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0c55b159cbfafe1f0",
"availability_zone": "us-west-2a",
"id": "i-00a123a0accffffff",
"instance_state": "running",
"instance_type": "t2.micro",
"(...)": "(truncated)"
}
}
]
}
]
}
Per impostazione predefinita, questo terraform.tfstate
è memorizzato localmente dove si trovano i file Terraform, si pianifica e si applicano le modifiche. Per un progetto personale dove si stanno solo eseguendo alcuni test, va bene, ma non è il modo raccomandato, ecco perché:
- Memorizzato in un’ubicazione condivisa: Se si ospita questo file di stato sul proprio workstation locale e si deve collaborare con un altro ingegnere, le cose si complicherebbero. Entrambi dovrete assicurarvi di utilizzare la versione più recente dello stato e potreste incorrere in condizioni di gara se eseguite un piano Terraform o un’applicazione contemporaneamente.
- Proteggere le informazioni sensibili: Un file di stato generato può contenere chiavi di crittografia e password dell’infrastruttura. Tuttavia, i file di stato non sono crittografati per impostazione predefinita e memorizzare informazioni sensibili in testo semplice è una cattiva idea.
- Blocco: La maggior parte dei sistemi di controllo versione non supporta alcuna forma di blocco, che impedisce a due membri del team di eseguire Terraform apply simultaneamente sullo stesso file di stato. Questo è un altro motivo per cui non vedremo un file di stato gestito dal controllo delle versioni.
Come ottenere che GitLab gestisca lo stato di Terraform
Dato che Terraform è considerato lo standard nella provisioning di infrastrutture cloud, è passato circa un anno da quando GitLab ha iniziato a offrire un modo per memorizzare e gestire lo stato di Terraform. A questo proposito, abbiamo voluto condividere con voi il processo di migrazione, poiché abbiamo recentemente iniziato ad utilizzare GitLab per gestire il nostro IaC.
Per questo articolo, presumiamo che stiate utilizzando uno stato locale e che abbiate lo stato gestito con un bucket AWS S3 o un’altra soluzione di backend.
In primo luogo, dovrete modificare il vostro backend.tf
per utilizzare HTTP:
terraform {
backend "http" {}
}
Successivamente, dovrete impostare quattro variabili nel vostro terminale:
1. PROJECT_ID
: Potete trovarlo facilmente navigando nel vostro repo sulla pagina “Panoramica del progetto”.
2. TF_USERNAME
: L’username di GitLab che ha accesso al repo su cui state lavorando.
3. TF_PASSWORD
: Token di accesso generato dal vostro account utente di GitLab.
4. TF_ADDRESS
: URL del backend di stato remoto.
PROJECT_ID="28450092"
TF_USERNAME="florianpialoux"
TF_PASSWORD="123456789"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/aws-buckets"
Ora potete eseguire il comando di migrazione che sposterà lo stato di Terraform dalla sua posizione precedente a GitLab con il seguente comando:
terraform init \
-migrate-state \
-backend-config=address=${TF_ADDRESS} \
-backend-config=lock_address=${TF_ADDRESS}/lock \
-backend-config=unlock_address=${TF_ADDRESS}/lock \
-backend-config=username=${TF_USERNAME} \
-backend-config=password=${TF_PASSWORD} \
-backend-config=lock_method=POST \
-backend-config=unlock_method=DELETE \
-backend-config=retry_wait_min=5
Dovrete fornire una conferma con un “sì” in modo che GitLab possa iniziare a gestire il vostro file di stato. Ecco un esempio da uno stato locale a GitLab:
Esempio da S3 a GitLab:

I noticed for some of the state files I had from S3 will be blank even after using the migrate-state
command ran previously. In this case, you can run this:
terraform state pull > aws-buckets.json
Copiate e incollate il contenuto dallo stato S3 ed eseguite un push:
terraform state push -lock=true aws-buckets.json
GitLab supporta la versioning per il tuo file di stato Terraform, ma visualizzare/ripristinare le versioni precedenti tramite l’interfaccia utente web richiederà l’utilizzo di un piano Premium di GitLab. In caso contrario, dovrai effettuare una richiesta API GraphQL.
Come far eseguire a GitLab la tua IaC attraverso una pipeline CI
GitLab fornisce un’immagine Docker che contiene GitLab-Terraform, che è uno script wrapper sottile intorno al binario Terraform ufficiale. In alternativa, potresti utilizzare l’immagine Docker ufficiale di Hashicorp. Puoi trovare maggiori informazioni sull’immagine GitLab Terraform qui.
Una volta che il job di applicazione Terraform viene eseguito, sarai in grado di vedere quando lo stato è stato utilizzato e con quale pipeline.
gitlab-ci.yml
looks like here. Below, are the variables that will need to be defined on the project level.Suggerimento Bonus: Infracost
Come potresti aver notato, osservando il nostro gitlab-ci.yaml
abbiamo aggiunto Infracost, che ci consente di avere maggiore controllo sulle nostre spese cloud poiché ti fornisce una stima dei costi ogni volta che definisci una nuova risorsa per la tua IaC.
Conclusione
Avere il tuo stato Terraform e il CI in esecuzione su Gitlab è un ottimo modo per seguire le best practice di GitOps. Entrambi si combinano perfettamente per sviluppare e distribuire IaC. Poiché molti di voi potrebbero già utilizzare GitLab per i vostri repository, diventa molto più semplice avere la vostra IaC in un’unica piattaforma e lasciare che GitLab gestisca il vostro stato Terraform, supportando l’encryption in transito e a riposo, nonché la versioning, il locking e il unlocking dello stato.
Source:
https://dzone.com/articles/how-to-migrate-terraform-state-to-gitlab-cicd