Exemplo prático de um serviço web simples na GCP provisionado com Terraform, com promoção do ambiente de desenvolvimento para produção usando workspaces.

A diferença central em relação à AWS e Azure é que na GCP tudo orbita em torno de um Project ID, e as regras de firewall são recursos independentes associados à rede (não à instância diretamente).

Estrutura do projeto

infra/
├── backend.tf
├── main.tf
├── variables.tf
├── outputs.tf
├── dev.tfvars
└── prod.tfvars

Backend remoto (Google Cloud Storage)

# backend.tf
terraform {
  backend "gcs" {
    bucket = "meu-projeto-tfstate"
    prefix = "app/terraform.tfstate"
  }
 
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}
 
provider "google" {
  project = var.projeto_id
  region  = var.regiao
}

A autenticação usa o gcloud auth application-default login em desenvolvimento ou uma Service Account via variável de ambiente em CI/CD:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

Variáveis

# variables.tf
variable "projeto_id" {
  type        = string
  description = "ID do projeto GCP"
}
 
variable "regiao" {
  type    = string
  default = "us-central1"
}
 
variable "zona" {
  type    = string
  default = "us-central1-a"
}
 
variable "ambiente" {
  type = string
}
 
variable "machine_type" {
  type = string
}
 
variable "projeto" {
  type    = string
  default = "meu-projeto"
}
# dev.tfvars
ambiente     = "dev"
machine_type = "e2-micro"
projeto_id   = "meu-gcp-project-id"
 
# prod.tfvars
ambiente     = "prod"
machine_type = "e2-medium"
projeto_id   = "meu-gcp-project-id"

Infraestrutura: Compute Instance com NGINX

# main.tf
locals {
  nome   = "${var.projeto}-${var.ambiente}"
  labels = {
    projeto   = var.projeto
    ambiente  = var.ambiente
    managedby = "terraform"
  }
}
 
# Habilita a API do Compute Engine (necessário em projetos novos)
resource "google_project_service" "compute" {
  service            = "compute.googleapis.com"
  disable_on_destroy = false
}
 
# Regra de firewall para HTTP, associada à rede, não à instância
resource "google_compute_firewall" "http" {
  name    = "${local.nome}-allow-http"
  network = "default"
 
  allow {
    protocol = "tcp"
    ports    = ["80"]
  }
 
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["web"]
 
  depends_on = [google_project_service.compute]
}
 
resource "google_compute_firewall" "ssh" {
  name    = "${local.nome}-allow-ssh"
  network = "default"
 
  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
 
  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["web"]
}
 
# Compute Instance, equivalente ao EC2 da AWS
resource "google_compute_instance" "app" {
  name         = local.nome
  machine_type = var.machine_type
  zone         = var.zona
  tags         = ["web"]
  labels       = local.labels
 
  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-2204-lts"
    }
  }
 
  network_interface {
    network = "default"
 
    access_config {}  # IP público efêmero
  }
 
  metadata_startup_script = <<-EOF
    #!/bin/bash
    apt-get update -y
    apt-get install -y nginx
    systemctl enable nginx
    systemctl start nginx
    echo "<h1>${local.nome}</h1>" > /var/www/html/index.html
  EOF
 
  depends_on = [google_project_service.compute]
}
# outputs.tf
output "ip_publico" {
  value = google_compute_instance.app.network_interface[0].access_config[0].nat_ip
}
 
output "url" {
  value = "http://${google_compute_instance.app.network_interface[0].access_config[0].nat_ip}"
}

Fluxo dev → prod

# 1. Subir ambiente de dev
terraform workspace new dev
terraform workspace select dev
terraform init
terraform plan  -var-file="dev.tfvars"
terraform apply -var-file="dev.tfvars"
 
# Valida no IP exibido pelo output "url"...
 
# 2. Promover para prod
terraform workspace new prod
terraform workspace select prod
terraform plan  -var-file="prod.tfvars"
terraform apply -var-file="prod.tfvars"
 
# 3. Destruir dev após validação
terraform workspace select dev
terraform destroy -var-file="dev.tfvars"

Diferenças em relação à AWS

ConceitoAWSGCP
OrganizaçãoAccount / RegionProject / Region
Backend de stateS3 + DynamoDBGCS (locking nativo)
VMaws_instancegoogle_compute_instance
FirewallSecurity Group (por instância)google_compute_firewall (por rede, com target_tags)
ImagemAMI (data source)image em boot_disk
IP públicoAssociado ao recursoaccess_config {} no network_interface
Locking do stateDynamoDB separadoNativo no GCS

Ver também: terraform-state | terraform-variaveis | terraform-providers | terraform | terraform-cloud-aws