Hoe om Terraform State te migreren naar GitLab CI/CD

Als een softwareprofessional die zich bezighoudt met Infrastructure as Code (IaC), heb je waarschijnlijk veel te maken met Terraform. Bij het helpen van nieuwe klanten met IaC is het gebruikelijk om dingen te vereenvoudigen, maar het beheren van een Terraform state-bestand is de eerste uitdaging die je tegenkomt. In wezen bevat Terraform state gevoelige informatie, die niet bewaard zou moeten worden door broncodebeheer, maar tegelijkertijd is het niet schaalbaar als je meerdere gebruikers hebt die werken aan hetzelfde Terraform state. De oplossing hiervoor? Backends.

Het is belangrijk op te merken dat je dat state-bestand op een S3-bucket zou kunnen opslaan en DynamoDB gebruiken om de lock-state te beheren. Dit zal echter ervoor zorgen dat je extra resources moet aanmaken, wat het een ingewikkelde optie maakt, vooral als de klant GitLab gebruikt. GitLab heeft onlangs de toegangspoort tot het integreren van Terraform verlaagd door een manier te bieden om Terraform state te bewaren en te beheren, evenals een eenvoudige manier om een CI hieromheen op te zetten.

In dit artikel leggen we uit wat een Terraform state-bestand is, hoe je het kunt migreren naar GitLab en hoe je een CI-pijplijn eromheen kunt instellen. Je kunt onze repository bezoeken hier.

Inhoudsopgave

  • Wat Is Terraform State?
  • Hoe GitLab Terraform State Te Beheren
  • Hoe GitLab Je IaC Te Laten Lopen Door Een CI-Pijplijn
    • Bonus Tip: Infracost
  • Conclusie

Wat Is Terraform State?

Terraform registreert informatie over de infrastructuur die is gedefinieerd in uw code via een statebestand. Geschreven in JSON, registreert het in wezen een toewijzing van de Terraform-code naar de daadwerkelijk gemaakte resources. Hieronder vindt u een voorbeeld van hoe een terraform.tfstate eruit zou kunnen zien. Voornamelijk, elke keer dat u Terraform uitvoert, haalt het de meest recente status voor zijn EC2-instantie op en vergelijkt deze met uw Terraform-configuratie om te bepalen welke wijzigingen moeten worden toegepast:

 

{   
     "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)"           
            }         
          }       
        ]      
      }   
    ]  
 }

Standaard wordt dit terraform.tfstate lokaal opgeslagen waar u uw Terraform-bestanden, -plannen en -wijzigingen uitvoert. Voor een persoonlijk project waar u gewoon wat tests uitvoert, is het prima, maar niet aanbevolen, en hier is de reden:

  • Opgeslagen in een gedeelde locatie: als u dit statebestand op uw lokale werkstation zou hosten en met een andere engineer zou moeten werken, wordt het ingewikkeld. Beiden moeten ervoor zorgen dat ze de meest recente versie van de staat gebruiken en u zou race-condities kunnen tegenkomen als u tegelijkertijd een Terraform-plan of -apply uitvoert.
  • Bescherm gevoelige informatie: Een gegenereerd statebestand kan versleutelingssleutels en infrastructuurwachtwoorden bevatten. Echter, statebestanden worden standaard niet versleuteld en het opslaan van gevoelige informatie in plain text is geen goed idee.
  • Locking: De meeste versiebeheersystemen ondersteunen geen vorm van vergrendeling, waardoor twee teamleden niet tegelijkertijd Terraform apply kunnen uitvoeren op hetzelfde statebestand. Dit is nog een reden waarom we een statebestand dat wordt beheerd door broncodebeheer niet zullen aantreffen.

Hoe GitLab te gebruiken voor het beheren van Terraform State

Aangezien Terraform als de standaard wordt beschouwd voor het inrichten van cloud infrastructuur, biedt GitLab al een jaar of zo een manier om uw Terraform state op te slaan en te beheren. Daarom wilden we de migratieprocedure delen, aangezien we onlangs zijn begonnen met het gebruik van GitLab voor het beheren van onze IaC.

Voor dit artikel gaan we ervan uit dat u een lokale state gebruikt en uw state beheert met een AWS S3 Bucket of een ander achtergrondoplossing.

Ten eerste moet u uw backend.tf wijzigen om HTTP te gebruiken:

 

terraform {  
    backend "http" {} 
  }

Vervolgens moet u vier variabelen instellen in uw terminal:

1. PROJECT_ID: U kunt deze gemakkelijk vinden door naar uw repo te navigeren op de pagina “Projectoverzicht”.

2. TF_USERNAME: De GitLab gebruikersnaam die toegang heeft tot de repo waar u aan werkt.

3. TF_PASSWORD: Toegangstoken gegenereerd vanuit uw GitLab-gebruiker.

4. TF_ADDRESS: URL van de remote state backend.

 

PROJECT_ID="28450092"
TF_USERNAME="florianpialoux"
TF_PASSWORD="123456789"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/aws-buckets"

U kunt nu de migratiecommando uitvoeren die uw Terraform state verplaatst van zijn vorige locatie naar GitLab met het volgende commando:

 

  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

U moet een bevestiging geven met een “ja” zodat GitLab uw statebestand kan gaan beheren. Hier is een voorbeeld van een lokale state naar GitLab:


Voorbeeld S3 naar GitLab:

Now, you can navigate to Infrastructure > Terraform from the GitLab interface and see your state:

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

Kopieer en plak de inhoud van de S3 state en voer een push uit:

 
terraform state push -lock=true aws-buckets.json

GitLab ondersteunt versiebeheer voor uw Terraform state-bestand, maar het bekijken/herstellen van oudere versies via de WebUI vereist dat u een GitLab Premium-abonnement gebruikt. Zo niet, dan moet u een GraphQL API verzoek maken.

Hoe GitLab uw IaC door een CI-pijplijn laat uitvoeren

GitLab biedt een Docker-afbeelding die GitLab-Terraform bevat, wat een dunne wrapper-script rond de officiële Terraform-binair is. U kunt ook de officiële Docker-afbeelding van Hashicorp gebruiken. Meer informatie over de GitLab Terraform Image vindt u hier.

Zodra de Terraform apply-taak wordt uitgevoerd, kunt u zien wanneer de status werd gebruikt en met welke pijplijn.

Learn more about what our gitlab-ci.yml looks like here. Below, are the variables that will need to be defined on the project level.

Bonus Tip: Infracost

Zoals u misschien heeft opgemerkt, kijken we naar ons gitlab-ci.yaml hebben we Infracost toegevoegd, waardoor we meer controle hebben over onze cloudkosten omdat het u een kostenschatting geeft wanneer u een nieuw middel aan uw IaC definieert.

Conclusie

Het hebben van uw Terraform-status en CI die draaien op Gitlab is een geweldige manier om de beste GitOps-praktijken te volgen. Ze vormen een uitstekend duo voor het ontwikkelen en implementeren van IaC. Aangezien de meesten van jullie waarschijnlijk al GitLab gebruiken voor uw repositories, wordt het veel eenvoudiger om uw IaC onder één dak te hebben en GitLab de Terraform-status te laten beheren door ondersteuning te bieden voor versleuteling in transitie en in rust, evenals voor het versioneren, vergrendelen en ontgrendelen van de status.

Source:
https://dzone.com/articles/how-to-migrate-terraform-state-to-gitlab-cicd