Como Migrarmos o Estado do Terraform para o GitLab CI/CD

Como profissional de software que lida com Infrastructure as Code (IaC), é provável que você trabalhe muito com o Terraform. Ao ajudar novos clientes a usar IaC, é comum simplificar as coisas, mas gerenciar um arquivo de estado do Terraform é o primeiro desafio que enfrenta. Essencialmente, o estado do Terraform contém informações sensíveis, que não devem ser armazenadas pelo controle de origem, mas, ao mesmo tempo, não escalará se você tiver vários usuários trabalhando no mesmo estado do Terraform. A resposta para isso? Backends.

É importante notar que você poderia armazenar esse arquivo de estado em um bucket S3 e usar o DynamoDB para gerenciar o estado de bloqueio. No entanto, essa abordagem forçará você a criar recursos adicionais, o que a torna uma opção complicada, especialmente se o cliente estiver usando o GitLab. Recentemente, o GitLab abaixou a barreira de entrada para integrar o Terraform, fornecendo uma maneira de armazenar e gerenciar o estado do Terraform, bem como uma maneira fácil de configurar um CI (Continuous Integration) em torno disso.

Neste artigo, explicaremos o que é um arquivo de estado do Terraform, como migrá-lo para o GitLab e configurar um pipeline de CI para ele. Você pode visitar nosso repositório aqui.

Sumário

  • O que é o Estado do Terraform?
  • Como fazer o GitLab gerenciar o estado do Terraform
  • Como fazer o GitLab executar sua IaC através de um pipeline de CI
    • Dica Bônus: Infracost
  • Conclusão

O que é o Estado do Terraform?

O Terraform registra qualquer informação sobre a infraestrutura definida no seu código através de um arquivo de estado. Escrito em JSON, ele essencialmente registra um mapeamento do código Terraform para os recursos reais criados. Abaixo está um exemplo de como um terraform.tfstate seria. Principalmente, cada vez que você executa o Terraform, ele buscará o status mais recente para sua instância EC2 e a comparará com sua configuração Terraform para determinar quais alterações precisam ser aplicadas:

 

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

Por padrão, este terraform.tfstate é armazenado localmente onde você tem seus arquivos Terraform, planeja e aplica suas alterações. Para um projeto pessoal onde você está apenas executando alguns testes; está bom, mas não é a maneira recomendada, aqui está o porquê:

  • Armazenado em um local compartilhado: se você estivesse hospedando este arquivo de estado no seu computador local e precisasse trabalhar com outro engenheiro, as coisas ficariam complicadas. Ambos teriam que garantir que estão usando a versão mais recente do estado e você poderia enfrentar condições de corrida se executar um plano Terraform ou aplicar ao mesmo tempo.
  • Proteger informações sensíveis: Um arquivo de estado gerado pode conter chaves de criptografia e senhas de infraestrutura. No entanto, os arquivos de estado não são criptografados por padrão e armazenar informações sensíveis em texto simples é uma má ideia.
  • Travamento: A maioria dos sistemas de controle de versão não suporta nenhum tipo de travamento, o que impede que dois membros da equipe executem o Terraform apply simultaneamente no mesmo arquivo de estado. Esta é outra razão pela qual não veremos um arquivo de estado gerenciado por controle de origem.

Como Fazer o GitLab Gerenciar o Estado do Terraform

Considerando que o Terraform é o padrão na provisionamento de infraestrutura em nuvem, faz cerca de um ano desde que o GitLab começou a oferecer uma maneira de armazenar e gerenciar o estado do Terraform. Por essa razão, queremos compartilhar o processo de migração com você, já que recentemente começamos a usar o GitLab para gerenciar nosso IaC.

Para este artigo, presumimos que você está usando um estado local e que tem seu estado gerenciado com um Bucket S3 da AWS ou outra solução de backend. 

Primeiro, você precisará alterar seu backend.tf para usar HTTP: 

 

terraform {  
    backend "http" {} 
  }

Em seguida, você precisará configurar quatro variáveis em seu terminal:

1. PROJECT_ID: Você pode encontrar isso facilmente navegando até o repositório na página de “Visão Geral do Projeto”.

2. TF_USERNAME: O nome de usuário do GitLab que tem acesso ao repositório em que está trabalhando.

3. TF_PASSWORD: Token de acesso gerado a partir do seu usuário do GitLab.

4. TF_ADDRESS: URL do backend de estado remoto.

 

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

Agora você pode executar o comando de migração que moverá seu estado do Terraform de sua localização anterior para o GitLab com o seguinte 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

Você precisará fornecer uma confirmação com um “sim” para que o GitLab possa começar a gerenciar seu arquivo de estado. Aqui está um exemplo de um estado local para o GitLab:


Exemplo de S3 para 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

Copie e cole o conteúdo do estado S3 e execute um push:

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

O GitLab suporta o versionamento para o seu arquivo de estado Terraform, mas visualizar/restaurar versões antigas através da WebUI exigirá que você esteja usando um plano Premium do GitLab. Caso contrário, você precisará fazer uma requisição à API GraphQL.

Como fazer o GitLab executar sua IaC através de um pipeline CI

O GitLab fornece uma imagem Docker que contém o GitLab-Terraform, que é um script wrapper fino em torno do binário oficial do Terraform. Como alternativa, você poderia usar a imagem Docker oficial da Hashicorp. Você pode encontrar mais informações sobre a Imagem Terraform do GitLab aqui.

Uma vez que o trabalho de aplicação do Terraform seja executado, você poderá ver quando o estado foi utilizado e com qual pipeline.

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.

Dica Bônus: Infracost

Como você deve ter notado, ao analisar nosso código gitlab-ci.yaml, adicionamos o Infracost, que nos permite ter mais controle sobre nossa fatura de nuvem, pois fornece uma estimativa de custo sempre que você define um novo recurso para sua IaC.

Conclusão

Ter seu estado do Terraform e CI rodando no Gitlab é uma ótima maneira de seguir as melhores práticas do GitOps. Ambos se combinam perfeitamente para desenvolver e implantar IaC. Como a maioria de vocês provavelmente já usa o GitLab para seus repositórios, fica muito mais simples ter sua IaC sob um mesmo teto e deixar o GitLab gerenciar seu estado do Terraform, suportando criptografia em trânsito e em repouso, bem como versionamento, bloqueio e desbloqueio do estado.

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