Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions examples/cross-regional-failover-with-gxlb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Cross-Regional Failover with GXLB Example

This example demonstrates how to use the **terraform-google-lb-http** module (or a variant that supports GXLB) to set up a **Global HTTP Load Balancer** with **cross-regional failover** capabilities (GXLB). The idea is que tráfego enviado ao *Global Load Balancer* será roteado para backends regionais saudáveis, com failover automático entre regiões.

Este projeto assume que sua versão do módulo *terraform-google-lb-http* (ou fork com suporte GXLB) já suporta a lógica de failover global entre regiões.

---

## How it Works

- **Backend module(s)**: serão criados recursos de backend (ex: *google_compute_backend_service*, instâncias, MIGs, health checks) em múltiplas regiões conforme definido nas variáveis.
- **Frontend / Global module**: cria os recursos do balanceador global — endereço IP global, regras de encaminhamento globais (*global forwarding rules*), proxy HTTP/HTTPS, URL map com lógica de failover entre regiões (prioridades ou condições de health).
- A lógica de failover global é configurada de modo que, se um backend em região A ficar indisponível, o tráfego será encaminhado para o backend em região B.

---

## Inputs

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
| Name | Description | Type | Default | Required |
|---------------------|---------------------------------------------------------------|----------------|----------------------------------|:--------:|
| project_id | The GCP project ID | `string` | n/a | yes |
| project | Alias project ID (used in some resources) | `string` | n/a | yes |
| regions | Map of regions where regional ALBs / backends will be created | `map(string)` | see example default in variables | no |
| vm_subnet_cidrs | Map of VM subnet CIDRs per region | `map(string)` | default map | no |
| proxy_subnet_cidrs | Map of proxy-only subnet CIDRs per region | `map(string)` | default map | no |
| default_region | Default region used by the provider | `string` | `"us-central1"` | no |
| region_to_zone | Map region → zone for MIGs | `map(string)` | default map | no |
| instance_image | Image to use for backend instances | `string` | `"projects/debian-cloud/global/images/family/debian-11"` | no |
| instance_machine_type | Machine type for backend instances | `string` | `"e2-medium"` | no |
| target_size | Number of VMs per managed instance group | `number` | `2` | no |
| regional_hostname | DNS hostname used for certificates and DNS records | `string` | `"regional.example.com"` | no |
| enable_dns_records | Whether to create DNS records | `bool` | `true` | no |
| create_public_zone | Whether to create a new public managed DNS zone | `bool` | `true` | no |
| public_zone_name | Name of existing public zone (if `create_public_zone = false`) | `string` | `"public-example-zone"` | no |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
189 changes: 189 additions & 0 deletions examples/cross-regional-failover-with-gxlb/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
resource "google_compute_network" "global_lb_network" {
name = "global-lb-network"
auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "vm_subnets" {
for_each = var.regions
name = "global-backend-${each.key}-vm-subnet"
region = each.key
network = google_compute_network.global_lb_network.self_link
ip_cidr_range = var.vm_subnet_cidrs[each.key]
}

resource "google_compute_firewall" "allow_global_hc" {
name = "allow-global-lb-health-checks"
network = google_compute_network.global_lb_network.name
allow {
protocol = "tcp"
ports = ["80", "443"]
}
direction = "INGRESS"
source_ranges = ["130.211.0.0/22", "35.191.0.0/16"]
target_tags = ["allow-health-check"]
}

resource "google_compute_instance_template" "global_backend_tmpl" {
for_each = var.regions
name_prefix = "global-backend-${each.key}-tmpl-"
machine_type = var.instance_machine_type
tags = ["allow-health-check"]

disk {
source_image = var.instance_image
auto_delete = true
boot = true
}

network_interface {
subnetwork = google_compute_subnetwork.vm_subnets[each.key].self_link
}

metadata_startup_script = <<-EOT
#!/bin/bash
apt-get update -y
apt-get install -y nginx
echo "Hello from Global LB Backend in ${each.key}" > /var/www/html/index.html
systemctl enable nginx
systemctl restart nginx
EOT
}

resource "google_compute_instance_group_manager" "global_backend_migs" {
for_each = var.regions
name = "global-backend-${each.key}-mig"
base_instance_name = "global-backend-${each.key}-vm"
zone = var.region_to_zone[each.key]
target_size = var.target_size

version {
instance_template = google_compute_instance_template.global_backend_tmpl[each.key].self_link
}
}

resource "google_compute_health_check" "global_lb_hc" {
name = "global-lb-health-check"
check_interval_sec = 10
timeout_sec = 5
healthy_threshold = 2
unhealthy_threshold = 3

http_health_check {
port = 80
request_path = "/"
}
}

resource "google_compute_security_policy" "global_armor" {
name = "global-armor-policy"
rule {
action = "allow"
priority = 2147483647
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["*"]
}
}
description = "Default allow all rule"
}
}

resource "google_compute_backend_service" "global_bs" {
name = "global-lb-backend-service"
protocol = "HTTP"
load_balancing_scheme = "EXTERNAL_MANAGED"
health_checks = [google_compute_health_check.global_lb_hc.self_link]
security_policy = google_compute_security_policy.global_armor.self_link
enable_cdn = true

dynamic "backend" {
for_each = var.regions
content {
group = google_compute_instance_group_manager.global_backend_migs[backend.key].instance_group
}
}
}

