-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Blue/green deployment for postgres (#517)
- Loading branch information
1 parent
9c264b9
commit 9c18851
Showing
41 changed files
with
530 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Blue/Green deployment example for PostgreSQL | ||
|
||
Configuration in this directory creates a set of RDS resources including DB instance, DB subnet group and DB parameter group. | ||
|
||
## Usage | ||
|
||
To run this example you need to execute: | ||
|
||
```bash | ||
$ terraform init | ||
$ terraform plan | ||
$ terraform apply | ||
``` | ||
|
||
To see blue/green deployment, update the `engine_version` argument in `module.postgres` to 15.4 and/or `engine_version` in module.mysql to 8.0.34 after initial apply then execute: | ||
|
||
```bash | ||
$ terraform plan | ||
$ terraform apply | ||
``` | ||
|
||
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. | ||
|
||
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> | ||
## Requirements | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 | | ||
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.25 | | ||
|
||
## Providers | ||
|
||
| Name | Version | | ||
|------|---------| | ||
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.25 | | ||
|
||
## Modules | ||
|
||
| Name | Source | Version | | ||
|------|--------|---------| | ||
| <a name="module_mysql"></a> [mysql](#module\_mysql) | ../../ | n/a | | ||
| <a name="module_mysql_security_group"></a> [mysql\_security\_group](#module\_mysql\_security\_group) | terraform-aws-modules/security-group/aws | ~> 5.0 | | ||
| <a name="module_postgres"></a> [postgres](#module\_postgres) | ../../ | n/a | | ||
| <a name="module_postgres_security_group"></a> [postgres\_security\_group](#module\_postgres\_security\_group) | terraform-aws-modules/security-group/aws | ~> 5.0 | | ||
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | | ||
|
||
## Resources | ||
|
||
| Name | Type | | ||
|------|------| | ||
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | ||
|
||
## Inputs | ||
|
||
No inputs. | ||
|
||
## Outputs | ||
|
||
| Name | Description | | ||
|------|-------------| | ||
| <a name="output_db_instance_status"></a> [db\_instance\_status](#output\_db\_instance\_status) | The RDS instance status | | ||
| <a name="output_mysql_db_instance_address"></a> [mysql\_db\_instance\_address](#output\_mysql\_db\_instance\_address) | The address of the RDS instance | | ||
| <a name="output_mysql_db_instance_arn"></a> [mysql\_db\_instance\_arn](#output\_mysql\_db\_instance\_arn) | The ARN of the RDS instance | | ||
| <a name="output_mysql_db_instance_availability_zone"></a> [mysql\_db\_instance\_availability\_zone](#output\_mysql\_db\_instance\_availability\_zone) | The availability zone of the RDS instance | | ||
| <a name="output_mysql_db_instance_cloudwatch_log_groups"></a> [mysql\_db\_instance\_cloudwatch\_log\_groups](#output\_mysql\_db\_instance\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | | ||
| <a name="output_mysql_db_instance_endpoint"></a> [mysql\_db\_instance\_endpoint](#output\_mysql\_db\_instance\_endpoint) | The connection endpoint | | ||
| <a name="output_mysql_db_instance_engine"></a> [mysql\_db\_instance\_engine](#output\_mysql\_db\_instance\_engine) | The database engine | | ||
| <a name="output_mysql_db_instance_engine_version_actual"></a> [mysql\_db\_instance\_engine\_version\_actual](#output\_mysql\_db\_instance\_engine\_version\_actual) | The running version of the database | | ||
| <a name="output_mysql_db_instance_hosted_zone_id"></a> [mysql\_db\_instance\_hosted\_zone\_id](#output\_mysql\_db\_instance\_hosted\_zone\_id) | The canonical hosted zone ID of the DB instance (to be used in a Route 53 Alias record) | | ||
| <a name="output_mysql_db_instance_identifier"></a> [mysql\_db\_instance\_identifier](#output\_mysql\_db\_instance\_identifier) | The RDS instance identifier | | ||
| <a name="output_mysql_db_instance_name"></a> [mysql\_db\_instance\_name](#output\_mysql\_db\_instance\_name) | The database name | | ||
| <a name="output_mysql_db_instance_port"></a> [mysql\_db\_instance\_port](#output\_mysql\_db\_instance\_port) | The database port | | ||
| <a name="output_mysql_db_instance_resource_id"></a> [mysql\_db\_instance\_resource\_id](#output\_mysql\_db\_instance\_resource\_id) | The RDS Resource ID of this instance | | ||
| <a name="output_mysql_db_instance_username"></a> [mysql\_db\_instance\_username](#output\_mysql\_db\_instance\_username) | The master username for the database | | ||
| <a name="output_mysql_db_parameter_group_arn"></a> [mysql\_db\_parameter\_group\_arn](#output\_mysql\_db\_parameter\_group\_arn) | The ARN of the db parameter group | | ||
| <a name="output_mysql_db_parameter_group_id"></a> [mysql\_db\_parameter\_group\_id](#output\_mysql\_db\_parameter\_group\_id) | The db parameter group id | | ||
| <a name="output_mysql_db_subnet_group_arn"></a> [mysql\_db\_subnet\_group\_arn](#output\_mysql\_db\_subnet\_group\_arn) | The ARN of the db subnet group | | ||
| <a name="output_mysql_db_subnet_group_id"></a> [mysql\_db\_subnet\_group\_id](#output\_mysql\_db\_subnet\_group\_id) | The db subnet group name | | ||
| <a name="output_postgres_db_instance_address"></a> [postgres\_db\_instance\_address](#output\_postgres\_db\_instance\_address) | The address of the RDS instance | | ||
| <a name="output_postgres_db_instance_arn"></a> [postgres\_db\_instance\_arn](#output\_postgres\_db\_instance\_arn) | The ARN of the RDS instance | | ||
| <a name="output_postgres_db_instance_availability_zone"></a> [postgres\_db\_instance\_availability\_zone](#output\_postgres\_db\_instance\_availability\_zone) | The availability zone of the RDS instance | | ||
| <a name="output_postgres_db_instance_cloudwatch_log_groups"></a> [postgres\_db\_instance\_cloudwatch\_log\_groups](#output\_postgres\_db\_instance\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | | ||
| <a name="output_postgres_db_instance_endpoint"></a> [postgres\_db\_instance\_endpoint](#output\_postgres\_db\_instance\_endpoint) | The connection endpoint | | ||
| <a name="output_postgres_db_instance_engine"></a> [postgres\_db\_instance\_engine](#output\_postgres\_db\_instance\_engine) | The database engine | | ||
| <a name="output_postgres_db_instance_engine_version_actual"></a> [postgres\_db\_instance\_engine\_version\_actual](#output\_postgres\_db\_instance\_engine\_version\_actual) | The running version of the database | | ||
| <a name="output_postgres_db_instance_hosted_zone_id"></a> [postgres\_db\_instance\_hosted\_zone\_id](#output\_postgres\_db\_instance\_hosted\_zone\_id) | The canonical hosted zone ID of the DB instance (to be used in a Route 53 Alias record) | | ||
| <a name="output_postgres_db_instance_identifier"></a> [postgres\_db\_instance\_identifier](#output\_postgres\_db\_instance\_identifier) | The RDS instance identifier | | ||
| <a name="output_postgres_db_instance_name"></a> [postgres\_db\_instance\_name](#output\_postgres\_db\_instance\_name) | The database name | | ||
| <a name="output_postgres_db_instance_port"></a> [postgres\_db\_instance\_port](#output\_postgres\_db\_instance\_port) | The database port | | ||
| <a name="output_postgres_db_instance_resource_id"></a> [postgres\_db\_instance\_resource\_id](#output\_postgres\_db\_instance\_resource\_id) | The RDS Resource ID of this instance | | ||
| <a name="output_postgres_db_instance_status"></a> [postgres\_db\_instance\_status](#output\_postgres\_db\_instance\_status) | The RDS instance status | | ||
| <a name="output_postgres_db_instance_username"></a> [postgres\_db\_instance\_username](#output\_postgres\_db\_instance\_username) | The master username for the database | | ||
| <a name="output_postgres_db_parameter_group_arn"></a> [postgres\_db\_parameter\_group\_arn](#output\_postgres\_db\_parameter\_group\_arn) | The ARN of the db parameter group | | ||
| <a name="output_postgres_db_parameter_group_id"></a> [postgres\_db\_parameter\_group\_id](#output\_postgres\_db\_parameter\_group\_id) | The db parameter group id | | ||
| <a name="output_postgres_db_subnet_group_arn"></a> [postgres\_db\_subnet\_group\_arn](#output\_postgres\_db\_subnet\_group\_arn) | The ARN of the db subnet group | | ||
| <a name="output_postgres_db_subnet_group_id"></a> [postgres\_db\_subnet\_group\_id](#output\_postgres\_db\_subnet\_group\_id) | The db subnet group name | | ||
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
provider "aws" { | ||
region = local.region | ||
} | ||
|
||
data "aws_availability_zones" "available" {} | ||
|
||
locals { | ||
name = "blue-green-example" | ||
region = "eu-west-1" | ||
|
||
vpc_cidr = "10.0.0.0/16" | ||
azs = slice(data.aws_availability_zones.available.names, 0, 3) | ||
|
||
tags = { | ||
Name = local.name | ||
Example = local.name | ||
Repository = "https://github.com/terraform-aws-modules/terraform-aws-rds" | ||
} | ||
} | ||
|
||
################################################################################ | ||
# Postgres | ||
################################################################################ | ||
|
||
module "postgres" { | ||
source = "../../" | ||
|
||
identifier = "${local.name}-postgres" | ||
|
||
# All blue/green deployment compatible versions: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RDS_Fea_Regions_DB-eng.Feature.BlueGreenDeployments.html | ||
engine = "postgres" | ||
engine_version = "14.9" | ||
family = "postgres14" # DB parameter group | ||
major_engine_version = "14" # DB option group | ||
instance_class = "db.t4g.large" | ||
|
||
allocated_storage = 20 | ||
max_allocated_storage = 100 | ||
|
||
# NOTE: Do NOT use 'user' as the value for 'username' as it throws: | ||
# "Error creating DB Instance: InvalidParameterValue: MasterUsername | ||
# user cannot be used as it is a reserved word used by the engine" | ||
db_name = "blueGreenExamplePostgresql" | ||
username = "blue_green_example_postgresql" | ||
port = 5432 | ||
|
||
multi_az = true | ||
db_subnet_group_name = module.vpc.database_subnet_group | ||
vpc_security_group_ids = [module.postgres_security_group.security_group_id] | ||
|
||
maintenance_window = "Mon:00:00-Mon:03:00" | ||
backup_window = "03:00-06:00" | ||
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"] | ||
create_cloudwatch_log_group = true | ||
blue_green_update = { | ||
enabled = true | ||
} | ||
|
||
password = "UberSecretPassword" | ||
# Not supported with blue/green deployment | ||
manage_master_user_password = false | ||
|
||
backup_retention_period = 1 | ||
skip_final_snapshot = true | ||
deletion_protection = false | ||
|
||
parameters = [ | ||
# required for blue-green deployment | ||
{ | ||
name = "rds.logical_replication" | ||
value = 1 | ||
apply_method = "pending-reboot" | ||
} | ||
] | ||
|
||
tags = local.tags | ||
} | ||
|
||
################################################################################ | ||
# MySQL | ||
################################################################################ | ||
|
||
module "mysql" { | ||
source = "../../" | ||
|
||
identifier = "${local.name}-mysql" | ||
|
||
# All blue/green deployment compatible versions: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RDS_Fea_Regions_DB-eng.Feature.BlueGreenDeployments.html | ||
engine = "mysql" | ||
engine_version = "8.0.33" | ||
family = "mysql8.0" # DB parameter group | ||
major_engine_version = "8.0" # DB option group | ||
instance_class = "db.t4g.large" | ||
|
||
allocated_storage = 20 | ||
max_allocated_storage = 100 | ||
|
||
db_name = "blueGreenExampleMysql" | ||
username = "blue_green_example_mysql" | ||
port = 3306 | ||
|
||
password = "UberSecretPassword" | ||
# Not supported with blue/green deployment | ||
manage_master_user_password = false | ||
|
||
multi_az = true | ||
db_subnet_group_name = module.vpc.database_subnet_group | ||
vpc_security_group_ids = [module.mysql_security_group.security_group_id] | ||
|
||
maintenance_window = "Mon:00:00-Mon:03:00" | ||
backup_window = "03:00-06:00" | ||
enabled_cloudwatch_logs_exports = ["general"] | ||
create_cloudwatch_log_group = true | ||
blue_green_update = { | ||
enabled = true | ||
} | ||
|
||
skip_final_snapshot = true | ||
deletion_protection = false | ||
|
||
tags = local.tags | ||
} | ||
|
||
################################################################################ | ||
# Supporting Resources | ||
################################################################################ | ||
|
||
module "vpc" { | ||
source = "terraform-aws-modules/vpc/aws" | ||
version = "~> 5.0" | ||
|
||
name = local.name | ||
cidr = local.vpc_cidr | ||
|
||
azs = local.azs | ||
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] | ||
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] | ||
database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] | ||
|
||
create_database_subnet_group = true | ||
|
||
tags = local.tags | ||
} | ||
|
||
module "postgres_security_group" { | ||
source = "terraform-aws-modules/security-group/aws" | ||
version = "~> 5.0" | ||
|
||
name = "${local.name}-postgresql" | ||
description = "Blue/Green deployment PostgreSQL example security group" | ||
vpc_id = module.vpc.vpc_id | ||
|
||
# ingress | ||
ingress_with_cidr_blocks = [ | ||
{ | ||
from_port = 5432 | ||
to_port = 5432 | ||
protocol = "tcp" | ||
description = "PostgreSQL access from within VPC" | ||
cidr_blocks = module.vpc.vpc_cidr_block | ||
}, | ||
] | ||
|
||
tags = local.tags | ||
} | ||
|
||
|
||
module "mysql_security_group" { | ||
source = "terraform-aws-modules/security-group/aws" | ||
version = "~> 5.0" | ||
|
||
name = "${local.name}-mysql" | ||
description = "Blue/Green deployment MySQL example security group" | ||
vpc_id = module.vpc.vpc_id | ||
|
||
# ingress | ||
ingress_with_cidr_blocks = [ | ||
{ | ||
from_port = 3306 | ||
to_port = 3306 | ||
protocol = "tcp" | ||
description = "MySQL access from within VPC" | ||
cidr_blocks = module.vpc.vpc_cidr_block | ||
}, | ||
] | ||
|
||
tags = local.tags | ||
} |
Oops, something went wrong.