Terraform e Localstack

Image: Infra as Code

Se você trabalha com DevOps, redes, sistemas ou cloud, provavelmente já ouviu falar do Terraform. Essa ferramenta se tornou quase obrigatória para quem quer automatizar infraestrutura de forma simples e escalável.

Mas existe uma barreira para muita gente: como praticar sem gastar dinheiro em nuvem pública? O cu$$to de brincar na cloud pode ser alto. Basta esquecer uma VM ligada para perceber como a conta chega rápido. É aí que entra a combinação Terraform + LocalStack.

Usar os dois juntos é uma ótima forma de treinar infraestrutura como código (IaC) sem gastar nada. Como o LocalStack é open source e pode ser instalado via containers, você consegue criar um cenário realista de nuvem privada para experimentar recursos como redes, máquinas virtuais e volumes. Isso elimina gastos em cloud pública e viabiliza o aprendizado de forma acessível.

Outra grande vantagem é que o combo permite simular fluxos muito próximos de ambientes de produção. Você escreve o código Terraform, aplica no LocalStack e vê os recursos sendo provisionados na prática. Assim, fica fácil entender conceitos como versionamento, modularização, gerenciamento de estado e automação de infraestrutura. É um aprendizado prático, que vai além da teoria, acelera a curva de conhecimento e ainda ajuda a perder o medo de criar e destruir recursos sem preocupação.

Preparei um lab baseado em Docker Compose e vou mostrar como usar o Terraform para provisionar uma instância no LocalStack (e também comparar com a AWS).

Organização dos arquivos

Antes de começarmos, para manter o laboratório organizado e fácil de entender, é importante seguir uma estrutura de diretório conforme descrito abaixo. O arquivo docker-compose.yml deve ficar na raiz do projeto, pois é ele quem sobe todo o ambiente de containers. Já os arquivos do Terraform ficam dentro da pasta terraform/, separando o que é infraestrutura de orquestração de containers. Dentro dessa pasta, o provider.tf é usado para configurar o provedor (como LocalStack ou AWS) e o main.tf concentra a definição dos recursos que serão criados. Essa organização simples torna o lab mais legível, modular e fácil de manter.

├── docker-compose.yml
├── terraform/
    ├── main.tf
    ├── provider.tf

Docker Compose

Docker compose vai ser a base para criar os ambientes e executar o script terraform e uma instância de LocalStack para simular um provider de cloud.

Arquivo: docker-compose.yml

 1version: '3.8'
 2
 3services:
 4  localstack:
 5    container_name: localstack
 6    image: localstack/localstack:latest
 7    ports:
 8      - "4566:4566"
 9      - "4510-4559:4510-4559"
10    environment:
11      - EDGE_PORT=4566
12      - AWS_DEFAULT_REGION=us-east-1
13      - AWS_ACCESS_KEY_ID=test
14      - AWS_SECRET_ACCESS_KEY=test  
15      - SERVICES=ec2
16      - DEBUG=1
17      - DATA_DIR=/tmp/localstack/data
18      - DOCKER_HOST=unix:///var/run/docker.sock
19      - HOST_TMP_FOLDER=/var/lib/localstack
20    volumes:
21      - localstack_data:/var/lib/localstack
22      - "/var/run/docker.sock:/var/run/docker.sock"
23    networks:
24      - terraform
25
26  terraform:
27    image: hashicorp/terraform:1.6
28    container_name: terraform
29    working_dir: /workspace
30    volumes:
31      - ./terraform:/workspace
32    networks:
33      - terraform
34    depends_on:
35      - localstack
36    entrypoint: ["tail", "-f", "/dev/null"]
37
38
39volumes:
40  localstack_data:
41
42networks:
43  terraform:
44    name: terraform

Para criar o ambiente basta executar

docker compose up -d --build

LocalStack Cloud Provider

No Terraform, um provider (provedor) é o componente responsável por fazer a ponte entre os scripts Terraform e o serviço que você quer gerenciar, no caso desta explicação é o LocalStack. Cada provider é como se fosse um plugin que traduz os comandos do Terraform em chamadas para a API da plataforma que você está usando.

Exemplo prático, se você quer criar uma instância na AWS, precisa do provider “aws”. Se quer criar uma rede no LocalStack, usa o provider “localstack”. E assim por diante, sacou??!?!

Veja a conf do nosso lab:

Arquivo: terraform/provider.tf
 1terraform {
 2  required_providers {
 3    aws = {
 4      source  = "hashicorp/aws"
 5      version = "~> 5.0"
 6    }
 7  }
 8}
 9
10provider "aws" {
11  access_key                  = "test"
12  secret_key                  = "test"
13  region                      = "us-east-1"
14  s3_use_path_style          = true
15  skip_credentials_validation = true
16  skip_metadata_api_check     = true
17  skip_requesting_account_id  = true
18
19  endpoints {
20    s3       = "http://localstack:4566"
21    ec2      = "http://localstack:4566"
22  }
23}

