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
| Conceito | AWS | GCP |
|---|---|---|
| Organização | Account / Region | Project / Region |
| Backend de state | S3 + DynamoDB | GCS (locking nativo) |
| VM | aws_instance | google_compute_instance |
| Firewall | Security Group (por instância) | google_compute_firewall (por rede, com target_tags) |
| Imagem | AMI (data source) | image em boot_disk |
| IP público | Associado ao recurso | access_config {} no network_interface |
| Locking do state | DynamoDB separado | Nativo no GCS |
Ver também: terraform-state | terraform-variaveis | terraform-providers | terraform | terraform-cloud-aws