Todos os artigos
Aprenda Terraform no Google Cloud

GCP

Terraform no Google Cloud: criando, alterando e destruindo infraestrutura como codigo

Engineering Handbook · Capitulo 03

Iury CoelhoIury Coelho
12 min de leitura

Terraform no Google Cloud: criando, alterando e destruindo infraestrutura como codigo

Google Cloud Master Journey 2026
Engineering Handbook · Capitulo 03

Como usei Terraform para provisionar uma VPC, criar maquinas virtuais, configurar IP estatico, modelar dependencias e entender o ciclo de vida da infraestrutura no Google Cloud.

Este artigo faz parte da serie Google Cloud Master Journey 2026, em que estou documentando minha jornada pratica com Google Cloud, Arcade, laboratorios da trilha de certificacao e preparacao para a Associate Cloud Engineer.

A ideia nao e apenas registrar badges ou comandos executados. Quero transformar cada laboratorio em um material que responda perguntas de engenharia:

  • qual problema essa tecnologia resolve;
  • como ela funciona por baixo;
  • quais decisoes arquiteturais aparecem no caminho;
  • quais riscos existem em ambiente real;
  • como eu aplicaria isso em projetos profissionais.

Neste capitulo, o tema e Infrastructure as Code com Terraform.

O que vamos construir

O laboratorio usado como base foi Infrastructure as Code with Terraform, executado em um ambiente temporario do Google Cloud.

Durante a pratica, a infraestrutura evoluiu por etapas:

  • uma rede VPC;
  • uma maquina virtual no Compute Engine;
  • um endereco IP estatico;
  • um bucket do Cloud Storage;
  • uma segunda maquina virtual com dependencia explicita;
  • um provisioner local para registrar o IP externo.
flowchart TD A[Escrever configuracao HCL] --> B[terraform init] B --> C[terraform plan] C --> D{Plano aprovado?} D -->|Nao| A D -->|Sim| E[terraform apply] E --> F[Infraestrutura provisionada] F --> G[terraform destroy em ambiente temporario]

Apesar de pequena, essa infraestrutura apresenta conceitos que aparecem em ambientes corporativos maiores: estado desejado, revisao de mudancas, dependencias, substituicao de recursos e automacao.

Por que infraestrutura manual nao escala

E possivel criar todos esses recursos pelo Console do Google Cloud. Para um teste isolado, clicar no painel pode funcionar.

O problema aparece quando precisamos repetir o processo:

  • em outro ambiente;
  • em homologacao parecida com producao;
  • em varias regioes;
  • para diferentes clientes;
  • com revisao de equipe;
  • com rastreabilidade de mudancas.

Infraestrutura manual tende a gerar configuracoes inconsistentes, pouca auditoria, dependencia de conhecimento individual e maior chance de erro humano.

Infrastructure as Code muda a pergunta principal.

Em vez de perguntar:

Quais passos preciso executar no Console?

Passamos a perguntar:

Qual estado minha infraestrutura precisa possuir?

Essa diferenca e o centro do Terraform.

O que e Terraform

Terraform e uma ferramenta de Infrastructure as Code criada pela HashiCorp. Ela usa uma linguagem declarativa chamada HCL, ou HashiCorp Configuration Language.

Em uma configuracao declarativa, descrevemos o estado desejado. O Terraform compara esse estado com o que ele conhece da infraestrutura e calcula as acoes necessarias.

resource "google_compute_network" "vpc_network" {
  name = "terraform-network"
}

Esse bloco nao diz "abra o Console, clique em redes e confirme". Ele declara:

Deve existir uma rede do Google Cloud chamada terraform-network.

O provider do Google Cloud faz a ponte entre o Terraform e a API da plataforma.

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "3.5.0"
    }
  }
}

Em um projeto novo eu avaliaria uma versao mais atual do provider, mas no laboratorio a versao fixa ajuda a manter previsibilidade.

O ciclo init, plan, apply e destroy

O fluxo basico do Terraform e simples, mas cada etapa tem uma responsabilidade importante.

