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 includes disowning the resources from the Cloudformation stack and updating manually. Mangling the Cloudformation state is both inconvenient and stressful, so here is a guide on how to handle the upgrades in place without data loss.

NOTE!

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 latest MySQL 5.7 engine version, and both have 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
    ...

Swap to default parameter groups

Start by updating 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
    ...

Update engine and parameter groups

set the engine version to upgrade target, change the parameter groups to use the upgrade target defaults.

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
    ...

At this point the Aurora cluster and instances will be upgraded. Unless you have blue/green deployments configured, this will cause downtime, the length of which depends largely on the size of the database.

Switch back to custom parameter groups

Once the engine upgrade is done, switch back to using custom the parameter groups.
Keep in mind that major engine upgrades usually include breaking changes, so modify the parameters 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

If everything went according to plan, you should now have an upgraded Aurora cluster running. If upgrade downtime is not acceptable, configuring blue/green deployments for Aurora is pretty simple.