【Aurora PostgreSQL】メジャーバージョンアップ時に CloudFormation で管理する DB パラメータグループを更新する

# 初めに

Aurora PostgreSQL のメジャーバージョンアップの際、CFn で管理している DB パラメータグループの更新がうまくいかなかったのでどうするか考えました。

# DB パラメータグループの更新

## DB パラメータグループ更新に関する CFn のドキュメント

パラメータグループの Family はスタック更新では更新できないことが記載されています。

> The DB parameter group family can't be changed when updating a DB parameter group.

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbparametergroup.html#cfn-rds-dbparametergroup-family

クラスターパラメータグループについても同様です。

> The DB cluster parameter group family can't be changed when updating a DB cluster parameter group.

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbclusterparametergroup.html#cfn-rds-dbclusterparametergroup-family

ナレッジセンターにトラブルシューティングの記載があります。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-rds-cluster-engine/

## 更新時のエラー

![cfn-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/6ffd012c-d1ca-aefb-daff-8ebbd8722d05.png)

> The following parameters are not defined for the specified group: enable_partitionwise_aggregate, babelfishpg_tds.listen_addresses, enable_parallel_append, cron.max_running_jobs, enable_incremental_sort, enable_partition_pruning, log_parameter_max_length_on_error, cron.log_statement, log_min_duration_sample, apg_enable_semijoin_push_down, cron.database_name, cron.log_run, log_parameter_max_length, enable_parallel_hash, hash_mem_multiplier, babelfishpg_tds.tds_debug_log_level, cron.use_background_workers, enable_partitionwise_join (Service: AmazonRDS; Status Code: 400; Error Code: InvalidParameterValue;)

# 更新手順


## 前提条件

Aurora PostgreSQL 10.20 を以下のテンプレートで作成するとします。簡単に各セクションについてまとめます。
- Resource セクション
  - Aurora クラスター、Aurora インスタンス、Aurora DB クラスターパラメータグループ、Aurora DB パラメータグループ
- Parameters セクション
  - DB エンジンバージョン
- Mappings セクション
  - パラメータグループファミリー

```yaml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  DBEngineVersion:
    Type: String
    Default: '10.20'
    AllowedValues:
      - '10.20'
      - '13.6'
Mappings:
  DBFamilyMap:
    '10.20':
      family: aurora-postgresql10
    '13.6':
      family: aurora-postgresql13
Resources:
  AuroraDBCluster:
    Type: 'AWS::RDS::DBCluster'
    Properties:
      Engine: aurora-postgresql
      EngineMode: provisioned
      EngineVersion: !Ref DBEngineVersion
      DBClusterParameterGroupName: !Ref DBClusterParameterGroup
      MasterUsername: postgres
      MasterUserPassword: PostgresAdmin1!
  AuroraDBInstance:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      Engine: aurora-postgresql
      DBInstanceClass: db.t3.medium
      DBClusterIdentifier: !Ref AuroraDBCluster
      DBParameterGroupName: !Ref DBParameterGroup
  DBClusterParameterGroup:
    Type: 'AWS::RDS::DBClusterParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Cluster Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
      Parameters:
        timezone: Asia/Tokyo
  DBParameterGroup:
    Type: 'AWS::RDS::DBParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
```

## 1. 手動アップグレードを行う

ドキュメントに以下のように記載があるので CloudFormation を使わずに手動でアップグレードします。

>メジャーバージョンのアップグレードには、以前のバージョンのデータベースと下位互換性のないデータベースの変更が含まれる場合があります。その場合、既存のアプリケーションが適切に動作しなくなることがあります。そのため、Amazon Aurora では、メジャーバージョンアップグレードは自動的に適用されません。メジャーバージョンのアップグレードを行うには、DB クラスターを手動で変更します。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.PostgreSQL.html#USER_UpgradeDBInstance.PostgreSQL.MajorVersion

アップグレードしたいクラスターを選択し、「変更」をクリックします。

