diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24e2673 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.terraform +.cache \ No newline at end of file diff --git a/alarms.tf b/alarms.tf index dccf270..d9c5b76 100644 --- a/alarms.tf +++ b/alarms.tf @@ -1,5 +1,5 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_DatabaseConnections_writer" { - count = "${var.cw_alarms ? 1 : 0}" + count = var.cw_alarms ? 1 : 0 alarm_name = "${aws_rds_cluster.default.id}-alarm-rds-writer-DatabaseConnections" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "1" @@ -7,19 +7,19 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_DatabaseConnections_writer" { namespace = "AWS/RDS" period = "60" statistic = "Sum" - threshold = "${var.cw_max_conns}" + threshold = var.cw_max_conns alarm_description = "RDS Maximum connection Alarm for ${aws_rds_cluster.default.id} writer" - alarm_actions = ["${var.cw_sns_topic}"] - ok_actions = ["${var.cw_sns_topic}"] + alarm_actions = [var.cw_sns_topic] + ok_actions = [var.cw_sns_topic] - dimensions { - DBClusterIdentifier = "${aws_rds_cluster.default.id}" + dimensions = { + DBClusterIdentifier = aws_rds_cluster.default.id Role = "WRITER" } } resource "aws_cloudwatch_metric_alarm" "alarm_rds_DatabaseConnections_reader" { - count = "${var.cw_alarms && var.replica_count > 0 ? 1 : 0}" + count = var.cw_alarms && var.replica_count > 0 ? 1 : 0 alarm_name = "${aws_rds_cluster.default.id}-alarm-rds-reader-DatabaseConnections" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "1" @@ -27,19 +27,19 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_DatabaseConnections_reader" { namespace = "AWS/RDS" period = "60" statistic = "Maximum" - threshold = "${var.cw_max_conns}" + threshold = var.cw_max_conns alarm_description = "RDS Maximum connection Alarm for ${aws_rds_cluster.default.id} reader(s)" - alarm_actions = ["${var.cw_sns_topic}"] - ok_actions = ["${var.cw_sns_topic}"] + alarm_actions = [var.cw_sns_topic] + ok_actions = [var.cw_sns_topic] - dimensions { - DBClusterIdentifier = "${aws_rds_cluster.default.id}" + dimensions = { + DBClusterIdentifier = aws_rds_cluster.default.id Role = "READER" } } resource "aws_cloudwatch_metric_alarm" "alarm_rds_CPU_writer" { - count = "${var.cw_alarms ? 1 : 0}" + count = var.cw_alarms ? 1 : 0 alarm_name = "${aws_rds_cluster.default.id}-alarm-rds-writer-CPU" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -47,19 +47,19 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_CPU_writer" { namespace = "AWS/RDS" period = "60" statistic = "Maximum" - threshold = "${var.cw_max_cpu}" + threshold = var.cw_max_cpu alarm_description = "RDS CPU Alarm for ${aws_rds_cluster.default.id} writer" - alarm_actions = ["${var.cw_sns_topic}"] - ok_actions = ["${var.cw_sns_topic}"] + alarm_actions = [var.cw_sns_topic] + ok_actions = [var.cw_sns_topic] - dimensions { - DBClusterIdentifier = "${aws_rds_cluster.default.id}" + dimensions = { + DBClusterIdentifier = aws_rds_cluster.default.id Role = "WRITER" } } resource "aws_cloudwatch_metric_alarm" "alarm_rds_CPU_reader" { - count = "${var.cw_alarms && var.replica_count > 0 ? 1 : 0}" + count = var.cw_alarms && var.replica_count > 0 ? 1 : 0 alarm_name = "${aws_rds_cluster.default.id}-alarm-rds-reader-CPU" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -67,19 +67,19 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_CPU_reader" { namespace = "AWS/RDS" period = "60" statistic = "Maximum" - threshold = "${var.cw_max_cpu}" + threshold = var.cw_max_cpu alarm_description = "RDS CPU Alarm for ${aws_rds_cluster.default.id} reader(s)" - alarm_actions = ["${var.cw_sns_topic}"] - ok_actions = ["${var.cw_sns_topic}"] + alarm_actions = [var.cw_sns_topic] + ok_actions = [var.cw_sns_topic] - dimensions { - DBClusterIdentifier = "${aws_rds_cluster.default.id}" + dimensions = { + DBClusterIdentifier = aws_rds_cluster.default.id Role = "READER" } } resource "aws_cloudwatch_metric_alarm" "alarm_rds_replica_lag" { - count = "${var.cw_alarms && var.replica_count > 0 ? 1 : 0}" + count = var.cw_alarms && var.replica_count > 0 ? 1 : 0 alarm_name = "${aws_rds_cluster.default.id}-alarm-rds-reader-AuroraReplicaLag" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "5" @@ -87,13 +87,14 @@ resource "aws_cloudwatch_metric_alarm" "alarm_rds_replica_lag" { namespace = "AWS/RDS" period = "60" statistic = "Maximum" - threshold = "${var.cw_max_replica_lag}" + threshold = var.cw_max_replica_lag alarm_description = "RDS CPU Alarm for ${aws_rds_cluster.default.id}" - alarm_actions = ["${var.cw_sns_topic}"] - ok_actions = ["${var.cw_sns_topic}"] + alarm_actions = [var.cw_sns_topic] + ok_actions = [var.cw_sns_topic] - dimensions { - DBClusterIdentifier = "${aws_rds_cluster.default.id}" + dimensions = { + DBClusterIdentifier = aws_rds_cluster.default.id Role = "READER" } } + diff --git a/main.tf b/main.tf index 50dbf35..2dc3638 100644 --- a/main.tf +++ b/main.tf @@ -162,94 +162,94 @@ // DB Subnet Group creation resource "aws_db_subnet_group" "main" { - name = "${var.name}" + name = var.name description = "Group of DB subnets" - subnet_ids = ["${var.subnets}"] + subnet_ids = var.subnets - tags { - envname = "${var.envname}" - envtype = "${var.envtype}" + tags = { + envname = var.envname + envtype = var.envtype } } // Create single DB instance resource "aws_rds_cluster_instance" "cluster_instance_0" { - identifier = "${var.identifier_prefix != "" ? format("%s-node-0", var.identifier_prefix) : format("%s-aurora-node-0", var.envname)}" - cluster_identifier = "${aws_rds_cluster.default.id}" - engine = "${var.engine}" - engine_version = "${var.engine-version}" - instance_class = "${var.instance_type}" - publicly_accessible = "${var.publicly_accessible}" - db_subnet_group_name = "${aws_db_subnet_group.main.name}" - db_parameter_group_name = "${var.db_parameter_group_name}" - preferred_maintenance_window = "${var.preferred_maintenance_window}" - apply_immediately = "${var.apply_immediately}" - monitoring_role_arn = "${join("", aws_iam_role.rds-enhanced-monitoring.*.arn)}" - monitoring_interval = "${var.monitoring_interval}" - auto_minor_version_upgrade = "${var.auto_minor_version_upgrade}" + identifier = var.identifier_prefix != "" ? format("%s-node-0", var.identifier_prefix) : format("%s-aurora-node-0", var.envname) + cluster_identifier = aws_rds_cluster.default.id + engine = var.engine + engine_version = var.engine-version + instance_class = var.instance_type + publicly_accessible = var.publicly_accessible + db_subnet_group_name = aws_db_subnet_group.main.name + db_parameter_group_name = var.db_parameter_group_name + preferred_maintenance_window = var.preferred_maintenance_window + apply_immediately = var.apply_immediately + monitoring_role_arn = join("", aws_iam_role.rds-enhanced-monitoring.*.arn) + monitoring_interval = var.monitoring_interval + auto_minor_version_upgrade = var.auto_minor_version_upgrade promotion_tier = "0" - performance_insights_enabled = "${var.performance_insights_enabled}" + performance_insights_enabled = var.performance_insights_enabled - tags { - envname = "${var.envname}" - envtype = "${var.envtype}" + tags = { + envname = var.envname + envtype = var.envtype } } // Create 'n' number of additional DB instance(s) in same cluster resource "aws_rds_cluster_instance" "cluster_instance_n" { - depends_on = ["aws_rds_cluster_instance.cluster_instance_0"] - count = "${var.replica_scale_enabled ? var.replica_scale_min : var.replica_count}" - engine = "${var.engine}" - engine_version = "${var.engine-version}" - identifier = "${var.identifier_prefix != "" ? format("%s-node-%d", var.identifier_prefix, count.index + 1) : format("%s-aurora-node-%d", var.envname, count.index + 1)}" - cluster_identifier = "${aws_rds_cluster.default.id}" - instance_class = "${var.instance_type}" - publicly_accessible = "${var.publicly_accessible}" - db_subnet_group_name = "${aws_db_subnet_group.main.name}" - db_parameter_group_name = "${var.db_parameter_group_name}" - preferred_maintenance_window = "${var.preferred_maintenance_window}" - apply_immediately = "${var.apply_immediately}" - monitoring_role_arn = "${join("", aws_iam_role.rds-enhanced-monitoring.*.arn)}" - monitoring_interval = "${var.monitoring_interval}" - auto_minor_version_upgrade = "${var.auto_minor_version_upgrade}" - promotion_tier = "${count.index + 1}" - performance_insights_enabled = "${var.performance_insights_enabled}" + depends_on = [aws_rds_cluster_instance.cluster_instance_0] + count = var.replica_scale_enabled ? var.replica_scale_min : var.replica_count + engine = var.engine + engine_version = var.engine-version + identifier = var.identifier_prefix != "" ? format("%s-node-%d", var.identifier_prefix, count.index + 1) : format("%s-aurora-node-%d", var.envname, count.index + 1) + cluster_identifier = aws_rds_cluster.default.id + instance_class = var.instance_type + publicly_accessible = var.publicly_accessible + db_subnet_group_name = aws_db_subnet_group.main.name + db_parameter_group_name = var.db_parameter_group_name + preferred_maintenance_window = var.preferred_maintenance_window + apply_immediately = var.apply_immediately + monitoring_role_arn = join("", aws_iam_role.rds-enhanced-monitoring.*.arn) + monitoring_interval = var.monitoring_interval + auto_minor_version_upgrade = var.auto_minor_version_upgrade + promotion_tier = count.index + 1 + performance_insights_enabled = var.performance_insights_enabled - tags { - envname = "${var.envname}" - envtype = "${var.envtype}" + tags = { + envname = var.envname + envtype = var.envtype } } // Create DB Cluster resource "aws_rds_cluster" "default" { - cluster_identifier = "${var.identifier_prefix != "" ? format("%s-cluster", var.identifier_prefix) : format("%s-aurora-cluster", var.envname)}" - availability_zones = ["${var.azs}"] - engine = "${var.engine}" + cluster_identifier = var.identifier_prefix != "" ? format("%s-cluster", var.identifier_prefix) : format("%s-aurora-cluster", var.envname) + availability_zones = var.azs + engine = var.engine - engine_version = "${var.engine-version}" - master_username = "${var.username}" - master_password = "${var.password}" + engine_version = var.engine-version + master_username = var.username + master_password = var.password final_snapshot_identifier = "${var.final_snapshot_identifier}-${random_id.server.hex}" - skip_final_snapshot = "${var.skip_final_snapshot}" - backup_retention_period = "${var.backup_retention_period}" - preferred_backup_window = "${var.preferred_backup_window}" - preferred_maintenance_window = "${var.preferred_maintenance_window}" - port = "${var.port}" - db_subnet_group_name = "${aws_db_subnet_group.main.name}" - vpc_security_group_ids = ["${var.security_groups}"] - snapshot_identifier = "${var.snapshot_identifier}" - storage_encrypted = "${var.storage_encrypted}" - apply_immediately = "${var.apply_immediately}" - db_cluster_parameter_group_name = "${var.db_cluster_parameter_group_name}" - deletion_protection = "${var.deletion_protection}" + skip_final_snapshot = var.skip_final_snapshot + backup_retention_period = var.backup_retention_period + preferred_backup_window = var.preferred_backup_window + preferred_maintenance_window = var.preferred_maintenance_window + port = var.port + db_subnet_group_name = aws_db_subnet_group.main.name + vpc_security_group_ids = var.security_groups + snapshot_identifier = var.snapshot_identifier + storage_encrypted = var.storage_encrypted + apply_immediately = var.apply_immediately + db_cluster_parameter_group_name = var.db_cluster_parameter_group_name + deletion_protection = var.deletion_protection } // Geneate an ID when an environment is initialised resource "random_id" "server" { keepers = { - id = "${aws_db_subnet_group.main.name}" + id = aws_db_subnet_group.main.name } byte_length = 8 @@ -268,30 +268,30 @@ data "aws_iam_policy_document" "monitoring-rds-assume-role-policy" { } resource "aws_iam_role" "rds-enhanced-monitoring" { - count = "${var.monitoring_interval > 0 ? 1 : 0}" + count = var.monitoring_interval > 0 ? 1 : 0 name_prefix = "rds-enhanced-mon-${var.envname}-" - assume_role_policy = "${data.aws_iam_policy_document.monitoring-rds-assume-role-policy.json}" + assume_role_policy = data.aws_iam_policy_document.monitoring-rds-assume-role-policy.json } resource "aws_iam_role_policy_attachment" "rds-enhanced-monitoring-policy-attach" { - count = "${var.monitoring_interval > 0 ? 1 : 0}" - role = "${aws_iam_role.rds-enhanced-monitoring.name}" + count = var.monitoring_interval > 0 ? 1 : 0 + role = aws_iam_role.rds-enhanced-monitoring[0].name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" } // Autoscaling resource "aws_appautoscaling_target" "autoscaling" { - count = "${var.replica_scale_enabled ? 1 : 0}" - max_capacity = "${var.replica_scale_max}" - min_capacity = "${var.replica_scale_min}" + count = var.replica_scale_enabled ? 1 : 0 + max_capacity = var.replica_scale_max + min_capacity = var.replica_scale_min resource_id = "cluster:${aws_rds_cluster.default.cluster_identifier}" scalable_dimension = "rds:cluster:ReadReplicaCount" service_namespace = "rds" } resource "aws_appautoscaling_policy" "autoscaling" { - count = "${var.replica_scale_enabled ? 1 : 0}" - depends_on = ["aws_appautoscaling_target.autoscaling"] + count = var.replica_scale_enabled ? 1 : 0 + depends_on = [aws_appautoscaling_target.autoscaling] name = "target-metric" policy_type = "TargetTrackingScaling" resource_id = "cluster:${aws_rds_cluster.default.cluster_identifier}" @@ -303,8 +303,9 @@ resource "aws_appautoscaling_policy" "autoscaling" { predefined_metric_type = "RDSReaderAverageCPUUtilization" } - scale_in_cooldown = "${var.replica_scale_in_cooldown}" - scale_out_cooldown = "${var.replica_scale_out_cooldown}" - target_value = "${var.replica_scale_cpu}" + scale_in_cooldown = var.replica_scale_in_cooldown + scale_out_cooldown = var.replica_scale_out_cooldown + target_value = var.replica_scale_cpu } } + diff --git a/outputs.tf b/outputs.tf index ac89aa7..a92e065 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,24 +1,25 @@ // The 'writer' endpoint for the cluster output "cluster_endpoint" { - value = "${aws_rds_cluster.default.endpoint}" + value = aws_rds_cluster.default.endpoint } // Comma separated list of all DB instance endpoints running in cluster output "all_instance_endpoints_list" { - value = ["${aws_rds_cluster_instance.cluster_instance_0.endpoint}", "${aws_rds_cluster_instance.cluster_instance_n.*.endpoint}"] + value = [aws_rds_cluster_instance.cluster_instance_0.endpoint, aws_rds_cluster_instance.cluster_instance_n.*.endpoint] } // A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas output "reader_endpoint" { - value = "${aws_rds_cluster.default.reader_endpoint}" + value = aws_rds_cluster.default.reader_endpoint } // Cluster ARN - can use when defining centralised backup output "cluster_arn" { - value = "${aws_rds_cluster.default.arn}" + value = aws_rds_cluster.default.arn } // Cluster ID - useful to any resources requiring cluster's ID, e.g. rds_cluster_role_association output "cluster_id" { - value = "${aws_rds_cluster.default.id}" -} \ No newline at end of file + value = aws_rds_cluster.default.id +} + diff --git a/variables.tf b/variables.tf index 297acbb..9d2f77f 100644 --- a/variables.tf +++ b/variables.tf @@ -1,53 +1,53 @@ variable "name" { - type = "string" + type = string description = "Name given to DB subnet group" } variable "subnets" { - type = "list" + type = list(string) description = "List of subnet IDs to use" } variable "envname" { - type = "string" + type = string description = "Environment name (eg,test, stage or prod)" } variable "envtype" { - type = "string" + type = string description = "Environment type (eg,prod or nonprod)" } variable "identifier_prefix" { - type = "string" + type = string default = "" description = "Prefix for cluster and instance identifier" } variable "azs" { - type = "list" + type = list(string) description = "List of AZs to use" } variable "replica_count" { - type = "string" + type = string default = "0" description = "Number of reader nodes to create. If `replica_scale_enable` is `true`, the value of `replica_scale_min` is used instead." } variable "security_groups" { - type = "list" + type = list(string) description = "VPC Security Group IDs" } variable "instance_type" { - type = "string" + type = string default = "db.t2.small" description = "Instance type to use" } variable "publicly_accessible" { - type = "string" + type = string default = "false" description = "Whether the DB should have a public IP address" } @@ -58,174 +58,175 @@ variable "username" { } variable "password" { - type = "string" + type = string description = "Master DB password" } variable "final_snapshot_identifier" { - type = "string" + type = string default = "final" description = "The name to use when creating a final snapshot on cluster destroy, appends a random 8 digits to name to ensure it's unique too." } variable "skip_final_snapshot" { - type = "string" + type = string default = "false" description = "Should a final snapshot be created on cluster destroy" } variable "backup_retention_period" { - type = "string" + type = string default = "7" description = "How long to keep backups for (in days)" } variable "preferred_backup_window" { - type = "string" + type = string default = "02:00-03:00" description = "When to perform DB backups" } variable "preferred_maintenance_window" { - type = "string" + type = string default = "sun:05:00-sun:06:00" description = "When to perform DB maintenance" } variable "port" { - type = "string" + type = string default = "3306" description = "The port on which to accept connections" } variable "apply_immediately" { - type = "string" + type = string default = "false" description = "Determines whether or not any DB modifications are applied immediately, or during the maintenance window" } variable "monitoring_interval" { - type = "string" + type = string default = 0 description = "The interval (seconds) between points when Enhanced Monitoring metrics are collected" } variable "auto_minor_version_upgrade" { - type = "string" + type = string default = "false" description = "Determines whether minor engine upgrades will be performed automatically in the maintenance window" } variable "db_parameter_group_name" { - type = "string" + type = string default = "default.aurora5.6" description = "The name of a DB parameter group to use" } variable "db_cluster_parameter_group_name" { - type = "string" + type = string default = "default.aurora5.6" description = "The name of a DB Cluster parameter group to use" } variable "deletion_protection" { - type = "string" + type = string default = "true" description = "If the DB instance should have deletion protection enabled. The database can't be deleted when this value is set to true." } variable "snapshot_identifier" { - type = "string" + type = string default = "" description = "DB snapshot to create this database from" } variable "storage_encrypted" { - type = "string" + type = string default = "true" description = "Specifies whether the underlying storage layer should be encrypted" } variable "cw_alarms" { - type = "string" + type = string default = false description = "Whether to enable CloudWatch alarms - requires `cw_sns_topic` is specified" } variable "cw_sns_topic" { - type = "string" + type = string default = "false" description = "An SNS topic to publish CloudWatch alarms to" } variable "cw_max_conns" { - type = "string" + type = string default = "500" description = "Connection count beyond which to trigger a CloudWatch alarm" } variable "cw_max_cpu" { - type = "string" + type = string default = "85" description = "CPU threshold above which to alarm" } variable "cw_max_replica_lag" { - type = "string" + type = string default = "2000" description = "Maximum Aurora replica lag in milliseconds above which to alarm" } variable "engine" { - type = "string" + type = string default = "aurora" description = "Aurora database engine type, currently aurora, aurora-mysql or aurora-postgresql" } variable "engine-version" { - type = "string" + type = string default = "5.6.10a" description = "Aurora database engine version." } variable "replica_scale_enabled" { - type = "string" + type = string default = false description = "Whether to enable autoscaling for RDS Aurora (MySQL) read replicas" } variable "replica_scale_max" { - type = "string" + type = string default = "0" description = "Maximum number of replicas to allow scaling for" } variable "replica_scale_min" { - type = "string" + type = string default = "2" description = "Maximum number of replicas to allow scaling for" } variable "replica_scale_cpu" { - type = "string" + type = string default = "70" description = "CPU usage to trigger autoscaling at" } variable "replica_scale_in_cooldown" { - type = "string" + type = string default = "300" description = "Cooldown in seconds before allowing further scaling operations after a scale in" } variable "replica_scale_out_cooldown" { - type = "string" + type = string default = "300" description = "Cooldown in seconds before allowing further scaling operations after a scale out" } variable "performance_insights_enabled" { - type = "string" + type = string default = false description = "Whether to enable Performance Insights" } + diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..ac97c6a --- /dev/null +++ b/versions.tf @@ -0,0 +1,4 @@ + +terraform { + required_version = ">= 0.12" +}