🏗️ IaC — Infraestrutura como Código

Terraform, CloudFormation e Ansible — provisione e gerencie infra com código

🏗️ O que é Infraestrutura como Código?

IaC (Infrastructure as Code) é a prática de gerenciar e provisionar infraestrutura através de arquivos de configuração versionados, em vez de processos manuais ou interfaces gráficas.

Com IaC você trata servidores, redes, bancos de dados e qualquer recurso de infra da mesma forma que trata código de aplicação — com versionamento, revisão, testes e automação.

  • Reprodutibilidade — o mesmo código cria ambientes idênticos em dev, staging e prod
  • Versionamento — histórico completo de mudanças na infra via Git
  • Automação — elimina erros humanos de configuração manual
  • Documentação viva — o código é a documentação da infra
  • Disaster recovery — recrie toda a infra em minutos a partir do código
💡 Regra de ouro: Se você fez uma mudança na infra manualmente, ela não existe — só existe o que está no código.

🛠️ Ferramentas de IaC

🟣

Terraform

Multi-cloud, declarativo, HCL. Padrão do mercado para provisionamento.

🟠

CloudFormation

Nativo AWS, YAML/JSON. Integração total com serviços AWS.

🔴

Ansible

Configuração e orquestração. Agentless, usa SSH.

🔵

Pulumi

IaC com linguagens reais: Python, TypeScript, Go.

FerramentaTipoLinguagemMelhor para
TerraformProvisionamentoHCLMulti-cloud, padrão de mercado
CloudFormationProvisionamentoYAML/JSONProjetos 100% AWS
AnsibleConfiguraçãoYAMLConfigurar servidores, apps
PulumiProvisionamentoPython/TS/GoTimes que preferem linguagens reais

🟣 Terraform — Fundamentos

O Terraform usa a linguagem HCL (HashiCorp Configuration Language) para descrever recursos de infra de forma declarativa.

Instalação no Ubuntu/WSL2:

# Adicionar repositório HashiCorp
wget -O- https://apt.releases.hashicorp.com/gpg | \
  sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
  https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update && sudo apt install terraform

# Verificar
terraform version

Estrutura básica de um projeto Terraform:

projeto/
├── main.tf          # recursos principais
├── variables.tf     # declaração de variáveis
├── outputs.tf       # valores de saída
├── providers.tf     # configuração do provider
└── terraform.tfvars # valores das variáveis (não commitar se tiver secrets)

Comandos essenciais:

# Inicializar projeto (baixa providers e módulos)
terraform init

# Ver o que será criado/alterado/destruído
terraform plan

# Aplicar as mudanças
terraform apply

# Aplicar sem confirmação (cuidado!)
terraform apply -auto-approve

# Destruir toda a infra
terraform destroy

# Ver estado atual
terraform show

# Listar recursos no state
terraform state list

# Formatar código
terraform fmt

# Validar sintaxe
terraform validate

☁️ Terraform + AWS — Exemplos Práticos

providers.tf — configurar AWS:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  # State remoto no S3 (recomendado para times)
  backend "s3" {
    bucket = "aegiscloud-terraform-state"
    key    = "producao/terraform.tfstate"
    region = "us-east-1"
  }
}

provider "aws" {
  region = var.aws_region
}

main.tf — bucket S3 + CloudFront:

# Bucket S3 para site estático
resource "aws_s3_bucket" "site" {
  bucket = var.bucket_name
}

resource "aws_s3_bucket_website_configuration" "site" {
  bucket = aws_s3_bucket.site.id
  index_document { suffix = "index.html" }
  error_document { key    = "index.html" }
}

