From f554047a95392ec69d2925eee355d603234c51f9 Mon Sep 17 00:00:00 2001 From: Arabinda Pani <22154314+catcharbind@users.noreply.github.com> Date: Mon, 16 Aug 2021 15:18:35 -0700 Subject: [PATCH 1/7] updates related to Aurora global DB unplanned failover --- .gitignore | 5 ++++- deploy/main.tf | 22 +++++++++++--------- deploy/variables.tf | 13 ++++++++++++ main.tf | 50 ++++++++++++++++++++++++--------------------- variables.tf | 6 ++++++ 5 files changed, 62 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 1651bdd..707948e 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,7 @@ terraform.rc .terraform.lock.hcl -backend.hcl \ No newline at end of file +backend.hcl + +# vscode directory +.vscode/* \ No newline at end of file diff --git a/deploy/main.tf b/deploy/main.tf index a779dac..c5efc17 100644 --- a/deploy/main.tf +++ b/deploy/main.tf @@ -71,14 +71,16 @@ module "aurora" { region = var.region sec_region = var.sec_region #vpc_id = module.aurora_vpc.vpc_id - Private_subnet_ids_p = [module.aurora_vpc_p.private_subnet_1a_id, module.aurora_vpc_p.private_subnet_2a_id, module.aurora_vpc_p.private_subnet_3a_id] - Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.private_subnet_1a_id, module.aurora_vpc_s.private_subnet_2a_id, module.aurora_vpc_s.private_subnet_3a_id] : null - engine = var.engine - engine_version_pg = var.engine_version_pg - engine_version_mysql = var.engine_version_mysql - password = var.password - setup_globaldb = var.setup_globaldb - tags = module.vpc_label.tags - monitoring_interval = var.monitoring_interval - storage_encrypted = var.storage_encrypted + Private_subnet_ids_p = [module.aurora_vpc_p.PrivateSubnet1AID, module.aurora_vpc_p.PrivateSubnet2AID, module.aurora_vpc_p.PrivateSubnet3AID] + Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.PrivateSubnet1AID, module.aurora_vpc_s.PrivateSubnet2AID, module.aurora_vpc_s.PrivateSubnet3AID] : null + engine = var.engine + engine_version_pg = var.engine_version_pg + engine_version_mysql = var.engine_version_mysql + username = var.username + password = var.password + setup_globaldb = var.setup_globaldb + setup_as_secondary = var.setup_as_secondary + tags = module.vpc_label.tags + monitoring_interval = var.monitoring_interval + storage_encrypted = var.storage_encrypted } \ No newline at end of file diff --git a/deploy/variables.tf b/deploy/variables.tf index 2370158..c50a745 100644 --- a/deploy/variables.tf +++ b/deploy/variables.tf @@ -24,6 +24,13 @@ variable "delimiter" { description = "delimiter, which could be used between name, namespace and env" default = "-" } + +variable "username" { + description = "Master DB username" + type = string + default = "root" +} + variable "password" { default = "" description = "If no password is provided, a random password will be generated" @@ -57,6 +64,12 @@ variable "setup_globaldb" { default = false } +variable "setup_as_secondary" { + description = "Setup Aurora Global Database Secondary cluster after an unplanned failover" + type = bool + default = false +} + variable "monitoring_interval" { description = "Enhanced Monitoring interval in seconds" type = number diff --git a/main.tf b/main.tf index 1e010d4..67a7b3a 100644 --- a/main.tf +++ b/main.tf @@ -148,9 +148,9 @@ resource "aws_rds_cluster" "primary" { availability_zones = [data.aws_availability_zones.region_p.names[0], data.aws_availability_zones.region_p.names[1], data.aws_availability_zones.region_p.names[2]] db_subnet_group_name = aws_db_subnet_group.private_p.name port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port - database_name = var.database_name - master_username = var.username - master_password = var.password == "" ? random_password.master_password.result : var.password + database_name = var.setup_as_secondary ? null : var.database_name + master_username = var.setup_as_secondary ? null : var.username + master_password = var.setup_as_secondary ? null : (var.password == "" ? random_password.master_password.result : var.password) db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_p.id backup_retention_period = var.backup_retention_period preferred_backup_window = var.preferred_backup_window @@ -159,6 +159,11 @@ resource "aws_rds_cluster" "primary" { apply_immediately = true skip_final_snapshot = var.skip_final_snapshot tags = var.tags + depends_on = [ + # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory + # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destory to work + #aws_rds_cluster_instance.secondary, + ] lifecycle { ignore_changes = [ replication_source_identifier, @@ -203,8 +208,10 @@ resource "aws_rds_cluster" "secondary" { apply_immediately = true skip_final_snapshot = var.skip_final_snapshot tags = var.tags - depends_on = [ - aws_rds_cluster.primary, + depends_on = [ + # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory + # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destory to work + aws_rds_cluster_instance.primary, ] lifecycle { ignore_changes = [ @@ -215,24 +222,21 @@ resource "aws_rds_cluster" "secondary" { # Secondary Cluster Instances resource "aws_rds_cluster_instance" "secondary" { - count = var.setup_globaldb ? 1 : 0 - provider = aws.secondary - identifier = "${var.name}-${var.sec_region}-${count.index + 1}" - cluster_identifier = aws_rds_cluster.secondary[0].id - engine = var.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - auto_minor_version_upgrade = false - instance_class = var.instance_class - db_subnet_group_name = aws_db_subnet_group.private_s[0].name - db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_s[0].id - performance_insights_enabled = true - monitoring_interval = var.monitoring_interval - monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn - apply_immediately = true - tags = var.tags - depends_on = [ - aws_rds_cluster.primary, - ] + count = var.setup_globaldb ? 1 : 0 + provider = aws.secondary + identifier = "${var.name}-${var.sec_region}-${count.index + 1}" + cluster_identifier = aws_rds_cluster.secondary[0].id + engine = var.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + auto_minor_version_upgrade = false + instance_class = var.instance_class + db_subnet_group_name = aws_db_subnet_group.private_s[0].name + db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_s[0].id + performance_insights_enabled = true + monitoring_interval = var.monitoring_interval + monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn + apply_immediately = true + tags = var.tags } ############################# diff --git a/variables.tf b/variables.tf index 3944190..12567a3 100644 --- a/variables.tf +++ b/variables.tf @@ -133,6 +133,12 @@ variable "setup_globaldb" { default = false } +variable "setup_as_secondary" { + description = "Setup Aurora Global Database Secondary cluster after an unplanned failover" + type = bool + default = false +} + variable "replica_scale_enabled" { description = "Whether to enable autoscaling for Aurora read replica auto scaling" type = bool From ac4f06ae7b8c20e9eb0cd569ede8bb9872ef2351 Mon Sep 17 00:00:00 2001 From: lcouto Date: Wed, 11 Aug 2021 09:51:43 -0400 Subject: [PATCH 2/7] adding more config options --- locals.tf | 7 +++++++ main.tf | 34 ++++++++++++++++++---------------- variables.tf | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/locals.tf b/locals.tf index 95abe77..15f1d82 100644 --- a/locals.tf +++ b/locals.tf @@ -114,4 +114,11 @@ locals { value = 1 apply_method = "immediate" }] + + logs_set = compact([ + var.enable_audit_log ? "audit" : "", + var.enable_error_log ? "error" : "", + var.enable_general_log ? "general" : "", + var.enable_slowquery_log ? "slowquery" : "", + ]) } \ No newline at end of file diff --git a/main.tf b/main.tf index 67a7b3a..a9af802 100644 --- a/main.tf +++ b/main.tf @@ -158,6 +158,8 @@ resource "aws_rds_cluster" "primary" { kms_key_id = var.storage_encrypted ? aws_kms_key.kms_p[0].arn : null apply_immediately = true skip_final_snapshot = var.skip_final_snapshot + snapshot_identifier = var.snapshot_identifier != "" ? var.snapshot_identifier : null + enabled_cloudwatch_logs_exports = local.logs_set tags = var.tags depends_on = [ # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory @@ -172,21 +174,21 @@ resource "aws_rds_cluster" "primary" { } resource "aws_rds_cluster_instance" "primary" { - count = 2 - provider = aws.primary - identifier = "${var.name}-${var.region}-${count.index + 1}" - cluster_identifier = aws_rds_cluster.primary.id - engine = aws_rds_cluster.primary.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - auto_minor_version_upgrade = var.setup_globaldb ? false : var.auto_minor_version_upgrade - instance_class = var.instance_class - db_subnet_group_name = aws_db_subnet_group.private_p.name - db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_p.id - performance_insights_enabled = true - monitoring_interval = var.monitoring_interval - monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn - apply_immediately = true - tags = var.tags + count = var.primary_instance_count + provider = aws.primary + identifier = "${var.name}-${var.region}-${count.index + 1}" + cluster_identifier = aws_rds_cluster.primary.id + engine = aws_rds_cluster.primary.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + auto_minor_version_upgrade = var.setup_globaldb ? false : var.auto_minor_version_upgrade + instance_class = var.instance_class + db_subnet_group_name = aws_db_subnet_group.private_p.name + db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_p.id + performance_insights_enabled = true + monitoring_interval = var.monitoring_interval + monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn + apply_immediately = true + tags = var.tags } # Secondary Aurora Cluster @@ -222,7 +224,7 @@ resource "aws_rds_cluster" "secondary" { # Secondary Cluster Instances resource "aws_rds_cluster_instance" "secondary" { - count = var.setup_globaldb ? 1 : 0 + count = var.setup_globaldb ? var.secondary_instance_count : 0 provider = aws.secondary identifier = "${var.name}-${var.sec_region}-${count.index + 1}" cluster_identifier = aws_rds_cluster.secondary[0].id diff --git a/variables.tf b/variables.tf index 12567a3..cfb006b 100644 --- a/variables.tf +++ b/variables.tf @@ -43,6 +43,16 @@ variable "allowed_security_groups" { default = [] } +variable "primary_instance_count" { + description = "instance count for primary cluster" + default = 2 +} + +variable "secondary_instance_count" { + description = "instance count for secondary cluster" + default = 1 +} + variable "instance_class" { type = string description = "Instance type to use at replica instance" @@ -160,5 +170,30 @@ variable "monitoring_interval" { validation { condition = contains([0, 1, 5, 10, 15, 30, 60], var.monitoring_interval) error_message = "Valid values for var: monitoring_interval are (0, 1, 5, 10, 15, 30, 60)." - } + } } + +variable "snapshot_identifier" { + description = "id of snapshot to restore, if you do not want to restore a db, leave the default empty string." + default = "" +} + +variable "enable_audit_log" { + description = "Enable audit log." + default = false +} + +variable "enable_error_log" { + description = "Enable error log." + default = true +} + +variable "enable_general_log" { + description = "Enable general log." + default = true +} + +variable "enable_slowquery_log" { + description = "Enable slowquery log." + default = true +} \ No newline at end of file From db948b0c88cce60a1430ec3b47e54f36db687243 Mon Sep 17 00:00:00 2001 From: lcouto Date: Wed, 11 Aug 2021 09:55:31 -0400 Subject: [PATCH 3/7] disables cloudwatch log exports by default --- variables.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/variables.tf b/variables.tf index cfb006b..86c417e 100644 --- a/variables.tf +++ b/variables.tf @@ -185,15 +185,15 @@ variable "enable_audit_log" { variable "enable_error_log" { description = "Enable error log." - default = true + default = false } variable "enable_general_log" { description = "Enable general log." - default = true + default = false } variable "enable_slowquery_log" { description = "Enable slowquery log." - default = true + default = false } \ No newline at end of file From c4f86ba9caec8519bf6a1c80a5c0a9ed56b08cbd Mon Sep 17 00:00:00 2001 From: Arabinda Pani <22154314+catcharbind@users.noreply.github.com> Date: Mon, 16 Aug 2021 20:49:32 -0700 Subject: [PATCH 4/7] various updates # 2 --- README.md | 2 +- deploy/main.tf | 34 ++++---- deploy/variables.tf | 10 +++ locals.tf | 9 +- main.tf | 201 ++++++++++++++++++++++++++++++++++++++++---- outputs.tf | 24 +++--- variables.tf | 25 +++--- 7 files changed, 241 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 246dbef..bea6ca6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ > Note: This module is in alpha state and is likely to contain bugs and updates may introduce breaking changes. It is not recommended for production use at this time. # Terraform Amazon Aurora -Authors: David Wright (dwright@hashicorp.com) and Tony Vattahil (tonynv@amazon.com) +Authors: David Wright (dwright@hashicorp.com), Tony Vattahil (tonynv@amazon.com) and Arabinda Pani (arabindp@amazon.com) To deploy the Terraform Amazon Aurora module, do the following: diff --git a/deploy/main.tf b/deploy/main.tf index c5efc17..f5ea4c4 100644 --- a/deploy/main.tf +++ b/deploy/main.tf @@ -67,20 +67,22 @@ module "aurora_vpc_s" { ###################################### module "aurora" { - source = "../" - region = var.region - sec_region = var.sec_region - #vpc_id = module.aurora_vpc.vpc_id - Private_subnet_ids_p = [module.aurora_vpc_p.PrivateSubnet1AID, module.aurora_vpc_p.PrivateSubnet2AID, module.aurora_vpc_p.PrivateSubnet3AID] - Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.PrivateSubnet1AID, module.aurora_vpc_s.PrivateSubnet2AID, module.aurora_vpc_s.PrivateSubnet3AID] : null - engine = var.engine - engine_version_pg = var.engine_version_pg - engine_version_mysql = var.engine_version_mysql - username = var.username - password = var.password - setup_globaldb = var.setup_globaldb - setup_as_secondary = var.setup_as_secondary - tags = module.vpc_label.tags - monitoring_interval = var.monitoring_interval - storage_encrypted = var.storage_encrypted + source = "../" + region = var.region + sec_region = var.sec_region + #vpc_id = module.aurora_vpc.vpc_id + Private_subnet_ids_p = [module.aurora_vpc_p.PrivateSubnet1AID, module.aurora_vpc_p.PrivateSubnet2AID, module.aurora_vpc_p.PrivateSubnet3AID] + Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.PrivateSubnet1AID, module.aurora_vpc_s.PrivateSubnet2AID, module.aurora_vpc_s.PrivateSubnet3AID] : null + engine = var.engine + engine_version_pg = var.engine_version_pg + engine_version_mysql = var.engine_version_mysql + username = var.username + password = var.password + setup_globaldb = var.setup_globaldb + setup_as_secondary = var.setup_as_secondary + tags = module.vpc_label.tags + monitoring_interval = var.monitoring_interval + storage_encrypted = var.storage_encrypted + primary_instance_count = var.primary_instance_count + secondary_instance_count = var.secondary_instance_count } \ No newline at end of file diff --git a/deploy/variables.tf b/deploy/variables.tf index c50a745..dc4d420 100644 --- a/deploy/variables.tf +++ b/deploy/variables.tf @@ -84,4 +84,14 @@ variable "storage_encrypted" { description = "Specifies whether the underlying storage layer should be encrypted" type = bool default = false +} + +variable "primary_instance_count" { + description = "instance count for primary cluster" + default = 2 +} + +variable "secondary_instance_count" { + description = "instance count for secondary cluster" + default = 1 } \ No newline at end of file diff --git a/locals.tf b/locals.tf index 15f1d82..9fa9528 100644 --- a/locals.tf +++ b/locals.tf @@ -116,9 +116,10 @@ locals { }] logs_set = compact([ - var.enable_audit_log ? "audit" : "", - var.enable_error_log ? "error" : "", - var.enable_general_log ? "general" : "", - var.enable_slowquery_log ? "slowquery" : "", + var.enable_audit_log && (var.engine != "aurora-postgresql") ? "audit" : "", + var.enable_error_log && (var.engine != "aurora-postgresql") ? "error" : "", + var.enable_general_log && (var.engine != "aurora-postgresql") ? "general" : "", + var.enable_slowquery_log && (var.engine != "aurora-postgresql") ? "slowquery" : "", + var.enable_postgresql_log && (var.engine == "aurora-postgresql") ? "postgresql" : "", ]) } \ No newline at end of file diff --git a/main.tf b/main.tf index a9af802..1daac13 100644 --- a/main.tf +++ b/main.tf @@ -92,22 +92,22 @@ resource "aws_db_subnet_group" "private_s" { ########### resource "aws_kms_key" "kms_p" { - provider = aws.primary - count = var.storage_encrypted ? 1 : 0 - description = "KMS key for Aurora Storage Enryption" - tags = var.tags - # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored. + provider = aws.primary + count = var.storage_encrypted ? 1 : 0 + description = "KMS key for Aurora Storage Enryption" + tags = var.tags + # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored for your production workload. lifecycle { prevent_destroy = true } } resource "aws_kms_key" "kms_s" { - provider = aws.secondary - count = var.setup_globaldb && var.storage_encrypted ? 1 : 0 - description = "KMS key for Aurora Storage Enryption" - tags = var.tags - # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored. + provider = aws.secondary + count = var.setup_globaldb && var.storage_encrypted ? 1 : 0 + description = "KMS key for Aurora Storage Enryption" + tags = var.tags + # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored for your production workload. lifecycle { prevent_destroy = true } @@ -148,9 +148,9 @@ resource "aws_rds_cluster" "primary" { availability_zones = [data.aws_availability_zones.region_p.names[0], data.aws_availability_zones.region_p.names[1], data.aws_availability_zones.region_p.names[2]] db_subnet_group_name = aws_db_subnet_group.private_p.name port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port - database_name = var.setup_as_secondary ? null : var.database_name - master_username = var.setup_as_secondary ? null : var.username - master_password = var.setup_as_secondary ? null : (var.password == "" ? random_password.master_password.result : var.password) + database_name = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.database_name + master_username = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.username + master_password = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : (var.password == "" ? random_password.master_password.result : var.password) db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_p.id backup_retention_period = var.backup_retention_period preferred_backup_window = var.preferred_backup_window @@ -209,6 +209,7 @@ resource "aws_rds_cluster" "secondary" { kms_key_id = var.storage_encrypted ? aws_kms_key.kms_s[0].arn : null apply_immediately = true skip_final_snapshot = var.skip_final_snapshot + enabled_cloudwatch_logs_exports = local.logs_set tags = var.tags depends_on = [ # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory @@ -324,8 +325,8 @@ resource "aws_db_parameter_group" "aurora_db_parameter_group_s" { ############################## resource "aws_sns_topic" "default_p" { - provider = aws.primary - name = "rds-events" + provider = aws.primary + name = "aurora-monitoring-sns" } resource "aws_db_event_subscription" "default_p" { @@ -345,9 +346,9 @@ resource "aws_db_event_subscription" "default_p" { } resource "aws_sns_topic" "default_s" { - count = var.setup_globaldb ? 1 : 0 - provider = aws.secondary - name = "rds-events" + count = var.setup_globaldb ? 1 : 0 + provider = aws.secondary + name = "aurora-monitoring-sns" } resource "aws_db_event_subscription" "default_s" { @@ -365,4 +366,168 @@ resource "aws_db_event_subscription" "default_s" { "maintenance", "notification", ] +} + +resource "aws_cloudwatch_metric_alarm" "cpu_util_p" { + count = var.primary_instance_count + provider = aws.primary + alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance CPU Utilization" + metric_name = "CPUUtilization" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "80" + statistic = "Maximum" + unit = "Percent" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } +} + + +resource "aws_cloudwatch_metric_alarm" "free_local_storage_p" { + count = var.primary_instance_count + provider = aws.primary + alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Local Storage Utilization" + metric_name = "FreeLocalStorage" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "5368709120" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } +} + +resource "aws_cloudwatch_metric_alarm" "free_random_access_memory_p" { + count = var.primary_instance_count + provider = aws.primary + alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" + metric_name = "FreeableMemory" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "2147483648" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } +} + +resource "aws_cloudwatch_metric_alarm" "PG_MaxUsedTxIDs_p" { + count = var.engine == "aurora-postgresql" ? 1 : 0 + provider = aws.primary + alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.primary.id}" + alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" + metric_name = "MaximumUsedTransactionIDs" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "600000000" + statistic = "Average" + unit = "Count" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBClusterIdentifier = "${aws_rds_cluster.primary.id}" + Role = "WRITER" + } +} + +resource "aws_cloudwatch_metric_alarm" "cpu_util_s" { + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance CPU Utilization" + metric_name = "CPUUtilization" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "80" + statistic = "Maximum" + unit = "Percent" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } +} + + +resource "aws_cloudwatch_metric_alarm" "free_local_storage_s" { + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Local Storage Utilization" + metric_name = "FreeLocalStorage" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "5368709120" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } +} + +resource "aws_cloudwatch_metric_alarm" "free_random_access_memory_s" { + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" + metric_name = "FreeableMemory" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "2147483648" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } +} + +resource "aws_cloudwatch_metric_alarm" "PG_MaxUsedTxIDs_s" { + count = (var.engine == "aurora-postgresql") && var.setup_globaldb ? 1 : 0 + provider = aws.secondary + alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.secondary[0].id}" + alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" + metric_name = "MaximumUsedTransactionIDs" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "600000000" + statistic = "Average" + unit = "Count" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBClusterIdentifier = "${aws_rds_cluster.secondary[0].id}" + Role = "WRITER" + } } \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index 34c5830..335b519 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,63 +1,63 @@ // aws_rds_cluster output "aurora_cluster_arn" { - description = "The ID of the cluster" + description = "The ARN of the Primary Aurora cluster" value = aws_rds_cluster.primary.arn } output "aurora_cluster_id" { - description = "The ID of the cluster" + description = "The ID of the Primary Aurora cluster" value = aws_rds_cluster.primary.id } output "aurora_cluster_resource_id" { - description = "The Resource ID of the cluster" + description = "The Cluster Resource ID of the Primary Aurora cluster" value = aws_rds_cluster.primary.cluster_resource_id } output "aurora_cluster_endpoint" { - description = "The cluster endpoint" + description = "Primary Aurora cluster endpoint" value = aws_rds_cluster.primary.endpoint } output "aurora_cluster_reader_endpoint" { - description = "The cluster reader endpoint" + description = "Primary Aurora cluster reader endpoint" value = aws_rds_cluster.primary.reader_endpoint } // database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "aurora_cluster_database_name" { - description = "Name for an automatically created database on cluster creation" + description = "Name for an automatically created database on Aurora cluster creation" value = var.database_name } output "aurora_cluster_master_password" { - description = "The master password" + description = "Aurora master User password" value = aws_rds_cluster.primary.master_password sensitive = true } output "aurora_cluster_port" { - description = "The port" + description = "Aurora cluster endpoint port" value = aws_rds_cluster.primary.port } output "aurora_cluster_master_username" { - description = "The master username" + description = "Aurora master username" value = aws_rds_cluster.primary.master_username } output "aurora_cluster_hosted_zone_id" { - description = "Route53 hosted zone id of the created cluster" + description = "Route53 hosted zone id of the Primary Aurora cluster" value = aws_rds_cluster.primary.hosted_zone_id } // aws_rds_cluster_instance output "aurora_cluster_instance_endpoints" { - description = "A list of all cluster instance endpoints" + description = "A list of all Primary Aurora cluster instance endpoints" value = aws_rds_cluster_instance.primary.*.endpoint } output "aurora_cluster_instance_ids" { - description = "A list of all cluster instance ids" + description = "A list of all Primary Aurora cluster instance ids" value = aws_rds_cluster_instance.primary.*.id } \ No newline at end of file diff --git a/variables.tf b/variables.tf index 86c417e..df659fe 100644 --- a/variables.tf +++ b/variables.tf @@ -62,8 +62,8 @@ variable "instance_class" { variable "skip_final_snapshot" { type = string description = "skip creating a final snapshot before deleting the DB" - #set the value to false for actual workload - default = true + #set the value to false for production workload + default = true } variable "database_name" { @@ -83,12 +83,6 @@ variable "password" { type = string } -variable "final_snapshot_identifier_prefix" { - description = "The prefix name to use when creating a final snapshot on cluster destroy, appends a random 8 digits to name to ensure it's unique too." - type = string - default = "final" -} - variable "backup_retention_period" { description = "How long to keep backups for (in days)" type = number @@ -174,26 +168,31 @@ variable "monitoring_interval" { } variable "snapshot_identifier" { - description = "id of snapshot to restore, if you do not want to restore a db, leave the default empty string." + description = "id of snapshot to restore. If you do not want to restore a db, leave the default empty string." default = "" } variable "enable_audit_log" { - description = "Enable audit log." + description = "Enable MySQL audit log export to Amazon Cloudwatch." default = false } variable "enable_error_log" { - description = "Enable error log." + description = "Enable MySQL error log export to Amazon Cloudwatch." default = false } variable "enable_general_log" { - description = "Enable general log." + description = "Enable MySQL general log export to Amazon Cloudwatch." default = false } variable "enable_slowquery_log" { - description = "Enable slowquery log." + description = "Enable MySQL slowquery log export to Amazon Cloudwatch." + default = false +} + +variable "enable_postgresql_log" { + description = "Enable PostgreSQL log export to Amazon Cloudwatch." default = false } \ No newline at end of file From c1a6c3c8352a122d561eb806fab802413813273b Mon Sep 17 00:00:00 2001 From: Arabinda Pani <22154314+catcharbind@users.noreply.github.com> Date: Tue, 26 Oct 2021 15:23:43 -0700 Subject: [PATCH 5/7] rebasing and adding missed updates in v0.0.4 --- README.md | 45 ++-- deploy/main.tf | 37 ++-- deploy/variables.tf | 25 ++- main.tf | 387 ++++++++++++++++++----------------- outputs.tf | 21 +- setup_workspace/workspace.tf | 13 +- variables.tf | 29 ++- 7 files changed, 294 insertions(+), 263 deletions(-) diff --git a/README.md b/README.md index bea6ca6..b0460b9 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,31 @@ > Note: This module is in alpha state and is likely to contain bugs and updates may introduce breaking changes. It is not recommended for production use at this time. # Terraform Amazon Aurora -Authors: David Wright (dwright@hashicorp.com), Tony Vattahil (tonynv@amazon.com) and Arabinda Pani (arabindp@amazon.com) +Terraform module for automating deployment of Amazon Aurora and related resources following AWS best practices. + +## Supported Features +- Aurora Provisioned cluster (MySQL & PostgreSQL) +- Aurora Global databases (MySQL & PostgreSQL) + +## Deployment Procedure To deploy the Terraform Amazon Aurora module, do the following: 1. Install Terraform. For instructions and a video tutorial, see [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli). -2. Sign up and log into Terraform Cloud. (There is a free tier available.) +2. Sign up and log into [Terraform Cloud](https://www.terraform.io/cloud) (There is a free tier available). + 1. Create a Terraform organization 3. Configure Terraform Cloud API access. Run the following to generate a Terraform Cloud token from the command line interface: -``` -terraform login + ``` + terraform login ---For Mac/Linux -export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" + --For Mac/Linux + export TERRAFORM_CONFIG="$HOME/.terraform.d/credentials.tfrc.json" ---For Windows -export TERRAFORM_CONFIG="$HOME/AppData/Roaming/terraform.d/credentials.tfrc.json" -``` + --For Windows + export TERRAFORM_CONFIG="$HOME/AppData/Roaming/terraform.d/credentials.tfrc.json" + ``` 4. Configure the AWS Command Line Interface (AWS CLI). For more information, see [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). @@ -32,15 +39,21 @@ export TERRAFORM_CONFIG="$HOME/AppData/Roaming/terraform.d/credentials.tfrc.json `cd terraform-aws-rds-aurora/` -8. For setting up a new terraform workspace: +8. Set up a new terraform workspace. - - `cd setup_workspace` - - `terraform init` - - `terraform apply` - -9. To create new VPC and deploy Aurora module: + ``` + cd setup_workspace + terraform init + terraform apply + ``` + +9. Deploy Aurora Terraform module. + 1. To create VPC and deploy Aurora module - Change to the deploy directory. Run `cd ../deploy` - Initialize the deploy directory. Run `terraform init`. - Start a Terraform run using the configuration files in your deploy directory. Run `terraform apply` or `terraform apply -var-file="$HOME/.aws/terraform.tfvars"` (Note: The deployment is remotely run in Terraform Cloud) + 2. To deploy Aurora module into existing VPCs, pass the list of private subnets (var.Private_subnet_ids_p & var.Private_subnet_ids_s) directly to the Aurora module. + +## Authors and Contributors - For existing VPCs, pass the list of private subnets (var.Private_subnet_ids_p & var.Private_subnet_ids_s) directly to the Aurora module. +David Wright (dwright@hashicorp.com), Tony Vattahil (tonynv@amazon.com), Arabinda Pani (arabindp@amazon.com) and [other contributors](https://github.com/aws-ia/terraform-aws-rds-aurora/graphs/contributors). \ No newline at end of file diff --git a/deploy/main.tf b/deploy/main.tf index f5ea4c4..c4c8196 100644 --- a/deploy/main.tf +++ b/deploy/main.tf @@ -67,22 +67,23 @@ module "aurora_vpc_s" { ###################################### module "aurora" { - source = "../" - region = var.region - sec_region = var.sec_region - #vpc_id = module.aurora_vpc.vpc_id - Private_subnet_ids_p = [module.aurora_vpc_p.PrivateSubnet1AID, module.aurora_vpc_p.PrivateSubnet2AID, module.aurora_vpc_p.PrivateSubnet3AID] - Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.PrivateSubnet1AID, module.aurora_vpc_s.PrivateSubnet2AID, module.aurora_vpc_s.PrivateSubnet3AID] : null - engine = var.engine - engine_version_pg = var.engine_version_pg - engine_version_mysql = var.engine_version_mysql - username = var.username - password = var.password - setup_globaldb = var.setup_globaldb - setup_as_secondary = var.setup_as_secondary - tags = module.vpc_label.tags - monitoring_interval = var.monitoring_interval - storage_encrypted = var.storage_encrypted - primary_instance_count = var.primary_instance_count - secondary_instance_count = var.secondary_instance_count + source = "../" + region = var.region + sec_region = var.sec_region + #vpc_id = module.aurora_vpc.vpc_id + Private_subnet_ids_p = [module.aurora_vpc_p.private_subnet_1a_id, module.aurora_vpc_p.private_subnet_2a_id, module.aurora_vpc_p.private_subnet_3a_id] + Private_subnet_ids_s = var.setup_globaldb ? [module.aurora_vpc_s.private_subnet_1a_id, module.aurora_vpc_s.private_subnet_2a_id, module.aurora_vpc_s.private_subnet_3a_id] : null + engine = var.engine + engine_version_pg = var.engine_version_pg + engine_version_mysql = var.engine_version_mysql + username = var.username + password = var.password + setup_globaldb = var.setup_globaldb + setup_as_secondary = var.setup_as_secondary + tags = module.vpc_label.tags + monitoring_interval = var.monitoring_interval + storage_encrypted = var.storage_encrypted + primary_instance_count = var.primary_instance_count + secondary_instance_count = var.secondary_instance_count + snapshot_identifier = var.snapshot_identifier } \ No newline at end of file diff --git a/deploy/variables.tf b/deploy/variables.tf index dc4d420..c29155d 100644 --- a/deploy/variables.tf +++ b/deploy/variables.tf @@ -1,10 +1,10 @@ variable "region" { - description = "The name of the primary region you wish to deploy into" + description = "The name of the primary AWS region you wish to deploy into" default = "us-east-2" } variable "sec_region" { - description = "The name of the secondary region you wish to deploy into" + description = "The name of the secondary AWS region you wish to deploy into" default = "us-west-2" } @@ -47,15 +47,15 @@ variable "engine" { } variable "engine_version_pg" { - description = "Aurora database engine version." + description = "Aurora PostgreSQL database engine version." type = string - default = "12.4" + default = "13.3" } variable "engine_version_mysql" { - description = "Aurora database engine version." + description = "Aurora MySQL database engine version." type = string - default = "5.7.mysql_aurora.2.10.0" + default = "5.7.mysql_aurora.2.10.1" } variable "setup_globaldb" { @@ -65,7 +65,7 @@ variable "setup_globaldb" { } variable "setup_as_secondary" { - description = "Setup Aurora Global Database Secondary cluster after an unplanned failover" + description = "Setup aws_rds_cluster.primary Terraform resource as Secondary Aurora cluster after an unplanned Aurora Global DB failover" type = bool default = false } @@ -80,18 +80,23 @@ variable "monitoring_interval" { } } +variable "snapshot_identifier" { + description = "id of snapshot to restore. If you do not want to restore a db, leave the default empty string." + default = "" +} + variable "storage_encrypted" { - description = "Specifies whether the underlying storage layer should be encrypted" + description = "Specifies whether the underlying Aurora storage layer should be encrypted" type = bool default = false } variable "primary_instance_count" { - description = "instance count for primary cluster" + description = "instance count for primary Aurora cluster" default = 2 } variable "secondary_instance_count" { - description = "instance count for secondary cluster" + description = "instance count for secondary Aurora cluster" default = 1 } \ No newline at end of file diff --git a/main.tf b/main.tf index 1daac13..4af41c7 100644 --- a/main.tf +++ b/main.tf @@ -4,6 +4,7 @@ terraform { required_version = ">= 1.0.0" + backend "remote" {} } provider "aws" { @@ -72,7 +73,7 @@ resource "aws_db_subnet_group" "private_p" { provider = aws.primary name = "${var.name}-sg" subnet_ids = var.Private_subnet_ids_p - tags = { + tags = { Name = "My DB subnet group" } } @@ -82,7 +83,7 @@ resource "aws_db_subnet_group" "private_s" { count = var.setup_globaldb ? 1 : 0 name = "${var.name}-sg" subnet_ids = var.Private_subnet_ids_s - tags = { + tags = { Name = "My DB subnet group" } } @@ -92,22 +93,22 @@ resource "aws_db_subnet_group" "private_s" { ########### resource "aws_kms_key" "kms_p" { - provider = aws.primary - count = var.storage_encrypted ? 1 : 0 - description = "KMS key for Aurora Storage Enryption" - tags = var.tags - # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored for your production workload. + provider = aws.primary + count = var.storage_encrypted ? 1 : 0 + description = "KMS key for Aurora Storage Encryption" + tags = var.tags + # following causes terraform destroy to fail. But this is needed so that Aurora encrypted snapshots can be restored for your production workload. lifecycle { prevent_destroy = true } } resource "aws_kms_key" "kms_s" { - provider = aws.secondary - count = var.setup_globaldb && var.storage_encrypted ? 1 : 0 - description = "KMS key for Aurora Storage Enryption" - tags = var.tags - # following causes terraform destory to fail. But this is needed so that old Aurora encrypted snapshots can be restored for your production workload. + provider = aws.secondary + count = var.setup_globaldb && var.storage_encrypted ? 1 : 0 + description = "KMS key for Aurora Storage Encryption" + tags = var.tags + # following causes terraform destroy to fail. But this is needed so that Aurora encrypted snapshots can be restored for your production workload. lifecycle { prevent_destroy = true } @@ -158,12 +159,13 @@ resource "aws_rds_cluster" "primary" { kms_key_id = var.storage_encrypted ? aws_kms_key.kms_p[0].arn : null apply_immediately = true skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.region}-${md5(timestamp())}" snapshot_identifier = var.snapshot_identifier != "" ? var.snapshot_identifier : null enabled_cloudwatch_logs_exports = local.logs_set tags = var.tags depends_on = [ - # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory - # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destory to work + # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destroy + # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destroy to work #aws_rds_cluster_instance.secondary, ] lifecycle { @@ -174,21 +176,21 @@ resource "aws_rds_cluster" "primary" { } resource "aws_rds_cluster_instance" "primary" { - count = var.primary_instance_count - provider = aws.primary - identifier = "${var.name}-${var.region}-${count.index + 1}" - cluster_identifier = aws_rds_cluster.primary.id - engine = aws_rds_cluster.primary.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - auto_minor_version_upgrade = var.setup_globaldb ? false : var.auto_minor_version_upgrade - instance_class = var.instance_class - db_subnet_group_name = aws_db_subnet_group.private_p.name - db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_p.id - performance_insights_enabled = true - monitoring_interval = var.monitoring_interval - monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn - apply_immediately = true - tags = var.tags + count = var.primary_instance_count + provider = aws.primary + identifier = "${var.name}-${var.region}-${count.index + 1}" + cluster_identifier = aws_rds_cluster.primary.id + engine = aws_rds_cluster.primary.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + auto_minor_version_upgrade = var.setup_globaldb ? false : var.auto_minor_version_upgrade + instance_class = var.instance_class + db_subnet_group_name = aws_db_subnet_group.private_p.name + db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_p.id + performance_insights_enabled = true + monitoring_interval = var.monitoring_interval + monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn + apply_immediately = true + tags = var.tags } # Secondary Aurora Cluster @@ -209,11 +211,12 @@ resource "aws_rds_cluster" "secondary" { kms_key_id = var.storage_encrypted ? aws_kms_key.kms_s[0].arn : null apply_immediately = true skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.sec_region}-${md5(timestamp())}" enabled_cloudwatch_logs_exports = local.logs_set tags = var.tags depends_on = [ - # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destory - # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destory to work + # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destroy + # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destroy to work aws_rds_cluster_instance.primary, ] lifecycle { @@ -225,21 +228,21 @@ resource "aws_rds_cluster" "secondary" { # Secondary Cluster Instances resource "aws_rds_cluster_instance" "secondary" { - count = var.setup_globaldb ? var.secondary_instance_count : 0 - provider = aws.secondary - identifier = "${var.name}-${var.sec_region}-${count.index + 1}" - cluster_identifier = aws_rds_cluster.secondary[0].id - engine = var.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - auto_minor_version_upgrade = false - instance_class = var.instance_class - db_subnet_group_name = aws_db_subnet_group.private_s[0].name - db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_s[0].id - performance_insights_enabled = true - monitoring_interval = var.monitoring_interval - monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn - apply_immediately = true - tags = var.tags + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + identifier = "${var.name}-${var.sec_region}-${count.index + 1}" + cluster_identifier = aws_rds_cluster.secondary[0].id + engine = var.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + auto_minor_version_upgrade = false + instance_class = var.instance_class + db_subnet_group_name = aws_db_subnet_group.private_s[0].name + db_parameter_group_name = aws_db_parameter_group.aurora_db_parameter_group_s[0].id + performance_insights_enabled = true + monitoring_interval = var.monitoring_interval + monitoring_role_arn = aws_iam_role.rds_enhanced_monitoring.arn + apply_immediately = true + tags = var.tags } ############################# @@ -257,8 +260,8 @@ resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group_p" { iterator = pblock content { - name = pblock.value.name - value = pblock.value.value + name = pblock.value.name + value = pblock.value.value apply_method = pblock.value.apply_method } } @@ -325,8 +328,8 @@ resource "aws_db_parameter_group" "aurora_db_parameter_group_s" { ############################## resource "aws_sns_topic" "default_p" { - provider = aws.primary - name = "aurora-monitoring-sns" + provider = aws.primary + name = "rds-events" } resource "aws_db_event_subscription" "default_p" { @@ -346,9 +349,9 @@ resource "aws_db_event_subscription" "default_p" { } resource "aws_sns_topic" "default_s" { - count = var.setup_globaldb ? 1 : 0 - provider = aws.secondary - name = "aurora-monitoring-sns" + count = var.setup_globaldb ? 1 : 0 + provider = aws.secondary + name = "rds-events" } resource "aws_db_event_subscription" "default_s" { @@ -369,165 +372,163 @@ resource "aws_db_event_subscription" "default_s" { } resource "aws_cloudwatch_metric_alarm" "cpu_util_p" { - count = var.primary_instance_count - provider = aws.primary - alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Instance CPU Utilization" - metric_name = "CPUUtilization" - comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "80" - statistic = "Maximum" - unit = "Percent" - alarm_actions = [aws_sns_topic.default_p.arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" - } + count = var.primary_instance_count + provider = aws.primary + alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance CPU Utilization" + metric_name = "CPUUtilization" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "80" + statistic = "Maximum" + unit = "Percent" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } } - resource "aws_cloudwatch_metric_alarm" "free_local_storage_p" { - count = var.primary_instance_count - provider = aws.primary - alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Local Storage Utilization" - metric_name = "FreeLocalStorage" - comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "5368709120" - statistic = "Average" - unit = "Bytes" - alarm_actions = [aws_sns_topic.default_p.arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" - } + count = var.primary_instance_count + provider = aws.primary + alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Local Storage Utilization" + metric_name = "FreeLocalStorage" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "5368709120" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } } resource "aws_cloudwatch_metric_alarm" "free_random_access_memory_p" { - count = var.primary_instance_count - provider = aws.primary - alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" - metric_name = "FreeableMemory" - comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "2147483648" - statistic = "Average" - unit = "Bytes" - alarm_actions = [aws_sns_topic.default_p.arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" - } + count = var.primary_instance_count + provider = aws.primary + alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.primary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" + metric_name = "FreeableMemory" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "2147483648" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.primary.*.id, count.index)}" + } } resource "aws_cloudwatch_metric_alarm" "PG_MaxUsedTxIDs_p" { - count = var.engine == "aurora-postgresql" ? 1 : 0 - provider = aws.primary - alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.primary.id}" - alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" - metric_name = "MaximumUsedTransactionIDs" - comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "600000000" - statistic = "Average" - unit = "Count" - alarm_actions = [aws_sns_topic.default_p.arn] - namespace = "AWS/RDS" - dimensions = { - DBClusterIdentifier = "${aws_rds_cluster.primary.id}" - Role = "WRITER" - } + count = var.engine == "aurora-postgresql" ? 1 : 0 + provider = aws.primary + alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.primary.id}" + alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" + metric_name = "MaximumUsedTransactionIDs" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "600000000" + statistic = "Average" + unit = "Count" + alarm_actions = [aws_sns_topic.default_p.arn] + namespace = "AWS/RDS" + dimensions = { + DBClusterIdentifier = "${aws_rds_cluster.primary.id}" + Role = "WRITER" + } } resource "aws_cloudwatch_metric_alarm" "cpu_util_s" { - count = var.setup_globaldb ? var.secondary_instance_count : 0 - provider = aws.secondary - alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Instance CPU Utilization" - metric_name = "CPUUtilization" - comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "80" - statistic = "Maximum" - unit = "Percent" - alarm_actions = [aws_sns_topic.default_s[0].arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" - } + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "CPU_Util-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance CPU Utilization" + metric_name = "CPUUtilization" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "80" + statistic = "Maximum" + unit = "Percent" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } } - resource "aws_cloudwatch_metric_alarm" "free_local_storage_s" { - count = var.setup_globaldb ? var.secondary_instance_count : 0 - provider = aws.secondary - alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Local Storage Utilization" - metric_name = "FreeLocalStorage" - comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "5368709120" - statistic = "Average" - unit = "Bytes" - alarm_actions = [aws_sns_topic.default_s[0].arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" - } + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "Free_local_storage-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Local Storage Utilization" + metric_name = "FreeLocalStorage" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "5368709120" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } } resource "aws_cloudwatch_metric_alarm" "free_random_access_memory_s" { - count = var.setup_globaldb ? var.secondary_instance_count : 0 - provider = aws.secondary - alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" - alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" - metric_name = "FreeableMemory" - comparison_operator = "LessThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "2147483648" - statistic = "Average" - unit = "Bytes" - alarm_actions = [aws_sns_topic.default_s[0].arn] - namespace = "AWS/RDS" - dimensions = { - DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" - } + count = var.setup_globaldb ? var.secondary_instance_count : 0 + provider = aws.secondary + alarm_name = "FreeableMemory-${element(split(",", join(",", aws_rds_cluster_instance.secondary.*.id)), count.index)}" + alarm_description = "This metric monitors Aurora Instance Random Access Memory Utilization" + metric_name = "FreeableMemory" + comparison_operator = "LessThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "2147483648" + statistic = "Average" + unit = "Bytes" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBInstanceIdentifier = "${element(aws_rds_cluster_instance.secondary.*.id, count.index)}" + } } resource "aws_cloudwatch_metric_alarm" "PG_MaxUsedTxIDs_s" { - count = (var.engine == "aurora-postgresql") && var.setup_globaldb ? 1 : 0 - provider = aws.secondary - alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.secondary[0].id}" - alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" - metric_name = "MaximumUsedTransactionIDs" - comparison_operator = "GreaterThanOrEqualToThreshold" - evaluation_periods = "5" - treat_missing_data = "notBreaching" - period = "60" - threshold = "600000000" - statistic = "Average" - unit = "Count" - alarm_actions = [aws_sns_topic.default_s[0].arn] - namespace = "AWS/RDS" - dimensions = { - DBClusterIdentifier = "${aws_rds_cluster.secondary[0].id}" - Role = "WRITER" - } + count = (var.engine == "aurora-postgresql") && var.setup_globaldb ? 1 : 0 + provider = aws.secondary + alarm_name = "PG_MaxUsedTxIDs-${aws_rds_cluster.secondary[0].id}" + alarm_description = "This metric monitors Aurora PostgreSQL Max Used Tx IDs" + metric_name = "MaximumUsedTransactionIDs" + comparison_operator = "GreaterThanOrEqualToThreshold" + evaluation_periods = "5" + treat_missing_data = "notBreaching" + period = "60" + threshold = "600000000" + statistic = "Average" + unit = "Count" + alarm_actions = [aws_sns_topic.default_s[0].arn] + namespace = "AWS/RDS" + dimensions = { + DBClusterIdentifier = "${aws_rds_cluster.secondary[0].id}" + Role = "WRITER" + } } \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index 335b519..9961279 100644 --- a/outputs.tf +++ b/outputs.tf @@ -24,28 +24,27 @@ output "aurora_cluster_reader_endpoint" { value = aws_rds_cluster.primary.reader_endpoint } -// database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output +output "aurora_cluster_port" { + description = "Primary Aurora cluster endpoint port" + value = aws_rds_cluster.primary.port +} + output "aurora_cluster_database_name" { description = "Name for an automatically created database on Aurora cluster creation" value = var.database_name } +output "aurora_cluster_master_username" { + description = "Aurora master username" + value = aws_rds_cluster.primary.master_username +} + output "aurora_cluster_master_password" { description = "Aurora master User password" value = aws_rds_cluster.primary.master_password sensitive = true } -output "aurora_cluster_port" { - description = "Aurora cluster endpoint port" - value = aws_rds_cluster.primary.port -} - -output "aurora_cluster_master_username" { - description = "Aurora master username" - value = aws_rds_cluster.primary.master_username -} - output "aurora_cluster_hosted_zone_id" { description = "Route53 hosted zone id of the Primary Aurora cluster" value = aws_rds_cluster.primary.hosted_zone_id diff --git a/setup_workspace/workspace.tf b/setup_workspace/workspace.tf index 4800d83..1e76b3c 100644 --- a/setup_workspace/workspace.tf +++ b/setup_workspace/workspace.tf @@ -1,11 +1,12 @@ terraform { required_version = ">= 1.0.0" } + locals { dir_down = ".." } -# Generate new terraform org and workspace +# Generate new Terraform org and workspace module "tfcloud" { source = "aws-ia/cloud_workspace/hashicorp" @@ -44,7 +45,7 @@ output "user_instructions" { # Run these commands in order: -cd ${local.dir_down}${var.working_directory} + cd ${local.dir_down}${var.working_directory} # Configure your tfvars file AWS_SECRET_ACCESS_KEY = "*****************" @@ -52,10 +53,10 @@ cd ${local.dir_down}${var.working_directory} AWS_SESSION_TOKEN = "*****************" region = ${var.region} -# Note: Use of STS Creds are highly reccommended! -# !!!!CAUTION!!!!: Make sure your credentials are secured outside version control -# (and follow secrets mangement bestpractices) -# +# Note: Use of STS Creds are highly recommended! +# !!!!CAUTION!!!!: Make sure your credential are secured outside version control +# (and follow secrets management best practices) +# terraform apply -var-file="$HOME/.aws/terraform.tfvars" README } diff --git a/variables.tf b/variables.tf index df659fe..8e61097 100644 --- a/variables.tf +++ b/variables.tf @@ -1,11 +1,11 @@ variable "region" { type = string - description = "The name of the primary region you wish to deploy into" + description = "The name of the primary AWS region you wish to deploy into" } variable "sec_region" { type = string - description = "The name of the secondary region you wish to deploy into" + description = "The name of the secondary AWS region you wish to deploy into" } variable "identifier" { @@ -44,12 +44,12 @@ variable "allowed_security_groups" { } variable "primary_instance_count" { - description = "instance count for primary cluster" + description = "instance count for primary Aurora cluster" default = 2 } variable "secondary_instance_count" { - description = "instance count for secondary cluster" + description = "instance count for secondary Aurora cluster" default = 1 } @@ -60,12 +60,18 @@ variable "instance_class" { } variable "skip_final_snapshot" { - type = string + type = bool description = "skip creating a final snapshot before deleting the DB" #set the value to false for production workload default = true } +variable "final_snapshot_identifier_prefix" { + description = "The prefix name to use when creating a final snapshot on cluster destroy, appends a random 8 digits to name to ensure it's unique too." + type = string + default = "final" +} + variable "database_name" { description = "Name for an automatically created database on cluster creation" type = string @@ -108,7 +114,7 @@ variable "auto_minor_version_upgrade" { } variable "storage_encrypted" { - description = "Specifies whether the underlying storage layer should be encrypted" + description = "Specifies whether the underlying Aurora storage layer should be encrypted" type = bool default = false } @@ -122,13 +128,13 @@ variable "engine" { variable "engine_version_pg" { description = "Aurora database engine version." type = string - default = "12.4" + default = "13.3" } variable "engine_version_mysql" { description = "Aurora database engine version." type = string - default = "5.7.mysql_aurora.2.10.0" + default = "5.7.mysql_aurora.2.10.1" } variable "setup_globaldb" { @@ -138,7 +144,7 @@ variable "setup_globaldb" { } variable "setup_as_secondary" { - description = "Setup Aurora Global Database Secondary cluster after an unplanned failover" + description = "Setup aws_rds_cluster.primary Terraform resource as Secondary Aurora cluster after an unplanned Aurora Global DB failover" type = bool default = false } @@ -174,25 +180,30 @@ variable "snapshot_identifier" { variable "enable_audit_log" { description = "Enable MySQL audit log export to Amazon Cloudwatch." + type = bool default = false } variable "enable_error_log" { description = "Enable MySQL error log export to Amazon Cloudwatch." + type = bool default = false } variable "enable_general_log" { description = "Enable MySQL general log export to Amazon Cloudwatch." + type = bool default = false } variable "enable_slowquery_log" { description = "Enable MySQL slowquery log export to Amazon Cloudwatch." + type = bool default = false } variable "enable_postgresql_log" { description = "Enable PostgreSQL log export to Amazon Cloudwatch." + type = bool default = false } \ No newline at end of file From c3c5ce316feae8538796dc7509f66e663a78e89f Mon Sep 17 00:00:00 2001 From: Arabinda Pani <22154314+catcharbind@users.noreply.github.com> Date: Fri, 29 Oct 2021 14:58:23 -0700 Subject: [PATCH 6/7] readme update --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b0460b9..034f163 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ To deploy the Terraform Amazon Aurora module, do the following: 1. Install Terraform. For instructions and a video tutorial, see [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli). 2. Sign up and log into [Terraform Cloud](https://www.terraform.io/cloud) (There is a free tier available). - 1. Create a Terraform organization + 1. Create a [Terraform organization](https://www.terraform.io/docs/cloud/users-teams-organizations/organizations.html#creating-organizations). -3. Configure Terraform Cloud API access. Run the following to generate a Terraform Cloud token from the command line interface: +3. Configure [Terraform Cloud API access](https://learn.hashicorp.com/tutorials/terraform/cloud-login). Run the following to generate a Terraform Cloud token from the command line interface: ``` terraform login @@ -27,7 +27,7 @@ To deploy the Terraform Amazon Aurora module, do the following: export TERRAFORM_CONFIG="$HOME/AppData/Roaming/terraform.d/credentials.tfrc.json" ``` -4. Configure the AWS Command Line Interface (AWS CLI). For more information, see [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). +4. [Install](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) and [configure](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) the AWS Command Line Interface (AWS CLI). 5. If you don't have git installed, [install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). From 6cbf8f5973988980821f675bc9aa2a58bdf86079 Mon Sep 17 00:00:00 2001 From: Arabinda Pani <22154314+catcharbind@users.noreply.github.com> Date: Mon, 8 Nov 2021 17:17:58 -0800 Subject: [PATCH 7/7] Aurora major version upgrade updates --- main.tf | 129 ++++++++++++++++++++++++++++++++------------------- variables.tf | 6 +++ 2 files changed, 88 insertions(+), 47 deletions(-) diff --git a/main.tf b/main.tf index 4af41c7..9c1d959 100644 --- a/main.tf +++ b/main.tf @@ -5,6 +5,12 @@ terraform { required_version = ">= 1.0.0" backend "remote" {} + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.64.0" + } + } } provider "aws" { @@ -65,6 +71,19 @@ resource "random_password" "master_password" { special = false } +#################################### +# Generate Final snapshot identifier +#################################### + +resource "random_id" "snapshot_id" { + + keepers = { + id = var.identifier + } + + byte_length = 4 +} + ########### # DB Subnet ########### @@ -141,29 +160,31 @@ resource "aws_rds_global_cluster" "globaldb" { } resource "aws_rds_cluster" "primary" { - provider = aws.primary - global_cluster_identifier = var.setup_globaldb ? aws_rds_global_cluster.globaldb[0].id : null - cluster_identifier = "${var.identifier}-${var.region}" - engine = var.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - availability_zones = [data.aws_availability_zones.region_p.names[0], data.aws_availability_zones.region_p.names[1], data.aws_availability_zones.region_p.names[2]] - db_subnet_group_name = aws_db_subnet_group.private_p.name - port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port - database_name = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.database_name - master_username = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.username - master_password = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : (var.password == "" ? random_password.master_password.result : var.password) - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_p.id - backup_retention_period = var.backup_retention_period - preferred_backup_window = var.preferred_backup_window - storage_encrypted = var.storage_encrypted - kms_key_id = var.storage_encrypted ? aws_kms_key.kms_p[0].arn : null - apply_immediately = true - skip_final_snapshot = var.skip_final_snapshot - final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.region}-${md5(timestamp())}" - snapshot_identifier = var.snapshot_identifier != "" ? var.snapshot_identifier : null - enabled_cloudwatch_logs_exports = local.logs_set - tags = var.tags - depends_on = [ + provider = aws.primary + global_cluster_identifier = var.setup_globaldb ? aws_rds_global_cluster.globaldb[0].id : null + cluster_identifier = "${var.identifier}-${var.region}" + engine = var.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + allow_major_version_upgrade = var.allow_major_version_upgrade + availability_zones = [data.aws_availability_zones.region_p.names[0], data.aws_availability_zones.region_p.names[1], data.aws_availability_zones.region_p.names[2]] + db_subnet_group_name = aws_db_subnet_group.private_p.name + port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port + database_name = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.database_name + master_username = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : var.username + master_password = var.setup_as_secondary || (var.snapshot_identifier != "") ? null : (var.password == "" ? random_password.master_password.result : var.password) + db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_p.id + db_instance_parameter_group_name = var.allow_major_version_upgrade ? aws_db_parameter_group.aurora_db_parameter_group_p.id : null + backup_retention_period = var.backup_retention_period + preferred_backup_window = var.preferred_backup_window + storage_encrypted = var.storage_encrypted + kms_key_id = var.storage_encrypted ? aws_kms_key.kms_p[0].arn : null + apply_immediately = true + skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.region}-${random_id.snapshot_id.hex}" + snapshot_identifier = var.snapshot_identifier != "" ? var.snapshot_identifier : null + enabled_cloudwatch_logs_exports = local.logs_set + tags = var.tags + depends_on = [ # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destroy # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destroy to work #aws_rds_cluster_instance.secondary, @@ -195,26 +216,28 @@ resource "aws_rds_cluster_instance" "primary" { # Secondary Aurora Cluster resource "aws_rds_cluster" "secondary" { - count = var.setup_globaldb ? 1 : 0 - provider = aws.secondary - global_cluster_identifier = aws_rds_global_cluster.globaldb[0].id - cluster_identifier = "${var.identifier}-${var.sec_region}" - engine = var.engine - engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql - availability_zones = [data.aws_availability_zones.region_s.names[0], data.aws_availability_zones.region_s.names[1], data.aws_availability_zones.region_s.names[2]] - db_subnet_group_name = aws_db_subnet_group.private_s[0].name - port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_s[0].id - backup_retention_period = var.backup_retention_period - preferred_backup_window = var.preferred_backup_window - source_region = var.storage_encrypted ? var.region : null - kms_key_id = var.storage_encrypted ? aws_kms_key.kms_s[0].arn : null - apply_immediately = true - skip_final_snapshot = var.skip_final_snapshot - final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.sec_region}-${md5(timestamp())}" - enabled_cloudwatch_logs_exports = local.logs_set - tags = var.tags - depends_on = [ + count = var.setup_globaldb ? 1 : 0 + provider = aws.secondary + global_cluster_identifier = aws_rds_global_cluster.globaldb[0].id + cluster_identifier = "${var.identifier}-${var.sec_region}" + engine = var.engine + engine_version = var.engine == "aurora-postgresql" ? var.engine_version_pg : var.engine_version_mysql + allow_major_version_upgrade = var.allow_major_version_upgrade + availability_zones = [data.aws_availability_zones.region_s.names[0], data.aws_availability_zones.region_s.names[1], data.aws_availability_zones.region_s.names[2]] + db_subnet_group_name = aws_db_subnet_group.private_s[0].name + port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port + db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_cluster_parameter_group_s[0].id + db_instance_parameter_group_name = var.allow_major_version_upgrade ? aws_db_parameter_group.aurora_db_parameter_group_s[0].id : null + backup_retention_period = var.backup_retention_period + preferred_backup_window = var.preferred_backup_window + source_region = var.storage_encrypted ? var.region : null + kms_key_id = var.storage_encrypted ? aws_kms_key.kms_s[0].arn : null + apply_immediately = true + skip_final_snapshot = var.skip_final_snapshot + final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.final_snapshot_identifier_prefix}-${var.identifier}-${var.sec_region}-${random_id.snapshot_id.hex}" + enabled_cloudwatch_logs_exports = local.logs_set + tags = var.tags + depends_on = [ # When this Aurora cluster is setup as a secondary, setting up the dependency makes sure to delete this cluster 1st before deleting current primary Cluster during terraform destroy # Comment out the following line if this cluster has changed role to be the primary Aurora cluster because of a failover for terraform destroy to work aws_rds_cluster_instance.primary, @@ -251,7 +274,7 @@ resource "aws_rds_cluster_instance" "secondary" { resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group_p" { provider = aws.primary - name = "${var.name}-cluster-parameter-group" + name_prefix = "${var.name}-cluster-" family = data.aws_rds_engine_version.family.parameter_group_family description = "aurora-cluster-parameter-group" @@ -265,11 +288,14 @@ resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group_p" { apply_method = pblock.value.apply_method } } + lifecycle { + create_before_destroy = true + } } resource "aws_db_parameter_group" "aurora_db_parameter_group_p" { provider = aws.primary - name = "${var.name}-db-parameter-group" + name_prefix = "${var.name}-db-" family = data.aws_rds_engine_version.family.parameter_group_family description = "aurora-db-parameter-group" @@ -283,12 +309,15 @@ resource "aws_db_parameter_group" "aurora_db_parameter_group_p" { apply_method = pblock.value.apply_method } } + lifecycle { + create_before_destroy = true + } } resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group_s" { count = var.setup_globaldb ? 1 : 0 provider = aws.secondary - name = "${var.name}-cluster-parameter-group" + name_prefix = "${var.name}-cluster-" family = data.aws_rds_engine_version.family.parameter_group_family description = "aurora-cluster-parameter-group" @@ -302,12 +331,15 @@ resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group_s" { apply_method = pblock.value.apply_method } } + lifecycle { + create_before_destroy = true + } } resource "aws_db_parameter_group" "aurora_db_parameter_group_s" { count = var.setup_globaldb ? 1 : 0 provider = aws.secondary - name = "${var.name}-db-parameter-group" + name_prefix = "${var.name}-db-" family = data.aws_rds_engine_version.family.parameter_group_family description = "aurora-db-parameter-group" @@ -321,6 +353,9 @@ resource "aws_db_parameter_group" "aurora_db_parameter_group_s" { apply_method = pblock.value.apply_method } } + lifecycle { + create_before_destroy = true + } } ############################# diff --git a/variables.tf b/variables.tf index 8e61097..42386b5 100644 --- a/variables.tf +++ b/variables.tf @@ -113,6 +113,12 @@ variable "auto_minor_version_upgrade" { default = true } +variable "allow_major_version_upgrade" { + description = "Enable to allow major engine version upgrades when changing engine versions. Defaults to `false`" + type = bool + default = true +} + variable "storage_encrypted" { description = "Specifies whether the underlying Aurora storage layer should be encrypted" type = bool