Amazon Aurora MySQL のインプレースアップグレード機能
つい先日、Amazon Aurora にて、MySQL 5.6互換のバージョン1.xから、MySQL 5.7互換のバージョン2.xへインプレースアップデートが可能になりました。
Amazon Aurora が MySQL 5.6 から 5.7 へのインプレースアップグレードをサポート
この機能を使うことで、従来のようにスナップショットからの復元やレプリケーション、インスタンスの切替といった作業をしなくても、エンドポイントなどはそのままに、簡単にMySQL5.7互換にアップグレードすることが可能になります。
早速この機能でアップグレードを試みたのですが、CloudFormationで管理されているAuroraクラスターをアップグレードする際にちょっとハマったことがあったので、その内容と対応方法をシェアします。
アップデート前のRDS用CloudFormation stack
更新前のDBクラスタのCloudFormationでの定義はこんな感じでした。(わかりやすいよう最小限の記述のみにしてあります)
DevAuroraParameterGroup
というカスタムのインスタンスパラメータグループを使っています。
--- AWSTemplateFormatVersion: '2010-09-09' Description: RDS for sandbox Resources: DevAuroraParameterGroup: Type: AWS::RDS::DBParameterGroup Properties: Description: Development Aurora parameter group Family: aurora5.6 Parameters: max_connections: '1024' wait_timeout: '300' DevAuroraParameterGroup57: Type: AWS::RDS::DBParameterGroup Properties: Description: Development Aurora parameter group for 5.7 Family: aurora-mysql5.7 Parameters: max_connections: '1024' wait_timeout: '300' DBCluster: Type: AWS::RDS::DBCluster Properties: DBClusterIdentifier: test-cluster DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup Engine: aurora EngineVersion: 5.6.mysql_aurora.1.22.2 MasterUsername: "{{resolve:ssm:rds.username.default:1}}" MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:1}}" DBInstance: Type: AWS::RDS::DBInstance DeletionPolicy: Delete Properties: DBClusterIdentifier: Ref: DBCluster DBInstanceClass: db.t2.medium DBInstanceIdentifier: test-db Engine: aurora EngineVersion: 5.6.mysql_aurora.1.22.2 DBParameterGroupName: Ref: DevAuroraParameterGroup DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup
ハマったこと
これを、以下のように書き換えて適用することで、MySQL5.7互換バージョンへのインプレースアップグレードを試みます。
@@ -82,8 +82,8 @@ DBClusterIdentifier: test-cluster DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup - Engine: aurora - EngineVersion: 5.6.mysql_aurora.1.22.2 + Engine: aurora-mysql + EngineVersion: 5.7.mysql_aurora.2.07.3 MasterUsername: "{{resolve:ssm:rds.username.default:1}}" MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:2}}" DBInstance: @@ -94,9 +94,9 @@ Ref: DBCluster DBInstanceClass: db.t2.medium DBInstanceIdentifier: test-db - Engine: aurora - EngineVersion: 5.6.mysql_aurora.1.22.2 + Engine: aurora-mysql + EngineVersion: 5.7.mysql_aurora.2.07.3 DBParameterGroupName: - Ref: DevAuroraParameterGroup + Ref: DevAuroraParameterGroup57 DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup
しかし、以下のようなエラーで失敗してしまいました。
{ "LogicalResourceId": "DBCluster", "ResourceStatus": "UPDATE_FAILED", "ResourceStatusReason": "The current DB instance parameter group sandbox-rds-devauroraparametergroup-fxfe7dqcn31p is custom. You must explicitly specify a new DB instance parameter group, either default or custom, for the engine version upgrade. (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterCombination; Request ID: ...)" }
カスタムのインスタンスパラメータグループを使っているため、5.7に対応した新しい DevAuroraParameterGroup57
に切り替えるよう指定しなければなりません。
CLIであれば modify-db-cluster に --db-instance-parameter-group-name
オプションでこれを指定可能です。
しかし、どうやらCloudFormationではこれを渡すことができない様子です。同時に DBInstance
の更新をしても、異なるリソースの変更までは拾ってはくれないようです。。
対応方法その1
こういう時の一つの方法は、いったんCloudFormationの管理下から外してしまい、手動でアップデートしたのち、CloudFormationにインポートし直すという方法です。
DBCluster
およびDBInstance
にDeletionPolicy: Retain
を指定して適用することで、CloudFormationによってこれらが削除されないようにします。DBCluster
およびDBInstance
の定義を削除し、更新を行います。残ったクラスターをAWSコンソールで5.7に更新します。
5.7の定義で再度
DBCluster
およびDBInstance
の定義を追加し、「インポート」 を行います。この時、追加する各リソースに対応するインスタンスの識別子(ここではtest-cluster
とtest-db
)を指定することで、CloudFormationスタックに既存リソースを取り込むことが可能です。ドリフト検知を行い、定義と実態にズレがないことを確認します。
しかし、手動オペレーションはなるべく避けたいということで、次のような方法も考えてみました。
対応方法その2
エラーメッセージを見るに、カスタムのインスタンスパラメータグループを使わなければ良いのだろうということで、いったんデフォルトに戻し、インブレースアップグレード後に再びカスタムのパラメータを適用しなおしてみます。
まず、 DBInstance
のパラメータグループをデフォルトである default.aurora5.6
にしてスタックを更新します。
@@ -96,7 +96,6 @@ DBInstanceIdentifier: test-db Engine: aurora EngineVersion: 5.6.mysql_aurora.1.22.2 - DBParameterGroupName: - Ref: DevAuroraParameterGroup + DBParameterGroupName: default.aurora5.6 DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup
次に、 インプレースアップグレードと合わせて、新しいカスタムのパラメータグループも指定して再度更新します。
@@ -82,8 +82,8 @@ DBClusterIdentifier: test-cluster DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup - Engine: aurora - EngineVersion: 5.6.mysql_aurora.1.22.2 + Engine: aurora-mysql + EngineVersion: 5.7.mysql_aurora.2.07.3 MasterUsername: "{{resolve:ssm:rds.username.default:1}}" MasterUserPassword: "{{resolve:ssm-secure:rds.password.default:2}}" DBInstance: @@ -94,8 +94,9 @@ Ref: DBCluster DBInstanceClass: db.t2.medium DBInstanceIdentifier: test-db - Engine: aurora - EngineVersion: 5.6.mysql_aurora.1.22.2 - DBParameterGroupName: default.aurora5.6 + Engine: aurora-mysql + EngineVersion: 5.7.mysql_aurora.2.07.3 + DBParameterGroupName: + Ref: DevAuroraParameterGroup57 DBSubnetGroupName: Fn::ImportValue: DBSubnetGroup
これで、無事にCloudFormationのみでインプレースアップグレードが完了しました。 またMySQL5.7への移行完了後も、DBは問題なく利用できることを確認できました。
後者の方法は途中でパラメータグループの更新が余分に入るという欠点がありますが、対象が多くて自動化したい場合などはこちらの手段の方が良いこともあるかもしれません。
もっとうまく対応できる方法が提供されるとありがたいのですけれどね。