Como profissional de software que lida com Infrastructure as Code (IaC), é provável que você trabalhe muito com Terraform. Ao ajudar novos clientes a usar IaC, é comum simplificar as coisas, mas gerenciar um arquivo de estado Terraform é o primeiro desafio que enfrenta. Essencialmente, o estado Terraform contém informações sensíveis, que não devem ser armazenadas por controle de origem, mas, ao mesmo tempo, não escalará se você tiver vários usuários trabalhando no mesmo estado 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 Terraform, bem como uma maneira fácil de configurar um CI ao redor dele.
Neste artigo, explicaremos o que é um arquivo de estado Terraform, como migrar para o GitLab e configurar um pipeline CI para ele. Você pode visitar nosso repositório aqui.
Sumário
- O que é o estado Terraform?
- Como fazer com que o GitLab gerencie o estado Terraform
- Como fazer com que o GitLab execute seu IaC por meio de um pipeline CI
- Dica Bônus: Infracost
- Conclusão
O que é o estado 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, sempre que você executar o Terraform, ele buscará o status mais recente para a instância EC2 e comparará com sua configuração Terraform para determinar quais mudanças 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 mudanças. Para um projeto pessoal onde você está apenas executando alguns testes, está tudo bem, mas não é a maneira recomendada, eis o porquê:
- Armazenado em um local compartilhado: se você estivesse hospedando este arquivo de estado no seu computador local e tivesse que 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 ou aplicar o Terraform 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 seu Terraform. Por esta razão, queríamos 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 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 você 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:

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 com que o GitLab execute sua IaC por meio 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 GitLab Terraform aqui.
Após a execução do trabalho ‘terraform apply’, você poderá ver quando o estado foi utilizado e com qual pipeline.
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, analisando nosso gitlab-ci.yaml
, adicionamos o Infracost, que nos permite ter mais controle sobre nossa cobrança em 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, oferecendo suporte a 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