Skip to content

Commit

Permalink
Bump to 16.2 (#627)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJBoyer authored Jun 11, 2024
1 parent e344b29 commit d411e78
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 2 deletions.
84 changes: 84 additions & 0 deletions docs/infra/upgrade-database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Upgrade database

Upgrading the database between major versions (e.g., from Postgres 15 to 16) is a two-step process.

1. Create a new DBParameterGroup for the new engine version and upgrade the database.
2. Remove the old DBParamaterGroup for the prior engine version.

These steps are a minimal starting point for the changes you'll need to make. As with any major change to your codebase, you should carefully test the impact of upgrading the database before applying it to a production environment. See also the AWS documentation for [Upgrading the PostgreSQL DB engine for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.PostgreSQL.html#USER_UpgradeDBInstance.PostgreSQL.MajorVersion.Process).

## 1. Creating a new DBParameterGroup and upgrading the database

1. Set `allow_major_version_upgrade = true`

Set the `aws_rds_cluster` resource in [infra/modules/database/main.tf#L20](../../infra/modules/database/main.tf).

2. (if needed) Update the `serverlessv2_scaling_configuration`

Set the `min_capacity` to 4.0 (and adjust the `max_capacity` accordingly).
If your minimum is lower than this, the upgrade will fail with `FATAL: shared memory segment sizes are configured too large`.

3. Create a new DBParamaterGroup

The database will need access to a new parameter group as part of the upgrade, but the old parameter group can't be deleted until the upgrade is complete.

Make a copy of the `rds_query_logging` resource.
In the original, replace the `${local.engine_major_version}` variable with your current database version.
Then, in the duplicate version, modify the resource name to a new unique value.

E.g., if you were moving from Postgres 14 to Postgres 15, your configuration would look like:

```terraform
# This is the original; note we are manually specifying the family is v14 since after the changes are applied the new engine major version will be 15.
resource "aws_rds_cluster_parameter_group" "rds_query_logging" {
family = "aurora-postgresql14"
...
}
# This is the new parameter group; we have given it a new name to distinguish it.
resource "aws_rds_cluster_parameter_group" "rds_query_logging_15" {
family = "aurora-postgresql${local.engine_major_version}"
...
}
```

Modify the `db_cluster_parameter_group_name` to reference this new parameter group:

```terraform
resource "aws_rds_cluster" "db" {
...
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.rds_query_logging_15.name
...
}
```

4. Set the `engine_version` to your new desired version.

5. Run `make infra-update-app-database APP_NAME=<APP_NAME> ENVIRONMENT=<ENV_NAME>`

Note that the upgrade is not applied immediately; it is queued for the next maintenance window.

If you wish to apply the upgrade immediately, you can manually change the engine version to match in the AWS Console. See also:

- https://developer.hashicorp.com/terraform/tutorials/aws/aws-rds
- https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html


## 2. Removing the old DBParameter group

Once the upgrade has been applied, you can remove the old parameter group.

You should also remove `allow_major_version_upgrade = true` (or set it to false).

If you had to increase your autoscaling settings to support the upgrade, you may wish to revert that change now as well.

Finally, the new DBParameter group will have a new resource name (e.g., in the example above, `rds_query_logging_15`). You can revert this to the original name (`rds_query_logging`) without modifying the infrastructure by using [Terraform's moved block](https://developer.hashicorp.com/terraform/cli/state/move), e.g.:

```terraform
moved {
from = aws_rds_cluster_parameter_group.rds_query_logging_15
to = aws_rds_cluster_parameter_group.rds_query_logging
}
```
5 changes: 3 additions & 2 deletions infra/modules/database/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ locals {
# See https://aws.amazon.com/blogs/database/using-iam-authentication-to-connect-with-pgadmin-amazon-aurora-postgresql-or-amazon-rds-for-postgresql/
db_user_arn_prefix = "arn:aws:rds-db:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:dbuser:${aws_rds_cluster.db.cluster_resource_id}"

engine_version = "14.6"
engine_version = "16.2"
engine_major_version = regex("^\\d+", local.engine_version)
}

Expand All @@ -34,6 +34,7 @@ resource "aws_rds_cluster" "db" {
manage_master_user_password = true
storage_encrypted = true
kms_key_id = aws_kms_key.db.arn
allow_major_version_upgrade = false

db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.rds_query_logging.name

Expand Down Expand Up @@ -76,7 +77,7 @@ resource "aws_kms_key" "db" {
# -------------

resource "aws_rds_cluster_parameter_group" "rds_query_logging" {
name = var.name
name = "${var.name}-${local.engine_major_version}"
family = "aurora-postgresql${local.engine_major_version}"
description = "Default cluster parameter group"

Expand Down
5 changes: 5 additions & 0 deletions infra/modules/database/role_manager/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,13 @@ def configure_database(conn: Connection) -> None:
schema_name = os.environ.get("DB_SCHEMA")
database_name = os.environ.get("DB_NAME")

# In Postgres 15 and higher, the CREATE privilege on the public
# schema is already revoked/removed from all users except the
# database owner. However, we are explicitly revoking access anyways
# for projects that wish to use earlier versions of Postgres.
print("---- Revoking default access on public schema")
db.execute(conn, "REVOKE CREATE ON SCHEMA public FROM PUBLIC")

print("---- Revoking database access from public role")
db.execute(conn, f"REVOKE ALL ON DATABASE {identifier(database_name)} FROM PUBLIC")
print(f"---- Setting default search path to schema {schema_name}")
Expand Down

0 comments on commit d411e78

Please sign in to comment.