Terraform script

Um script Terraform é um arquivos ou um conjunto de arquivos de configuração escritos em HCL (HashiCorp Configuration Language) que descrevem a infraestrutura que você deseja criar ou gerenciar.

Em vez de criar recursos manualmente em um painel de cloud, você escreve esse script dizendo, por exemplo, “quero uma VM com tal rede e tal disco”. O Terraform lê o script, compara com o estado atual da infraestrutura e executa as mudanças necessárias para deixar tudo igual ao que foi definido no código. É a base do conceito de infraestrutura como código (IaC).

O script abaixo, criar uma VM na AWS, para o Terraform isso é um recurso chamado de “aws_instance”, veja os passos de como criar

Arquivo: terraform/main.tf
 1# Buscar a última AMI Amazon Linux 2
 2data "aws_ami" "amazon_linux" {
 3  most_recent = true
 4
 5  filter {
 6    name   = "name"
 7    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
 8  }
 9
10  owners = ["amazon"]
11}
12
13# Criar uma instância EC2
14resource "aws_instance" "exemplo_ec2" {
15  ami           = data.aws_ami.amazon_linux.id
16  instance_type = "t2.micro"
17
18  tags = {
19    Name = "Infraascode.com.br - Terraform"
20  }
21}

Iniciando o Terraform

O comando terraform init serve para inicializar um diretório de trabalho do Terraform, preparando tudo para que você possa usar seus scripts. Ele baixa e instala os providers necessários (como AWS, Azure, LocalStack, etc.), configura o backend de armazenamento do estado (se houver) e valida a estrutura inicial dos arquivos, em resumo, é o primeiro passo obrigatório antes de rodar qualquer outro comando, pois garante que o ambiente esteja pronto para executar o plano e aplicar a infraestrutura.

 1  $ terraform  init
 2
 3Initializing the backend...
 4
 5Initializing provider plugins...
 6- Finding hashicorp/aws versions matching "~> 5.0"...
 7- Installing hashicorp/aws v5.100.0...
 8- Installed hashicorp/aws v5.100.0 (signed by HashiCorp)
 9
10Terraform has created a lock file .terraform.lock.hcl to record the provider
11selections it made above. Include this file in your version control repository
12so that Terraform can guarantee to make the same selections by default when
13you run "terraform init" in the future.
14
15Terraform has been successfully initialized!
16
17You may now begin working with Terraform. Try running "terraform plan" to see
18any changes that are required for your infrastructure. All Terraform commands
19should now work.
20
21If you ever set or change modules or backend configuration for Terraform,
22rerun this command to reinitialize your working directory. If you forget, other
23commands will detect it and remind you to do so if necessary.

Verificando o plano de execução

O comando terraform plan serve para mostrar, de forma prévia, o que o Terraform vai fazer antes de aplicar as mudanças na sua infraestrutura. Ele compara o que está definido nos seus arquivos de configuração com o estado atual e gera um “plano de execução”, indicando quais recursos serão criados, alterados ou destruídos. Isso ajuda a revisar e validar as alterações antes de executá-las, evitando surpresas ou erros.

 1terraform plan -out=infraascode_com_br
 2data.aws_ami.amazon_linux: Reading...
 3data.aws_ami.amazon_linux: Read complete after 2s [id=ami-04681a1dbd79675a5]
 4
 5Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 6  + create
 7
 8Terraform will perform the following actions:
 9
10  # aws_instance.exemplo_ec2 will be created
11  + resource "aws_instance" "exemplo_ec2" {
12      + ami                                  = "ami-04681a1dbd79675a5"
13      + arn                                  = (known after apply)
14      + associate_public_ip_address          = (known after apply)
15      + availability_zone                    = (known after apply)
16      + instance_type                        = "t2.micro"
17      + tags                                 = {
18          + "Name" = "Infraascode.com.br - Terraform"
19        }
20      + tags_all                             = {
21          + "Name" = "Infraascode.com.br - Terraform"
22        }
23      + id                                   = (known after apply)
24      + public_ip                            = (known after apply)
25      + private_ip                           = (known after apply)
26    }
27
28Plan: 1 to add, 0 to change, 0 to destroy.
29
30───────────────────────────────────────────────────────────────────────────────
31
32Saved the plan to: infraascode_com_br
33
34To perform exactly these actions, run the following command to apply:
35    terraform apply "infraascode_com_br"

Terraform apply

O comando terraform apply é usado para executar as mudanças descritas nos arquivos de configuração, aplicando na infraestrutura tudo o que foi planejado no terraform plan. Ele cria, altera ou remove recursos de acordo com o código e só finaliza quando a infraestrutura está no estado desejado. Em outras palavras, é o comando que transforma seu código Terraform em recursos reais funcionando no ambiente definido, no nosso caso o LocalStack.