![upgrade-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/5915d4a1-06b2-9e94-36ec-e1227526e4c9.png)

エンジンバージョンをアップグレード先バージョンに変更します。

![upgrade-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/8071a8b9-169f-d338-e162-4ed6d2a47623.png)

「すぐに適用」をクリックします。

![upgrade-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/1bf581f6-dfb3-dfdc-2c49-d70d1c555659.png)

アップグレードが始まるので完了するまで待ちます。

![upgrade-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/baee735d-7a05-06eb-dbd9-505563ff2b36.png)

アップグレードが完了したことを確認します。

![upgrade-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/0274d7f0-6c3b-38fe-afd0-54272df415cc.png)

## 2. CFn のパラメータ更新とパラメータグループを更新する

以下のテンプレートで変更セットを作成します。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  DBEngineVersion:
    Type: String
    Default: '10.20'
    AllowedValues:
      - '10.20'
      - '13.6'
Mappings:
  DBFamilyMap:
    '10.20':
      family: aurora-postgresql10
    '13.6':
      family: aurora-postgresql13
Resources:
  AuroraDBCluster:
    Type: 'AWS::RDS::DBCluster'
    Properties:
      Engine: aurora-postgresql
      EngineMode: provisioned
      EngineVersion: !Ref DBEngineVersion
      DBClusterParameterGroupName: !Ref DBClusterParameterGroupPostgreSQL13
      MasterUsername: postgres
      MasterUserPassword: PostgresAdmin1!
  AuroraDBInstance:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      Engine: aurora-postgresql
      DBInstanceClass: db.t3.medium
      DBClusterIdentifier: !Ref AuroraDBCluster
      DBParameterGroupName: !Ref DBParameterGroupPostgreSQL13
  DBClusterParameterGroupPostgreSQL13:
    Type: 'AWS::RDS::DBClusterParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Cluster Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
      Parameters:
        timezone: Asia/Tokyo
  DBParameterGroupPostgreSQL13:
    Type: 'AWS::RDS::DBParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
```

変更セットを作成します。

![change-set-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/b86d9209-f3d4-2efd-eebf-af8c715c1804.png)

編集したテンプレートをアップロードします。

![change-set-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/6f69e6a4-2090-4a88-16c3-1aa57da9a72d.png)

`DBEngineVersion` の値はアップグレード先バージョンを選択します。

![change-set-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/d2e10bf8-7d3c-c5eb-2f1a-82676afe7f16.png)

変更内容を確認します。

![change-set-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/19424173-5bf7-efd9-2eb9-831da1226817.png)

実行をクリックします。

![change-set-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/e9b36d22-0c54-a205-588d-e1270bb04dca.png)

「変更セットを実行」をクリックします。

![change-set-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/2bc08a05-e024-0ce5-5f6b-439796aa4a77.png)

変更セット実行後、CFn のパラメータ更新と、古い DB パラメータグループが削除されていることを確認します。

- CFn パラメータ更新

**更新前**

![cfn-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/2e13c041-745e-77aa-c72e-f867620eeda9.png)

**更新後**

![cfn-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/a53cdffc-12b1-82ab-c4bd-e701c9e0be2c.png)

- 古い DB パラメータグループが削除されていること

**更新前**

![cfn-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/c84d9639-4ea3-66c2-8ec8-f7f50cd5c702.png)

**更新後**

![cfn-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/6abe60e6-1e05-881f-f183-c578a1023db6.png)

# 考慮事項

## スタック更新時のインスタンスの挙動

2 回目のスタック更新時、DB インスタンスのステータスが「変更中」となっていました。

![update-stack-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/eeced5f4-8a26-902b-7ffa-b2cd2e7eb279.png)

その後、インスタンスは再起動されました。

![update-stack-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/92893a26-d472-e149-a04a-eff138b81d2b.png)

スタック更新前後で作成したインスタンスが初期化されるのではと思いましたが、スタック更新前に作成したテーブルはスタック更新後も残っていました。これは CFn のドキュメントに更新動作の記述がありました。`EngineVersion` の更新動作は「一時的な中断を伴う更新」でしたので、インスタンスが初期化されることはないようです。（変更セットのコンソール画面からも置換列の値が「False」になっていることが確認できます）

> Update requires: Some interruptions

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-engineversion

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html

## AllowMajorVersionUpgrade プロパティ

`AWS::RDS::Instance` には `AllowMajorVersionUpgrade` というプロパティがあります。

> A value that indicates whether major version upgrades are allowed. Changing this parameter doesn't result in an outage and the change is asynchronously applied as soon as possible.
> Constraints: Major version upgrades must be allowed when specifying a value for the EngineVersion parameter that is a different major version than the DB instance's current version.

Aurora ではない RDS ではこれまでに書いた手順よりもメジャーバージョンアップが簡単にできるようです。
以下に記載があります。

https://dev.classmethod.jp/articles/upgrade-amazon-rds-using-aws-cloudformation/

以下のようなテンプレートでスタックを更新しました。
※`DBEngineVersion` はスタック更新時にアップグレード先バージョンに変更します。

```yaml
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  DBEngineVersion:
    Type: String
    Default: '10.20'
    AllowedValues:
      - '10.20'
      - '13.6'
