3
votes

I have a db instance in aws region us-east-1 running through terraform code. Now I want to create a read replica of that db in another region: us-west-1.

This is the code:

# PostgreSQL RDS App Instance
module "rds" {
  source = "[email protected]:****"

  name           = var.rds_name_app
  engine         = var.rds_engine_app
  engine_version = var.rds_engine_version_app
  family         = var.rds_family_app
  instance_class = var.rds_instance_class_app

  # WARNING: 'terraform taint random_string.rds_password' must be run prior to recreating the DB if it is destroyed
  password                   = random_string.rds_password.result
  port                       = var.rds_port_app
  security_groups            = [aws_security_group.rds_app.id]
  subnets                    = [module.vpc.public_subnets]
  auto_minor_version_upgrade = var.rds_auto_minor_version_upgrade_app
  backup_retention_period    = var.rds_backup_retention_period_app
  backup_window              = var.rds_backup_window_app
  maintenance_window         = var.rds_maintenance_window_app
  environment                = var.environment
  kms_key_id                 = aws_kms_key.rds.arn
  multi_az                   = var.rds_multi_az_app
  notification_topic         = var.rds_notification_topic_app
  publicly_accessible        = var.rds_publicly_accessible_app
  storage_encrypted          = var.rds_storage_encrypted_app
  storage_size               = var.rds_storage_size_app
  storage_type               = var.rds_storage_type_app
  apply_immediately          = true
}

# PostgreSQL RDS Read Replica Instance
module "rds_replica" {
  source = "[email protected]:****"

  name           = var.rds_name_app_replica
  engine         = var.rds_engine_app_replica
  engine_version = var.rds_engine_version_app_replica
  family         = var.rds_family_app_replica
  instance_class = var.rds_instance_class_app_replica

  read_replica = "true"
  source_db    = module.rds.db_instance

  # NOTE: Using same password as primary 'rds_app' instance generated above
  password                   = ""
  port                       = var.rds_port_app_replica
  security_groups            = [aws_security_group.rds_app.id]
  subnets                    = [module.vpc.public_subnets]
  auto_minor_version_upgrade = var.rds_auto_minor_version_upgrade_app_replica
  backup_retention_period    = var.rds_backup_retention_period_app_replica
  backup_window              = var.rds_backup_window_app_replica
  maintenance_window         = var.rds_maintenance_window_app_replica
  environment                = var.environment
  kms_key_id                 = aws_kms_key.rds.arn
  multi_az                   = var.rds_multi_az_app_replica
  notification_topic         = var.rds_notification_topic_app_replica
  publicly_accessible        = var.rds_publicly_accessible_app_replica
  storage_encrypted          = var.rds_storage_encrypted_app_replica
  storage_size               = var.rds_storage_size_app_replica
  storage_type               = var.rds_storage_type_app_replica
  apply_immediately          = true
}

Also, this is my main.tf:

# pinned provider versions

provider "random" {
  version = "~> 2.3.0"
}

provider "template" {
  version = "~> 2.1.2"
}

provider "archive" {
  version = "~> 1.1"
}

# default provider
provider "aws" {
  version             = "~> 2.44"
  allowed_account_ids = [var.aws_account_id]
  region              = "us-east-1"
}

# remote state
terraform {
  required_version = "0.12.24"

  backend "s3" {
    key     = "terraform.dev.tfstate"
    encrypt = "true"
    bucket  = "dev-tfstate"
    region  = "us-east-1"
  }
}
  1. Is this part correctly defined to tell terraform I am creating a replica of the pervious database?:
read_replica = "true"
source_db    = module.rds.db_instance
  1. I am not sure where and how to specify that I want my replica to be created in another region?

Someone please let me know!

  • I added solution which Grzegorz Oledzki gave in the answers.. and it worked.
  • However when I run plan it is not telling me anywhere that it will create in us-west-1.. how can I confirm that?

part of plan:

module.rds_replica.aws_db_instance.db_instance will be created
  + resource "aws_db_instance" "db_instance" {
      + address                               = (known after apply)
      + allocated_storage                     = 200
      + allow_major_version_upgrade           = false
      + apply_immediately                     = true
      + arn                                   = (known after apply)
      + auto_minor_version_upgrade            = true
      + availability_zone                     = (known after apply)
      + backup_retention_period               = 0
      + backup_window                         = "***"
      + ca_cert_identifier                    = (known after apply)
      + character_set_name                    = (known after apply)
      + copy_tags_to_snapshot                 = true
      + db_subnet_group_name                  = (known after apply)
      + delete_automated_backups              = true
      + deletion_protection                   = false
      + endpoint                              = (known after apply)
      + engine                                = "postgres"
      + engine_version                        = "9.5.22"
      + final_snapshot_identifier             = "app-replica-final-snapshot"
      + hosted_zone_id                        = (known after apply)
      + iam_database_authentication_enabled   = false
      + id                                    = (known after apply)
      + identifier                            = (known after apply)
      + identifier_prefix                     = "app-replica-"
      + instance_class                        = "db.t2.micro"
      + iops                                  = 0
      + kms_key_id                            = "arn****"
      + license_model                         = (known after apply)
      + maintenance_window                    = "sat:05:09-sat:05:39"
      + max_allocated_storage                 = 0
      + monitoring_interval                   = 0
      + monitoring_role_arn                   = (known after apply)
      + multi_az                              = false
      + name                                  = (known after apply)
      + option_group_name                     = (known after apply)
      + parameter_group_name                  = (known after apply)
      + performance_insights_enabled          = false
      + performance_insights_kms_key_id       = (known after apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = 5432
      + publicly_accessible                   = false
      + replicas                              = (known after apply)
      + replicate_source_db                   = "arn****"
      + resource_id                           = (known after apply)
      + skip_final_snapshot                   = true
      + status                                = (known after apply)
      + storage_encrypted                     = true
      + storage_type                          = "gp2"

see it does say anything about region?

1
You need two aws providers configured, one for each region. source_db needs to be a full ARN when setting up cross-region.jordanm
@jordanm thank you, but can you also help me with the code like how to write it exactly, because im new to tfmgb
@jordanm thanks.. but where do I specify that my read replica needs to be in west-1?mgb

1 Answers

5
votes

(I have never done it myself, but...)

It looks like the docs for AWS Terraform provider have taken that possibility into account.

I haven't tested that at all, but as I read it:

  • you can create a separate Terraform configuration or within the same configuration declare another aws provider under different alias, let the other provider use us-west-1 as the region:
# The default provider you already have
provider "aws" {
  region = "us-east-1"
}
# Thew new one
provider "aws" {
  region = "us-west-1"
  alias = "west"
}
  • and there create a read replica with replicate_source_db having the ARN of the writer/main instance. And here again you are using modules, so the trick needs to be applied when "calling" the rds_replica module to pass aws.west as aws and let it use as the main instance ARN as replicate_source_db. Something like: (again untested)
module "rds_replica" {
  source = "[email protected]:****"
  ...
  providers = {
    aws = aws.west
  }

  # point to the main instance's ARN
  replicate_source_db = module.rds.db_instance.arn
}