1  $terraform  apply infraascode_com_br
2aws_instance.exemplo_ec2: Creating...
3aws_instance.exemplo_ec2: Still creating... [10s elapsed]
4aws_instance.exemplo_ec2: Creation complete after 10s [id=i-50b40c581c4dad9b4]
5
6Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Verificando o resultado

O comando terraform state list serve para exibir todos os recursos que o Terraform está gerenciando no arquivo de estado (terraform.tfstate). Ele mostra a lista dos objetos conhecidos pelo Terraform, como VMs, redes, discos ou qualquer outro recurso criado. Isso é útil para verificar o que já foi provisionado, confirmar nomes corretos de recursos e até para depurar situações em que o código e a infraestrutura parecem não estar alinhados.

 1terraform state list
 2data.aws_ami.amazon_linux
 3aws_instance.exemplo_ec2
 4/workspace/# terraform state show   aws_instance.exemplo_ec2
 5# aws_instance.exemplo_ec2:
 6resource "aws_instance" "exemplo_ec2" {
 7    ami                                  = "ami-04681a1dbd79675a5"
 8    arn                                  = "arn:aws:ec2:us-east-1::instance/i-50b40c581c4dad9b4"
 9    associate_public_ip_address          = true
10    availability_zone                    = "us-east-1a"
11    disable_api_stop                     = false
12    disable_api_termination              = false
13    ebs_optimized                        = false
14    get_password_data                    = false
15    hibernation                          = false
16    id                                   = "i-50b40c581c4dad9b4"
17    instance_initiated_shutdown_behavior = "stop"
18    instance_state                       = "running"
19    instance_type                        = "t2.micro"
20    ipv6_address_count                   = 0
21    ipv6_addresses                       = []
22    monitoring                           = false
23    placement_partition_number           = 0
24    primary_network_interface_id         = "eni-697884262d742bf4f"
25    private_dns                          = "ip-10-75-171-105.ec2.internal"
26    private_ip                           = "10.75.171.105"
27    public_dns                           = "ec2-54-214-150-17.compute-1.amazonaws.com"
28    public_ip                            = "54.214.150.17"
29    secondary_private_ips                = []
30    security_groups                      = []
31    source_dest_check                    = true
32    subnet_id                            = "subnet-777fbdb4bbd4df236"
33    tags                                 = {
34        "Name" = "Infraascode.com.br - Terraform"
35    }
36    tags_all                             = {
37        "Name" = "Infraascode.com.br - Terraform"
38    }
39    tenancy                              = "default"
40    user_data_replace_on_change          = false
41    vpc_security_group_ids               = []
42
43    metadata_options {
44        http_endpoint               = "enabled"
45        http_protocol_ipv6          = "disabled"
46        http_put_response_hop_limit = 1
47        http_tokens                 = "optional"
48        instance_metadata_tags      = "disabled"
49    }
50
51    root_block_device {
52        delete_on_termination = true
53        device_name           = "/dev/sda1"
54        encrypted             = false
55        iops                  = 0
56        tags                  = {}
57        tags_all              = {}
58        throughput            = 0
59        volume_id             = "vol-22f90e0fe787def16"
60        volume_size           = 8
61        volume_type           = "gp2"
62    }
63}

Resumindo

Brincar com Terraform e Localstack em um ambiente de LAB abre um leque de possibilidades para quem quer aprender infraestrutura como código sem depender da nuvem pública e sem se preocupar com custos. Você pode testar a criação de máquinas virtuais, redes, volumes e simular fluxos de produção de forma segura, rápida e controlada. Essa liberdade de experimentar dá confiança para entender conceitos de automação, versionamento e modularização sem medo de “quebrar” nada crítico.

Além disso, o lab com Terraform e LocalStack é uma ótima maneira de descobrir novas funcionalidades, criar cenários diferentes e evoluir suas habilidades de forma prática. A cada teste você ganha um pouco mais de experiência e se aproxima do que encontrará em ambientes de empresas. É um investimento em aprendizado que acelera sua curva de evolução e te prepara para os desafios.

Abraços!

Vida longa e próspera a todos!!

Referências


Entre em contato:

NewsLetter - https://engineeringmanager.com.br/
Linkdin - linkedin.com/in/leonardoml/
Twitter: @infraascode_br

Te convido a ver os outros posts do blog Infra-as-Code garanto que tem coisas legais lá!!


--- --- IMPORTANTE --- ---
As opiniões aqui expressas são pessoais e de responsabilidade única e exclusiva do autor, elas não refletem necessariamente a posição das empresas que eu trabalho(ei) e/ou presto(ei) serviço.


bio_banner_test