rds (terraform)

Introduction

Serverless v2 (intro)

A database has a cluster and one o more instances:

DB cluster name: "${local.env}-${local.ci}-cluster"

DB instance name: "${local.env}-${local.ci}-instance-1"


Reference

Terraform migration from Serverless v1 to v2 

https://www.reddit.com/r/Terraform/comments/zrvs1x/terraform_with_aurora_serverless_v2/ 

Easier to understand indications  for upgrading Serverless v1 to v2

https://stackoverflow.com/a/71989216/1323562 

Sample: Upgrade Amazon Aurora Serverless v1 to Serverless v2

With Terraform "This is not possible. AWS clear states, you should do snapshot first. Restore on provisioned instance, upgrade to 14.x and then you can add a server less V2 instance reader . you can fail over it if you like to have it like writer. Then you can import in Terraform. But you need to have two resources, cluster and at least 1 instance (in your case V2)."


With the AWS console (Serverless v1 to v2)

10) In RDS > Databases

[Modify] DB cluster identifier, add suffix "-v1", eg:

"env-ci-cluster-v1"

[Continue]

"Apply immediatly"

[Modify cluster]

Wait until 'Status' changes to 'Availale'


20) Amazon RDS, select DB

[Actions >Take snapshot]

Choose Snapshot type : "DB cluster"

DB cluster: eg: env-ci-cluster

Snapshot name: v1-TICKET-N

[Take snapshot]

Wait until it finishes. Refresh the snapshots view from time to time.


30) Choose the snapshot & "Actions>Restore snapshot"

Capacity type: Provisioned

Avaiable versions: default major version 13, eg: 13.12

DB instance identifier: "env-ci-instance-1"

DB instance class: Serverless v2

Virtual Private cloud (VPC): <the same one where the original database was>

DB subnet group: env-ci-rds-subnet-group

VPC Security Group: env-ci-rds-sg (leave only this one, remove 'default' if was automatically added)

[Restore DB cluster] (might take ~15 minutes)


40) [Refresh] until the DB cluster changes to 'Available'

Note: Database doesn't need to be ready, only the cluster!


50) Select the cluster & [Modify]

DB engine version: Choose the default for major version 13, eg: 13.12

DB cluster identifier: env-ci-cluster

[Continue]

"Apply immediatly"

[Modify cluster] (might take ~20 minutes)


[60] Once the cluster and database have status 'Available', select the DATABASE

and choose [Modify]

DB instance class: Serverless v2

[Continue] button

Apply immediately

[Modify DB instance] button

Wait for status change to 'Available'


With terraform (Serverless v1 to v2)

Now that the database is already Serverless v2, lets remove the v1 cluster resource from terraform and import the v2 cluster and instance.


a) Remove the Serverless v1 RDS cluster

#resource "aws_rds_cluster" "default"


b) Add the Serverless v2 RDS Cluster

Note: Use the same cluster id, so that Terraform is able to atomatically refresh the new cluster

# RDS DB Cluster (Serverless v2) #### ####

# - Query Editor (Data API) w/ PostgeSQL Serverless v2 > https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.Aurora_Fea_Regions_DB-eng.Feature.Data_API.html#Concepts.Aurora_Fea_Regions_DB-eng.Feature.Data_API.apg

resource "aws_rds_cluster" "default" {

  lifecycle {

    ignore_changes = [

      availability_zones,

      engine_version #Comment line for upgrading DB version

    ]

  }


  allow_major_version_upgrade   = true #(Optional) allow major engine version upgrades when changing engine versions

  apply_immediately             = true #(Optional) whether any cluster modifications are applied immediately, or during the next maintenance window

  availability_zones            = var.rds_availability_zones

  cluster_identifier            = var.cluster_identifier

  backup_retention_period       = var.backup_retention_period

  copy_tags_to_snapshot         = true

  database_name                 = var.database_name

  db_subnet_group_name          = aws_db_subnet_group.rds_subnet_group.name #NOTE: This must match the db_subnet_group_name specified on every aws_rds_cluster_instance in the cluster

  delete_automated_backups      = false        #(Optional) Specifies whether to remove automated backups immediately after the DB cluster is deleted

  deletion_protection           = true         #(Optional) The database can't be deleted when this value is set

  enable_http_endpoint          = var.enable_http_endpoint

  enable_local_write_forwarding = false

  enabled_cloudwatch_logs_exports = ["postgresql"]

  engine_mode                   = var.engine_mode #"provisioned" for Serverless v2

  engine_version                = var.engine_version

  engine                        = var.engine

  master_username               = var.master_username

  master_password               = var.cluster_master_password

  serverlessv2_scaling_configuration {

    max_capacity = var.rds_cluster_max_capacity #Detaults to 16. 1 to 128 in increments of 0.5

    min_capacity = var.rds_cluster_min_capacity #0.5 to 128 in increments of 0.5

  }

  skip_final_snapshot    = var.skip_final_snapshot

  vpc_security_group_ids = [var.sg_database_id]

}



# CloudWatch log group for RDS cluster (enabled_cloudwatch_logs_exports = ["postgresql"])

resource "aws_cloudwatch_log_group" "cluster_log" {

  name              = "/aws/rds/cluster/${aws_rds_cluster.regional.cluster_identifier}/postgresql"

  retention_in_days = var.log_retention_in_days

}



c) Add at least one Serverless v2 RDS Cluster instance

# RDS DB Cluster Instance (Serverless v2) #### ####

resource "aws_rds_cluster_instance" "instance_1" {

  apply_immediately          = true

  auto_minor_version_upgrade = true

  #availability_zone       #(Optional, Computed, Forces new resource) EC2 Availability Zone that the DB instance is created in.

  #ca_cert_identifier

  cluster_identifier    = aws_rds_cluster.default.id

  copy_tags_to_snapshot = true

  #custom_iam_instance_profile

  #db_parameter_group_name

  #db_subnet_group_name

  engine_version = aws_rds_cluster.default.engine_version

  engine         = aws_rds_cluster.default.engine

  #identifier_prefix

  identifier     = "${local.env}-${local.ci}-instance-1" #(Optional, Forces new resource) Identifier for the RDS instance, if omitted, Terraform will assign a random, unique identifier.

  instance_class = "db.serverless"

  #monitoring_interval 

  #monitoring_role_arn

  #performance_insights_enabled

  #performance_insights_kms_key_id

  #performance_insights_retention_period

  #preferred_backup_window

  #preferred_maintenance_window 

  promotion_tier      = 1

  publicly_accessible = false

  #tags #(Optional) Map of tags to assign to the instance. If configured with a provider default_tags configuration block present, tags with matching keys will overwrite those defined at the provider-level.

}



d) Import the Serverless v2 instance(s) into the terraform aws_rds_cluster_instance resource(s)

In main.tf, add the block:

import {

  id = "${local.env}-${local.ci}-instance-1"

  to = module.rds.aws_rds_cluster_instance.instance_1

}