sequenceDiagram participant Dev as Engenheiro participant TF as Terraform participant State as State participant GCP as Google Cloud Dev->>TF: terraform init TF->>TF: baixa providers Dev->>TF: terraform plan TF->>State: le estado conhecido TF->>GCP: consulta recursos TF-->>Dev: mostra plano de mudancas Dev->>TF: terraform apply TF->>GCP: cria, altera ou remove recursos TF->>State: atualiza estado

terraform init

Inicializa o diretorio de trabalho, baixa providers e prepara o ambiente local.

No laboratorio, ele tambem criou o arquivo .terraform.lock.hcl, que registra as versoes selecionadas dos providers e ajuda a manter execucoes consistentes.

terraform plan

Compara configuracao desejada, state e infraestrutura real.

Ele nao altera nada. Serve para revisar impacto antes da execucao.

Simbolos importantes:

Simbolo Significado
+ criar recurso
~ alterar em lugar
- destruir recurso
-/+ destruir e recriar

Em ambiente real, o plan deveria ser revisado em Pull Request ou pipeline antes de qualquer alteracao chegar em producao.

terraform apply

Executa as mudancas planejadas. No primeiro passo do laboratorio, o resultado foi a criacao da VPC:

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

terraform destroy

Remove os recursos administrados pela configuracao.

Esse comando e util em laboratorios, ambientes efemeros, testes automatizados e demonstracoes. Em producao, destruicao exige controles adicionais: aprovacao, backup, politicas e janelas de execucao.

A primeira infraestrutura

A configuracao inicial tinha uma VPC e uma VM.

resource "google_compute_network" "vpc_network" {
  name = "terraform-network"
}

resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = "e2-micro"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
    }
  }

  network_interface {
    network = google_compute_network.vpc_network.name

    access_config {
    }
  }
}
flowchart TB P[Google Cloud Project] --> VPC[VPC Network] VPC --> VM[Compute Engine VM]

A linha abaixo ja cria uma relacao entre VM e rede:

network = google_compute_network.vpc_network.name

Essa relacao e uma dependencia implicita.

Criar, alterar ou substituir

Uma parte importante do laboratorio foi observar como o Terraform reage a mudancas diferentes.

Ao adicionar uma VM nova, o plano mostra criacao:

+ create

Ao adicionar tags na instancia, o plano mostra alteracao em lugar:

~ update in-place

A diferenca no codigo era pequena:

Antes
resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = "e2-micro"
}
Depois
resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = "e2-micro"
  tags         = ["web", "dev"]
}

Mas quando a imagem do disco de boot muda, a instancia precisa ser substituida:

-/+ destroy and then create replacement

Esse e um aprendizado fundamental: uma mudanca pequena no codigo pode representar uma substituicao completa na infraestrutura.

Por isso, terraform plan nao e burocracia. E etapa de engenharia.

O state do Terraform

O Terraform precisa saber quais recursos ele administra, quais IDs reais foram criados e como os recursos se relacionam. Para isso, ele mantem um state.

flowchart LR A[Configuracao HCL] --> C[Terraform] B[State] --> C D[Infraestrutura real no Google Cloud] --> C C --> E[Plano de mudancas]

No laboratorio, o state ficou local. Em equipe, eu usaria backend remoto com:

  • controle de concorrencia;
  • versionamento;
  • criptografia;
  • acesso restrito;
  • backup;
  • recuperacao de versoes.

O state pode conter informacoes sensiveis e deve ser tratado como parte critica da infraestrutura.

Dependencias implicitas

Depois da VM, adicionei um IP estatico:

resource "google_compute_address" "vm_static_ip" {
  name = "terraform-static-ip"
}

E associei esse IP na interface de rede:

network_interface {
  network = google_compute_network.vpc_network.self_link

  access_config {
    nat_ip = google_compute_address.vm_static_ip.address
  }
}

A referencia google_compute_address.vm_static_ip.address cria uma dependencia implicita. O Terraform entende que o IP precisa existir antes da VM consumir esse valor.

flowchart TB VPC[VPC Network] --> VM[Main VM] IP[Static IP] --> VM

