Multi-Region AWS Infrastructure

Description

Build a highly available, multi-region AWS infrastructure using Terraform with auto-scaling, load balancing, and disaster recovery.

Objective

Design and deliver a production-ready cloud solution with clear infrastructure, security, and operations practices.

Solution

Plan the architecture

  1. 1Define the workload, availability requirements, regions, and recovery objectives.
  2. 2Choose the network, compute, storage, and identity boundaries for the solution.
  3. 3
    terraform# provider.tf
    provider "aws" {
      region = var.primary_region
      alias  = "primary"
    }
    
    provider "aws" {
      region = var.secondary_region
      alias  = "secondary"
    }
  4. 4
    terraform# VPCs
    module "vpc_primary" {
      source  = "terraform-aws-modules/vpc/aws"
      providers = { aws = aws.primary }
      name    = "primary-vpc"
      cidr    = "10.0.0.0/16"
      azs     = ["us-east-1a", "us-east-1b"]
      public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
      private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
    }
    
    module "vpc_secondary" {
      source  = "terraform-aws-modules/vpc/aws"
      providers = { aws = aws.secondary }
      name    = "secondary-vpc"
      cidr    = "10.1.0.0/16"
      azs     = ["us-west-2a", "us-west-2b"]
      public_subnets  = ["10.1.1.0/24", "10.1.2.0/24"]
      private_subnets = ["10.1.3.0/24", "10.1.4.0/24"]
    }

Provision the foundation

  1. 1Configure AWS providers for multiple regions in Terraform.
  2. 2Create reusable modules for VPC, EC2, ALB, ASG, and RDS.
  3. 3Apply least-privilege IAM roles, tagging, and configuration conventions.
  4. 4
    terraform# Launch Template + Auto Scaling
    resource "aws_launch_template" "app" {
      name_prefix   = "app-template"
      image_id      = var.ami_id
      instance_type = "t3.micro"
    }
    
    resource "aws_autoscaling_group" "asg_primary" {
      provider = aws.primary
      desired_capacity     = 2
      max_size             = 4
      min_size             = 2
      vpc_zone_identifier  = module.vpc_primary.private_subnets
      launch_template {
        id      = aws_launch_template.app.id
        version = "$Latest"
      }
      tag {
        key                 = "Name"
        value               = "primary-asg"
        propagate_at_launch = true
      }
    }
  5. 5
    terraform# Load Balancer
    resource "aws_lb" "alb_primary" {
      provider = aws.primary
      name     = "primary-alb"
      internal = false
      load_balancer_type = "application"
      subnets = module.vpc_primary.public_subnets
    }
    
    resource "aws_lb_target_group" "tg_primary" {
      provider = aws.primary
      name     = "primary-tg"
      port     = 80
      protocol = "HTTP"
      vpc_id   = module.vpc_primary.vpc_id
    }
    
    resource "aws_lb_listener" "listener_primary" {
      provider = aws.primary
      load_balancer_arn = aws_lb.alb_primary.arn
      port              = 80
      protocol          = "HTTP"
      default_action {
        type             = "forward"
        target_group_arn = aws_lb_target_group.tg_primary.arn
      }
    }
  6. 6
    terraform# Route 53 Failover
    resource "aws_route53_record" "primary" {
      zone_id = var.zone_id
      name    = "app.example.com"
      type    = "A"
      set_identifier = "primary"
      failover_routing_policy {
        type = "PRIMARY"
      }
      alias {
        name                   = aws_lb.alb_primary.dns_name
        zone_id                = aws_lb.alb_primary.zone_id
        evaluate_target_health = true
      }
    }
    
    resource "aws_route53_record" "secondary" {
      zone_id = var.zone_id
      name    = "app.example.com"
      type    = "A"
      set_identifier = "secondary"
      failover_routing_policy {
        type = "SECONDARY"
      }
      alias {
        name                   = aws_lb.alb_secondary.dns_name
        zone_id                = aws_lb.alb_secondary.zone_id
        evaluate_target_health = true
      }
    }
  7. 7
    terraform# Disaster Recovery (S3 + RDS)
    resource "aws_s3_bucket" "primary" {
      provider = aws.primary
      bucket   = "primary-app-bucket"
    }
    
    resource "aws_s3_bucket_replication_configuration" "replication" {
      provider = aws.primary
      bucket   = aws_s3_bucket.primary.id
      role     = aws_iam_role.replication.arn
    
      rules {
        id     = "replication"
        status = "Enabled"
        destination {
          bucket        = aws_s3_bucket.secondary.arn
          storage_class = "STANDARD"
        }
      }
    }
    
    resource "aws_db_instance" "primary_rds" {
      provider = aws.primary
      engine   = "mysql"
      instance_class = "db.t3.micro"
      allocated_storage = 20
      name     = "appdb"
      username = "admin"
      password = var.db_password
    }
    
    resource "aws_db_instance" "secondary_rds" {
      provider = aws.secondary
      replicate_source_db = aws_db_instance.primary_rds.arn
    }
  8. 8
    terraform# Commands
    terraform init
    terraform validate
    terraform plan -var="primary_region=us-east-1" -var="secondary_region=us-west-2" -var="ami_id=ami-0abcd1234efgh5678" -var="zone_id=Z123456789" -var="db_password=SuperSecret123"
    terraform apply -auto-approve

Validate and operate

  1. 1Add Route 53 health checks for failover between regions.
  2. 2Enable CloudWatch metrics, logs, and alarms for ASG, ALB, and RDS.
  3. 3Document rollback, scaling, and disaster-recovery procedures.
  4. 4Test failover by simulating primary region outage and verifying secondary takeover.

Tool Stack Used

  • ☁️AWS
  • πŸ—οΈTerraform
  • πŸ”§Route 53
  • πŸ”§Auto Scaling
  • πŸ”§Application Load Balancer
  • πŸ”§S3 Replication
  • πŸ”§RDS Read Replica
  • πŸ“ŠMonitoring