Mappings:
  DBFamilyMap:
    '10.20':
      family: aurora-postgresql10
    '13.6':
      family: aurora-postgresql13
Resources:
  AuroraDBCluster:
    Type: 'AWS::RDS::DBCluster'
    Properties:
      Engine: aurora-postgresql
      EngineMode: provisioned
      EngineVersion: !Ref DBEngineVersion
      DBClusterParameterGroupName: !Ref DBClusterParameterGroupPostgreSQL13
      MasterUsername: postgres
      MasterUserPassword: PostgresAdmin1!
  AuroraDBInstance:
    Type: 'AWS::RDS::DBInstance'
    Properties:
      Engine: aurora-postgresql
      DBInstanceClass: db.t3.medium
      AllowMajorVersionUpgrade: true
      DBClusterIdentifier: !Ref AuroraDBCluster
      DBParameterGroupName: !Ref DBParameterGroupPostgreSQL13
  DBClusterParameterGroupPostgreSQL13:
    Type: 'AWS::RDS::DBClusterParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Cluster Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
      Parameters:
        timezone: Asia/Tokyo
  DBParameterGroupPostgreSQL13:
    Type: 'AWS::RDS::DBParameterGroup'
    Properties:
      Description: Aurora PostgreSQL Parameter Group
      Family: !FindInMap 
        - DBFamilyMap
        - !Ref DBEngineVersion
        - family
```

しかし、以下のようなエラーでスタック更新に失敗しました。`AWS::RDS::DBCluster` には `AllowMajorVersionUpgrade ` プロパティが存在しないので、DB クラスターの更新に失敗するようです。

![cfn-7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/bb9f5c36-ca03-eedf-86e2-c61cea41a836.png)

> The current DB instance parameter group aurora-stack-2-dbparametergroup-bm9hsf6qkay4 is custom. You must explicitly specify a new DB instance parameter group, either default or custom, for the engine version upgrade.



# 参考資料

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-rds-cluster-engine/

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.PostgreSQL.html#USER_UpgradeDBInstance.PostgreSQL.MajorVersion

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html

https://aws.amazon.com/jp/blogs/news/deploy-an-amazon-aurora-postgresql-db-cluster-with-recommended-best-practices-using-aws-cloudformation/

https://dev.classmethod.jp/articles/upgrade-amazon-rds-using-aws-cloudformation/

https://aws.amazon.com/jp/blogs/news/amazon-aurora-postgresql-10-endoflife/

https://repost.aws/questions/QU0ligxMlJSJWhzzgKbKgytQ/announcement-amazon-aurora-postgre-sql-10-x-end-of-support-is-january-31-2023