Sempre que a dependencia aparece por uma referencia real entre recursos, prefiro deixa-la implicita. O codigo fica mais expressivo.

Dependencias explicitas

Dependencias de recursos no Terraform

Nem toda dependencia aparece em uma propriedade do recurso.

Imagine uma aplicacao que roda em uma VM e espera encontrar um bucket durante a inicializacao. A VM pode nao referenciar o bucket em nenhum atributo, mas a aplicacao depende dele.

Nesse caso, usamos depends_on.

resource "google_compute_instance" "another_instance" {
  depends_on = [google_storage_bucket.example_bucket]

  name         = "terraform-instance-2"
  machine_type = "e2-micro"
}
flowchart LR B[Cloud Storage Bucket] -->|depends_on| VM2[Second VM]

A ordem dos blocos no arquivo nao determina a ordem de criacao. O Terraform usa o grafo de dependencias.

Como o Terraform pensa

Uma forma simples de visualizar o processo:

flowchart TD A[Ler arquivos HCL] --> B[Carregar state] B --> C[Consultar recursos existentes] C --> D[Comparar atual vs desejado] D --> E[Construir grafo de dependencias] E --> F[Gerar plano] F --> G[Executar operacoes na ordem correta]

Esse grafo permite criar recursos dependentes na ordem correta, destruir em ordem inversa, executar operacoes independentes em paralelo e evitar remover recursos ainda utilizados.

Salvando um plano

O laboratorio tambem mostrou:

terraform plan -out static_ip
terraform apply "static_ip"

Salvar o plano permite aplicar exatamente aquilo que foi revisado. Em pipeline, isso ajuda a reduzir diferenca entre revisao e execucao.

flowchart LR PR[Pull Request] --> Plan[terraform plan] Plan --> Review[Revisao humana] Review --> Approval[Aprovacao] Approval --> Apply[terraform apply do plano salvo]

Provisioners

Na ultima etapa, adicionei um provisioner:

provisioner "local-exec" {
  command = "echo ${self.name}: ${self.network_interface[0].access_config[0].nat_ip} >> ip_address.txt"
}

O local-exec roda na maquina onde o Terraform esta sendo executado. No laboratorio, isso significa o Cloud Shell. Ele nao roda dentro da VM criada.

Um detalhe importante: depois de adicionar o provisioner, o Terraform informou que nao havia mudancas. Isso acontece porque provisioners normalmente executam na criacao do recurso.

Para forcar a recriacao no laboratorio, foi usado:

terraform taint google_compute_instance.vm_instance

Em fluxos mais modernos, eu preferiria:

terraform apply -replace="google_compute_instance.vm_instance"

Provisioners sao uteis, mas eu evitaria trata-los como primeira opcao. Em producao, avaliaria alternativas como startup scripts, cloud-init, Packer, imagens pre-configuradas, containers ou servicos gerenciados.

Arquitetura final do laboratorio

flowchart TB P[Google Cloud Project] P --> VPC[VPC Network] VPC --> IP[Static IP] IP --> VM1[Main VM] VPC --> VM1 P --> B[Cloud Storage Bucket] B --> VM2[Second VM] VPC --> VM2

O bucket e a segunda VM foram recursos temporarios para demonstrar dependencia explicita. Depois da validacao, eles foram removidos.

Google Cloud e AWS: equivalencias uteis

Como eu ja venho de experiencia com AWS, comparar os conceitos ajuda a consolidar.

Conceito Google Cloud AWS
Provider Terraform hashicorp/google hashicorp/aws
Rede virtual google_compute_network aws_vpc
Maquina virtual google_compute_instance aws_instance
IP estatico google_compute_address aws_eip
Armazenamento de objetos google_storage_bucket aws_s3_bucket
Terminal gerenciado Cloud Shell AWS CloudShell
Imagem de VM Compute Engine Image AMI
Escopo principal Google Cloud Project AWS Account

As equivalencias nao sao perfeitas, mas ajudam a transferir intuicoes entre nuvens.

Como eu aplicaria isso em um projeto real

Eu nao deixaria toda a infraestrutura em um unico main.tf.

Uma estrutura inicial poderia ser:

