# Multi-Region High Availability Workspace # Global deployment across 3 providers and 3 geographic regions # # Architecture: # - US East (DigitalOcean NYC): Primary region, active serving # - EU Central (Hetzner Germany): Secondary region, active serving + read replicas # - Asia Pacific (AWS Singapore): Tertiary region, active serving + read replicas # # Features: # - Geographic load balancing with Route53 # - Multi-master database replication # - Automatic failover # - Zero downtime deployment # - Cost: ~$250/month across all regions let hetzner = import "../../../extensions/providers/hetzner/nickel/main.ncl" in let aws = import "../../../extensions/providers/aws/nickel/main.ncl" in let digitalocean = import "../../../extensions/providers/digitalocean/nickel/main.ncl" in { workspace_name = "multi-region-ha", description = "High availability deployment across 3 geographic regions", version = "1.0", environment = "production", owner = "platform-team", tags = { "project" = "global-app", "deployment" = "multi-region-ha", "environment" = "production" }, # ============================================================================= # Global Configuration # ============================================================================= global_config = { dns_provider = "route53", health_check_interval = 30, failover_ttl = 60, replication_lag_tolerance = 300, rpo_target = 300, rto_target = 900 }, # ============================================================================= # US EAST REGION (DigitalOcean NYC) - PRIMARY # ============================================================================= region_us_east = { name = "us-east", provider = "digitalocean", region_code = "nyc3", primary = true, description = "Primary region: serves North America", # Private Network vpc = digitalocean.VPC & { name = "us-east-vpc", region = "nyc3", ip_range = "10.0.0.0/16" }, # Application Servers (3 replicas for HA) app_servers = digitalocean.Droplet & { name = "us-app", region = "nyc3", size = "s-2vcpu-4gb", image = "ubuntu-22-04-x64", count = 3, vpc_uuid = "{{ region_us_east.vpc.id }}", backups = true, monitoring = true, tags = ["us-east", "primary", "production"] }, # Load Balancer load_balancer = digitalocean.LoadBalancer & { name = "us-lb", algorithm = "round_robin", region = "nyc3", forwarding_rules = [ { entry_protocol = "https", entry_port = 443, target_protocol = "http", target_port = 8080, certificate_id = "cert-id" } ], health_check = { protocol = "http", port = 8080, path = "/health", interval = 10, timeout = 5, healthy_threshold = 3, unhealthy_threshold = 3 }, sticky_sessions = { type = "cookies", cookie_name = "REGION_SESSION", cookie_ttl_seconds = 300 } }, # Primary Database (Multi-AZ in DigitalOcean) database = digitalocean.Database & { name = "us-db-primary", engine = "pg", version = "14", size = "db-s-2vcpu-4gb", region = "nyc3", num_nodes = 3, multi_az = true, backup_retention_days = 30 } }, # ============================================================================= # EU CENTRAL REGION (Hetzner Germany) - SECONDARY # ============================================================================= region_eu_central = { name = "eu-central", provider = "hetzner", location = "nbg1", description = "Secondary region: serves Europe, read replicas", # Private Network network = hetzner.Network & { name = "eu-central-network", ip_range = "10.1.0.0/16" }, # Application Servers (3 replicas for HA) app_servers = hetzner.Server & { name = "eu-app", server_type = "cpx21", image = "ubuntu-22.04", location = "nbg1", count = 3, networks = [ { network_name = "eu-central-network", ip = "10.1.1.10" } ], labels = { "region" = "eu-central", "tier" = "application" } }, # Load Balancer load_balancer = hetzner.LoadBalancer & { name = "eu-lb", load_balancer_type = "lb21", location = "nbg1", services = [ { protocol = "http", listen_port = 443, destination_port = 8080, health_check = { protocol = "http", port = 8080, interval = 10, timeout = 5 } } ] }, # Read Replica Database (from US primary) database_replica = { type = "read-replica", source = "region_us_east.database", replication_lag_seconds = 300, read_only = true, description = "Read-only replica of US primary database" } }, # ============================================================================= # ASIA PACIFIC REGION (AWS Singapore) - TERTIARY # ============================================================================= region_asia_southeast = { name = "asia-southeast", provider = "aws", region_code = "ap-southeast-1", description = "Tertiary region: serves Asia Pacific, read replicas", # VPC for region vpc = aws.VPC & { cidr_block = "10.2.0.0/16", enable_dns_hostnames = true, enable_dns_support = true, tags = [ { key = "Name", value = "asia-vpc" }, { key = "Region", value = "ap-southeast-1" } ] }, # Private Subnet private_subnet = aws.Subnet & { vpc_id = "{{ region_asia_southeast.vpc.id }}", cidr_block = "10.2.1.0/24", availability_zone = "ap-southeast-1a", tags = [ { key = "Name", value = "asia-private-subnet" } ] }, # Application Servers (EC2 instances) app_servers = aws.EC2 & { instance_type = "t3.medium", image_id = "ami-xxxxxxxx", region = "ap-southeast-1", subnet_id = "{{ region_asia_southeast.private_subnet.id }}", count = 3, tags = [ { key = "Name", value = "asia-app" }, { key = "Region", value = "ap-southeast-1" } ] }, # Load Balancer (ALB) load_balancer = aws.ALB & { name = "asia-lb", internal = false, load_balancer_type = "application", region = "ap-southeast-1", subnets = ["{{ region_asia_southeast.private_subnet.id }}"], tags = [ { key = "Name", value = "asia-lb" } ] }, # Read Replica Database (from US primary) database_replica = aws.RDS & { identifier = "asia-db-replica", replicate_source_db = "{{ region_us_east.database.identifier }}", instance_class = "db.t3.small", region = "ap-southeast-1", multi_az = true, tags = [ { key = "Name", value = "asia-db-replica" } ] } }, # ============================================================================= # VPN Tunnels Between Regions # ============================================================================= vpn_tunnels = { us_to_eu = { name = "us-eu-vpn", source_region = "us-east", destination_region = "eu-central", protocol = "ipsec", encryption = "aes-256", source_network = "10.0.0.0/16", destination_network = "10.1.0.0/16" }, eu_to_asia = { name = "eu-asia-vpn", source_region = "eu-central", destination_region = "asia-southeast", protocol = "ipsec", encryption = "aes-256", source_network = "10.1.0.0/16", destination_network = "10.2.0.0/16" }, asia_to_us = { name = "asia-us-vpn", source_region = "asia-southeast", destination_region = "us-east", protocol = "ipsec", encryption = "aes-256", source_network = "10.2.0.0/16", destination_network = "10.0.0.0/16" } }, # ============================================================================= # Global DNS and Load Balancing (Route53) # ============================================================================= global_dns = { domain = "api.example.com", dns_provider = "route53", # Geographic routing policy geolocation_rules = [ { location = "North America", endpoint = "us-east-lb", weight = 100 }, { location = "Europe", endpoint = "eu-central-lb", weight = 100 }, { location = "Asia Pacific", endpoint = "asia-southeast-lb", weight = 100 } ], # Health checks for each region health_checks = [ { region = "us-east", endpoint = "us.api.example.com", protocol = "HTTPS", port = 443, path = "/health", interval = 30, failure_threshold = 3 }, { region = "eu-central", endpoint = "eu.api.example.com", protocol = "HTTPS", port = 443, path = "/health", interval = 30, failure_threshold = 3 }, { region = "asia-southeast", endpoint = "asia.api.example.com", protocol = "HTTPS", port = 443, path = "/health", interval = 30, failure_threshold = 3 } ], # Failover configuration failover_policy = { strategy = "geographic", primary = "us-east", secondary = "eu-central", tertiary = "asia-southeast", health_check_grace_period = 60 } }, # ============================================================================= # Database Replication Configuration # ============================================================================= database_replication = { mode = "multi-master", primary_region = "us-east", read_replicas = [ { region = "eu-central", lag_tolerance = 300, read_only = true }, { region = "asia-southeast", lag_tolerance = 300, read_only = true } ], replication_settings = { method = "logical", wal_level = "logical", max_wal_senders = 5, max_replication_slots = 5, backup_retention_days = 30 } }, # ============================================================================= # Monitoring and Alerting # ============================================================================= monitoring = { enabled = true, regional_metrics = [ { region = "us-east", metrics = ["cpu", "memory", "disk", "network", "database_connections"] }, { region = "eu-central", metrics = ["cpu", "memory", "disk", "network", "replication_lag"] }, { region = "asia-southeast", metrics = ["cpu", "memory", "disk", "network", "replication_lag"] } ], alerts = [ { name = "high-cpu", condition = "cpu > 80%", action = "scale-up", severity = "warning" }, { name = "replication-lag", condition = "replication_lag > 600s", action = "alert", severity = "critical" }, { name = "region-down", condition = "health_check_failed", action = "failover", severity = "critical" } ] }, # ============================================================================= # Backup and Disaster Recovery # ============================================================================= backup_strategy = { frequency = "daily", retention_days = 30, backup_locations = [ { region = "us-east", strategy = "automated", retention = "30 days" }, { region = "eu-central", strategy = "replica-backup", retention = "30 days" }, { region = "asia-southeast", strategy = "replica-backup", retention = "30 days" } ] }, # ============================================================================= # Cost Estimation # ============================================================================= cost_estimate = { monthly_breakdown = { us_east = { droplets = "$72", # 3 x $24 load_balancer = "$0", database = "$30", subtotal = "$102" }, eu_central = { servers = "$62.70", # 3 x CPX21 @ €20.90 load_balancer = "$10", subtotal = "€72.70 (~$79)" }, asia_southeast = { ec2 = "$80", # 3 x t3.medium alb = "$20", database = "$30", subtotal = "$130" }, total_monthly = "$311", total_annual = "$3,732" } } }