In this AWS Database Blog, they assert that
You can set up Amazon RDS in a Single-AZ database (DB) instance or a Multi-AZ DB instance for high availability requirements
and that you can
...modify existing Single-AZ instances to become Multi-AZ deployments.
Furthermore,
...you can create a Multi-AZ read replica, synchronize it with your Single-AZ DB instance, and then promote it as your primary DB instance to minimize latencies during conversion.
Additionally, in v1.32 of the official AWS VPC Module there are multiple references to the usage of single_nat_gateway, particularly
If single_nat_gateway = true, then all private subnets will route their Internet traffic through this single NAT gateway.
and in the official RDS module, multi_az
is shown as defaulting to false
(link).
Despite this, I am getting the following error
╷
│ Error: DBSubnetGroupDoesNotCoverEnoughAZs: The DB subnet group doesn't meet Availability Zone (AZ) coverage requirement. Current AZ coverage: us-west-2a. Add subnets to cover at least 2 AZs.
│ status code: 400, request id: *****
│
│ with module.rds.module.db_subnet_group.aws_db_subnet_group.this[0],
│ on .terraform/modules/rds/modules/db_subnet_group/main.tf line 8, in resource "aws_db_subnet_group" "this":
│ 8: resource "aws_db_subnet_group" "this" {
when attempting to terraform apply
this main.tf
configuration:
module "rds" {
source = "terraform-aws-modules/rds/aws"
version = "~> 3.4.0"
identifier = "${var.env}-${var.user}-${local.db_name}"
engine = var.postgres.engine
engine_version = var.postgres.engine_version
family = var.postgres.family
major_engine_version = var.postgres.major_engine_version
instance_class = var.postgres.instance_class
allocated_storage = var.postgres.allocated_storage
max_allocated_storage = var.postgres.max_allocated_storage
storage_encrypted = var.postgres.storage_encrypted
password = random_password.password.result
port = var.postgres.port
multi_az = false
subnet_ids = [data.aws_subnet.priv1.id]
vpc_security_group_ids = [module.db_security_group.security_group_id]
maintenance_window = var.postgres.maintenance_window
backup_window = var.postgres.backup_window
enabled_cloudwatch_logs_exports = var.postgres.enabled_cloudwatch_logs_exports
backup_retention_period = var.postgres.backup_retention_period
skip_final_snapshot = var.postgres.skip_final_snapshot
deletion_protection = var.postgres.deletion_protection
performance_insights_enabled = var.postgres.performance_insights_enabled
performance_insights_retention_period = var.postgres.performance_insights_retention_period
create_monitoring_role = var.postgres.create_monitoring_role
monitoring_role_name = "${var.env}-${var.user}-${var.postgres.monitoring_role_name}"
monitoring_interval = var.postgres.monitoring_interval
snapshot_identifier = var.postgres.snapshot_identifier
iam_database_authentication_enabled = var.postgres.iam_auth
apply_immediately = true
tags = {
Name = "${var.env}-${var.user}-rds"
Terraform = "true"
Environment = var.env
Created = timestamp()
}
}
with this postgres
variable defined in my terraform.tfvars
:
postgres = {
db_name = "postgres-db"
# All available versions: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts
engine = "postgres"
engine_version = "11.12"
family = "postgres11" # DB parameter group
major_engine_version = "11" # DB option group
instance_class = "db.t2.micro"
allocated_storage = 100
max_allocated_storage = 200
storage_encrypted = false
port = 5432
multi_az = false
maintenance_window = "Mon:00:00-Mon:03:00"
backup_window = "03:00-06:00"
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
backup_retention_period = 0
skip_final_snapshot = true
deletion_protection = false
performance_insights_enabled = false
performance_insights_retention_period = 7
create_monitoring_role = true
monitoring_role_name = "monitoring_role"
monitoring_interval = 60
snapshot_identifier = "arn:aws:rds:us-west-2:999999999999:snapshot:rds-ss"
iam_auth = true
}
Similar questions on SO seem to all have answers with the theme that you must provide multiple availability zones, which implies at least two subnets, which - if you are creating them manually as private subnets - would then each need their own NAT gateway. That seems unnecessarily expensive and constraining, especially for development and test environments.
How can I deploy a single-az RDS Postgres instance with these components?
A DB subnet group has to have multiple subnets. That's a requirement of RDS that you can't bypass. Even if you are only deploying a single instance, if that entire availability zone were to go down, Amazon RDS would automatically spin up a new instance in one of the other availability zones you have specified. That's one of the managed database services that you get automatically with Amazon RDS.
So even if you are deploying a single-az instance, you have to specify multiple availability zones in the DB subnet group.