Estrutura Terraform
  • infrastructure/
    • environments/
      • development/
      • staging/
      • production/
    • modules/
      • network/
      • compute/
      • database/
      • storage/
      • iam/
      • observability/
    • versions.tf
    • providers.tf
    • variables.tf

Cada ambiente consumiria modulos reutilizaveis, mantendo padroes e reduzindo duplicacao.

Em uma plataforma real, o fluxo deveria ser:

flowchart TD A[Engenheiro altera Terraform] --> B[Abre Pull Request] B --> C[Pipeline executa terraform plan] C --> D[Equipe revisa impacto] D --> E{Aprovado?} E -->|Nao| A E -->|Sim| F[Apply no ambiente correto] F --> G[Auditoria e observabilidade]

O que eu faria diferente em producao

O laboratorio e bom para aprender, mas producao pede mais cuidado.

  • Usaria state remoto com locking, criptografia e versionamento.
  • Separaria arquivos por responsabilidade.
  • Receberia project_id, regiao, zona e nomes por variaveis.
  • Exporia valores importantes com output.
  • Evitaria acesso externo desnecessario nas VMs.
  • Rodaria terraform fmt e terraform validate no pipeline.
  • Revisaria terraform plan antes de aplicar.
  • Nao executaria apply manualmente do notebook de um desenvolvedor para producao.

Erros que apareceram no laboratorio

Registrar erros tambem faz parte da jornada.

Durante a instalacao, um arquivo de chave ja existia e o processo entrou em modo interativo. A solucao foi interromper, revisar o bloco e executar corretamente.

Ao adicionar o IP estatico, uma chave do HCL ficou aberta e o Terraform retornou:

Error: Unclosed configuration block

Isso reforcou o valor de rodar:

terraform fmt
terraform validate

Tambem aprendi na pratica que adicionar um provisioner nao forca execucao em recurso ja criado. O comportamento estava correto, mas era facil interpretar como erro se eu nao entendesse o ciclo de vida do recurso.

Licoes aprendidas

  1. Infrastructure as Code nao e apenas automacao. Tambem e documentacao, revisao, auditoria e governanca.
  2. terraform plan e etapa de engenharia, nao uma formalidade.
  3. Uma mudanca pequena pode substituir um recurso inteiro.
  4. Dependencias formam a arquitetura operacional.
  5. depends_on deve ser usado com intencao.
  6. O state e parte critica da infraestrutura.
  7. Provisioners resolvem casos especificos, mas nao deveriam ser a estrategia padrao.

Como isso ajuda na Associate Cloud Engineer

Esse laboratorio reforca habilidades importantes para a certificacao:

  • criacao e configuracao de recursos no Google Cloud;
  • operacao de Compute Engine;
  • redes e enderecos IP;
  • uso do Cloud Shell;
  • modelo de projetos;
  • automacao de infraestrutura;
  • analise de impacto antes de mudancas;
  • ciclo de vida de recursos.

A certificacao nao exige apenas decorar comandos. Ela exige entender qual recurso usar, como configura-lo e qual impacto uma decisao pode causar.

Conclusao

Este laboratorio comecou com uma VPC simples e terminou mostrando conceitos centrais do Terraform: estado desejado, plano de execucao, dependencias, substituicao de recursos, provisionamento e infraestrutura declarativa.

O aprendizado principal nao foi executar terraform apply.

Foi entender que o Terraform constroi uma representacao da infraestrutura, calcula dependencias e executa mudancas para alcancar o estado declarado.

Essa mudanca de mentalidade e o que torna Infrastructure as Code tao poderosa.

Proximo capitulo

Nos proximos capitulos da Google Cloud Master Journey 2026, quero continuar conectando os laboratorios do Arcade com preparacao real para Cloud Engineering:

  • Cloud Shell e gcloud;
  • Compute Engine;
  • armazenamento e APIs;
  • IAM e seguranca;
  • Cloud Run;
  • Terraform mais proximo de producao.

A jornada esta apenas comecando.

Em breve

Comentários

Em breve

As respostas da comunidade chegam em breve.

Em breve

Leia também