resource "google_compute_url_map" "global_um" {
name = "global-lb-url-map"
default_service = google_compute_backend_service.global_bs.id
}

resource "google_compute_target_https_proxy" "global_https_proxy" {
name = "global-lb-https-proxy"
url_map = google_compute_url_map.global_um.id
certificate_map = "//certificatemanager.googleapis.com/${google_certificate_manager_certificate_map.global_cert_map.id}"
}

resource "google_compute_global_address" "global_addr" {
name = "global-lb-ip"
}

resource "google_compute_global_forwarding_rule" "global_fr" {
name = "global-lb-forwarding-rule"
ip_protocol = "TCP"
load_balancing_scheme = "EXTERNAL_MANAGED"
port_range = "443"
target = google_compute_target_https_proxy.global_https_proxy.id
ip_address = google_compute_global_address.global_addr.address
}

locals {
dns_managed_zone_name = var.create_public_zone && var.enable_dns_records ? google_dns_managed_zone.public_new[0].name : var.public_zone_name
}

resource "google_dns_managed_zone" "public_new" {
count = var.create_public_zone && var.enable_dns_records ? 1 : 0
name = format("public-%s", replace(var.hostname, ".", "-"))
dns_name = "${var.hostname}."
description = "Public zone for ${var.hostname}"
}

resource "google_certificate_manager_dns_authorization" "global_auth" {
provider = google-beta
name = "global-dns-auth"
domain = var.hostname
}

resource "google_certificate_manager_certificate" "global_cert" {
provider = google-beta
name = "global-cm-cert"
managed {
domains = [var.hostname]
dns_authorizations = [google_certificate_manager_dns_authorization.global_auth.id]
}
}

resource "google_certificate_manager_certificate_map" "global_cert_map" {
provider = google-beta
name = "global-lb-cert-map"
}

resource "google_certificate_manager_certificate_map_entry" "global_cert_map_entry" {
provider = google-beta
name = "global-lb-cert-map-entry"
map = google_certificate_manager_certificate_map.global_cert_map.name
certificates = [google_certificate_manager_certificate.global_cert.id]
hostname = var.hostname
}

resource "google_dns_record_set" "global_acme_txt" {
count = var.enable_dns_records && length(local.dns_managed_zone_name) > 0 ? 1 : 0

managed_zone = local.dns_managed_zone_name
name = google_certificate_manager_dns_authorization.global_auth.dns_resource_record[0].name
type = google_certificate_manager_dns_authorization.global_auth.dns_resource_record[0].type
ttl = 60
rrdatas = [google_certificate_manager_dns_authorization.global_auth.dns_resource_record[0].data]
}

resource "google_dns_record_set" "global_a" {
count = var.enable_dns_records && length(local.dns_managed_zone_name) > 0 ? 1 : 0

managed_zone = local.dns_managed_zone_name
name = "${var.hostname}."
type = "A"
ttl = 60
rrdatas = [google_compute_global_address.global_addr.address]
}
9 changes: 9 additions & 0 deletions examples/cross-regional-failover-with-gxlb/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "global_lb_ip" {
description = "The public IP address of the Global Load Balancer."
value = google_compute_global_address.global_addr.address
}

output "hostname" {
description = "The domain name (hostname) configured for the Global Load Balancer."
value = var.hostname
}
79 changes: 79 additions & 0 deletions examples/cross-regional-failover-with-gxlb/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
variable "project_id" {
description = "GCP project ID"
type = string
}

variable "default_region" {
description = "Default region used for the provider"
type = string
default = "us-central1"
}

variable "regions" {
description = "Regions to create backend groups (MIGs)"
type = map(string)
default = {
"us-central1" = "us-central1"
"us-east1" = "us-east1"
}
}

variable "vm_subnet_cidrs" {
description = "VM subnet CIDRs per region"
type = map(string)
default = {
"us-central1" = "10.10.0.0/24"
"us-east1" = "10.20.0.0/24"
}
}

variable "region_to_zone" {
description = "Region -> zone mapping for MIGs"
type = map(string)
default = {
"us-central1" = "us-central1-a"
"us-east1" = "us-east1-b"
}
}

variable "instance_image" {
description = "Image for backend instances"
type = string
default = "projects/debian-cloud/global/images/family/debian-11"
}

variable "instance_machine_type" {
description = "Machine type for backend instances"
type = string
default = "e2-medium"
}

variable "target_size" {
description = "Number of VMs per MIG"
type = number
default = 2
}

variable "hostname" {
description = "The domain name (hostname) for the Global Load Balancer"
type = string
default = "global.example.com"
}

variable "enable_dns_records" {
description = "Whether to create DNS zone and records"
type = bool
default = true
}

variable "create_public_zone" {
description = "Whether to create a new public managed zone in Cloud DNS"
type = bool
default = true
}

variable "public_zone_name" {
description = "Name of an existing public zone (used if create_public_zone=false)"
type = string
default = "public-example-zone"
}