# Distribuição CloudFront
resource "aws_cloudfront_distribution" "cdn" {
  enabled             = true
  default_root_object = "index.html"

  origin {
    domain_name = aws_s3_bucket.site.bucket_regional_domain_name
    origin_id   = "S3Origin"
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3Origin"
    viewer_protocol_policy = "redirect-to-https"
    forwarded_values {
      query_string = false
      cookies { forward = "none" }
    }
  }

  restrictions {
    geo_restriction { restriction_type = "none" }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

variables.tf e outputs.tf:

# variables.tf
variable "aws_region" {
  description = "Região AWS"
  type        = string
  default     = "us-east-1"
}

variable "bucket_name" {
  description = "Nome do bucket S3"
  type        = string
}

# outputs.tf
output "cloudfront_url" {
  description = "URL do CloudFront"
  value       = "https://${aws_cloudfront_distribution.cdn.domain_name}"
}

output "bucket_name" {
  value = aws_s3_bucket.site.bucket
}

📦 State e Workspaces

O terraform.tfstate é o arquivo que mapeia os recursos declarados no código com os recursos reais na nuvem. É o "cérebro" do Terraform.

⚠️ Nunca commite o tfstate no Git — ele pode conter dados sensíveis. Use sempre backend remoto (S3 + DynamoDB para lock).
# Criar bucket S3 para state remoto
aws s3 mb s3://aegiscloud-terraform-state --region us-east-1

# Criar tabela DynamoDB para lock de state
aws dynamodb create-table \
  --table-name terraform-lock \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

Workspaces permitem múltiplos ambientes com o mesmo código:

# Criar e usar workspace de staging
terraform workspace new staging
terraform workspace new producao

# Listar workspaces
terraform workspace list

# Trocar de workspace
terraform workspace select producao

# Usar workspace no código
# resource "aws_instance" "app" {
#   instance_type = terraform.workspace == "producao" ? "t3.medium" : "t3.micro"
# }

🟠 AWS CloudFormation

O CloudFormation é a solução nativa da AWS para IaC. Usa YAML ou JSON e tem integração profunda com todos os serviços AWS.

Template básico — EC2 + Security Group:

AWSTemplateFormatVersion: '2010-09-09'
Description: Servidor web simples

Parameters:
  InstanceType:
    Type: String
    Default: t3.micro
    AllowedValues: [t3.micro, t3.small, t3.medium]

Resources:
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Permite HTTP e SSH
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0

  WebServer:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref InstanceType
      ImageId: ami-0c02fb55956c7d316  # Amazon Linux 2 us-east-1
      SecurityGroupIds:
        - !Ref WebSecurityGroup
      UserData:
        Fn::Base64: |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd

Outputs:
  PublicIP:
    Value: !GetAtt WebServer.PublicIp
    Description: IP público do servidor
# Deploy do stack via CLI
aws cloudformation deploy \
  --template-file template.yaml \
  --stack-name meu-servidor-web \
  --parameter-overrides InstanceType=t3.micro \
  --region us-east-1

# Ver eventos do stack
aws cloudformation describe-stack-events \
  --stack-name meu-servidor-web \
  --region us-east-1

# Deletar stack
aws cloudformation delete-stack \
  --stack-name meu-servidor-web \
  --region us-east-1

🔴 Ansible — Configuração de Servidores

O Ansible é usado para configurar servidores após o provisionamento — instalar pacotes, configurar serviços, fazer deploy de aplicações. Funciona via SSH, sem agente nos servidores.

Instalação:

sudo apt update && sudo apt install -y ansible
ansible --version

Inventory — lista de servidores:

# inventory.ini
[webservers]
192.168.1.10 ansible_user=ubuntu
192.168.1.11 ansible_user=ubuntu

[databases]
192.168.1.20 ansible_user=ubuntu

[all:vars]
ansible_ssh_private_key_file=~/.ssh/minha-chave.pem

Playbook — instalar e configurar Nginx:

# playbook-nginx.yml
---
- name: Configurar servidores web
  hosts: webservers
  become: true  # sudo

  vars:
    app_port: 80

  tasks:
    - name: Atualizar pacotes
      apt:
        update_cache: yes

    - name: Instalar Nginx
      apt:
        name: nginx
        state: present

    - name: Copiar configuração
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: Reiniciar Nginx

    - name: Garantir que Nginx está rodando
      service:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: Reiniciar Nginx
      service:
        name: nginx
        state: restarted
# Executar playbook
ansible-playbook -i inventory.ini playbook-nginx.yml

# Testar conectividade com todos os hosts
ansible all -i inventory.ini -m ping

# Executar comando ad-hoc
ansible webservers -i inventory.ini -m shell -a "df -h"

✅ Boas Práticas de IaC

  • State remoto sempre: use S3 + DynamoDB para Terraform em times — nunca state local
  • Módulos reutilizáveis: crie módulos Terraform para padrões repetidos (VPC, ECS cluster, RDS)
  • Variáveis por ambiente: use terraform.tfvars separados para dev/staging/prod
  • Nunca commite secrets: use AWS SSM Parameter Store ou Secrets Manager para senhas e chaves
  • Plan antes de apply: sempre revise o terraform plan antes de aplicar em produção
  • Tagging obrigatório: tag todos os recursos com Environment, Project, Owner — facilita billing e gestão
  • Drift detection: execute terraform plan periodicamente para detectar mudanças manuais na infra
💡 Dica para o time: Para projetos novos na AWS, use Terraform para provisionamento (VPC, ECS, RDS) e Ansible para configuração de servidores legados. São complementares, não concorrentes.