Aurora Engine Upgrade with Cloudformation

05 June, 2023

Recently, I was tasked with updating an Aurora MySQL database engine from version 5.7 to 8.0 via Cloudformation. According to various internet sources, this usually necessitates the use of DbSnapshotIdentifier, or alternatively disowning the resources from the Cloudformation stack momentarily, while updates are executed manually.

Mangling the Cloudformation state is both inconvenient and stressful, and I really did not want to include the DbSnapshotIdentifier in the template, so here is a guide on how to handle the upgrades in place without doing either.

Note that following these steps will cause downtime unless blue/green RDS deployments are configured.

Example infrastructure

Consider this simplified example running an Aurora MySQL cluster with a single DB instance. The cluster is running the latest MySQL 5.7 engine version, and both are using a custom parameter group:

ClusterParamGroup:
  Type: "AWS::RDS::DBClusterParameterGroup"
  Properties:
    Description: Aurora cluster parameters
    Family: "aurora-mysql5.7"
    Parameters:
    ...

InstanceParamGroup:
  Type: "AWS::RDS::DBParameterGroup"
  Properties:
    Description: Aurora instance parameters
    Family: "aurora-mysql5.7"
    Parameters:
    ...

Cluster:
  Type: "AWS::RDS::DBCluster"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBClusterParameterGroupName: !Ref ClusterParamGroup
    Engine: aurora-mysql
    EngineVersion: "5.7.mysql_aurora.2.03.2"
    ...

Instance:
  Type: "AWS::RDS::DBInstance"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBParameterGroupName: !Ref InstanceParamGroup
    DBSubnetGroupName: !Ref RDSSubnetGroup
    Engine: aurora-mysql
    ...

1. Swap to default parameter groups

Update the resources to use the default parameter groups appropriate for the current engine version:

Cluster:
  Type: "AWS::RDS::DBCluster"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBClusterParameterGroupName: "default.aurora-mysql5.7" # default for 5.7
    Engine: aurora-mysql
    EngineVersion: "5.7.mysql_aurora.2.03.2"

Instance:
  Type: "AWS::RDS::DBInstance"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBParameterGroupName:  "default.aurora-mysql5.7" # default for 5.7
    DBSubnetGroupName: !Ref RDSSubnetGroup
    Engine: aurora-mysql
    ...

2. Update engine and parameter groups

Set the engine version to upgrade target, change the parameter groups to use the upgrade target defaults. Applying this template will upgraded the Aurora cluster and instances.

Cluster:
  Type: "AWS::RDS::DBCluster"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBClusterParameterGroupName: "default.aurora-mysql8.0" # default for 8.0
    Engine: aurora-mysql
    EngineVersion: "8.0.mysql_aurora.3.03.1" # new engine version

Instance:
  Type: "AWS::RDS::DBInstance"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBParameterGroupName:  "default.aurora-mysql8.0" # default for 8.0
    DBSubnetGroupName: !Ref RDSSubnetGroup
    Engine: aurora-mysql
    ...

3. Switch back to custom parameter groups

Once the engine upgrade is done, switch back custom parameter groups.
Keep in mind that major engine upgrades (like the one in this example) usually include breaking changes, so modify the parameter group(s) accordingly.

ClusterParamGroup:
  Type: "AWS::RDS::DBClusterParameterGroup"
  Properties:
    Description: Aurora cluster parameters
    Family: "aurora-mysql8.0" # change family to match engine version
    Parameters:
    ...

InstanceParamGroup:
  Type: "AWS::RDS::DBParameterGroup"
  Properties:
    Description: Aurora instance parameters
    Family: "aurora-mysql8.0" # change family to match engine version
    Parameters:
    ...

Cluster:
  Type: "AWS::RDS::DBCluster"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBClusterParameterGroupName: !Ref ClusterParamGroup # custom parameter group
    Engine: aurora-mysql
    EngineVersion: "8.0.mysql_aurora.3.03.1"
    ...

Instance:
  Type: "AWS::RDS::DBInstance"
  Properties:
    DBClusterIdentifier: !Ref Cluster
    DBParameterGroupName: !Ref InstanceParamGroup # custom parameter group
    DBSubnetGroupName: !Ref RDSSubnetGroup
    Engine: aurora-mysql

Conclusions

You should now have an upgraded Aurora cluster running.
If necessary, the operation can be done with zero downtime by configuring blue/green deployments for Aurora.