[アップデート] CloudFormationでRDSのパラメーターグループとオプショングループの名前が指定できるようになりました

しっかりとした命名規約がある環境待望のアップデート
2022.11.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

個人的にとっても嬉しい

こんにちは、のんピ(@non____97)です。

皆さんはCloudFormationでRDSのパラメーターグループとオプショングループの名前を指定したいと思ったことはありますか? 私はあります。

AWS CDKのAPI ReferenceでパラメーターグループのL1 Constructを確認すると、以下のように名前を指定する箇所がありません。

// The code below shows an example of how to instantiate this type.
// The values are placeholders you should change.
import { aws_rds as rds } from 'aws-cdk-lib';

declare const parameters: any;
const cfnDBParameterGroup = new rds.CfnDBParameterGroup(this, 'MyCfnDBParameterGroup', {
  description: 'description',
  family: 'family',

  // the properties below are optional
  parameters: parameters,
  tags: [{
    key: 'key',
    value: 'value',
  }],
});

それがなんと、改めてCloudFormationのユーザーガイドを見ると、RDSのパラメーターグループとオプショングループどちらも名前を指定できるようになっているではありませんか。

Type: AWS::RDS::DBParameterGroup
Properties: 
  DBParameterGroupName: String
  Description: String
  Family: String
  Parameters: Json
  Tags: 
    - Tag
Type: AWS::RDS::OptionGroup
Properties: 
  EngineName: String
  MajorEngineVersion: String
  OptionConfigurations: 
    - OptionConfiguration
  OptionGroupDescription: String
  OptionGroupName: String
  Tags: 
    - Tag

これはめちゃくちゃありがたいですね。

Release historyを確認すると、2022/11/3に更新されたようで、ほっかほかです。

Change Description Date
Updated resource The following resource was updated: AWS::RDS::DBClusterParameterGroup
AWS::RDS::DBClusterParameterGroup
Use the DBClusterParameterGroupName property to specify the name of the DB cluster parameter group.
November 3, 2022
Updated resource The following resource was updated: AWS::RDS::DBInstance
AWS::RDS::DBParameterGroup
Use the DBParameterGroupName property to specify the name of the DB parameter group.
November 3, 2022
Updated resource The following resource was updated: AWS::RDS::OptionGroup
AWS::RDS::OptionGroup
Use the OptionGroupName property to specify the name of the new option group.
November 3, 2022

早速試してみたので紹介します。

試してみた

名前を指定しない場合

パラメーターグループとオプショングループの名前を指定する前に、比較用として名前を指定しなかった場合にどのような名前が付与されるのか確認します。

パラメーターグループとオプショングループはAWS CDKで定義します。実際のコードは以下の通りです。

./lib/rds-stack.ts

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";

export class RdsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Parameter Group
    const dbParameterGroup = new cdk.aws_rds.ParameterGroup(
      this,
      "Parameter Group",
      {
        engine: cdk.aws_rds.DatabaseInstanceEngine.mysql({
          version: cdk.aws_rds.MysqlEngineVersion.VER_8_0,
        }),
      }
    );
    dbParameterGroup.bindToInstance({});

    // Option Group
    const dbOptionGroup = new cdk.aws_rds.OptionGroup(this, "Option Group", {
      engine: cdk.aws_rds.DatabaseInstanceEngine.mysql({
        version: cdk.aws_rds.MysqlEngineVersion.VER_8_0,
      }),
      configurations: [
        {
          name: "MARIADB_AUDIT_PLUGIN",
          settings: {
            SERVER_AUDIT_EVENTS:
              "CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL,QUERY_DML_NO_SELECT",
            SERVER_AUDIT_FILE_ROTATE_SIZE: "1000000",
            SERVER_AUDIT_FILE_ROTATIONS: "10",
          },
        },
      ],
    });
  }
}

パラメーターグループのL2 Constructは以下Issueの通り、DBインスタンスにバインドしなければ作成されません。

その対処として、dbParameterGroup.bindToInstance({})で空のオブジェクトにバインドしています。

こちらのコードでデプロイすると、以下のようなリソースが作成されました。

名前を指定しない場合の物理ID

どちらの物理IDもスタック名-論理ID-ランダムな文字列になっていますね。

名前を指定する場合

それでは、パラメーターグループとオプショングループに名前を指定してみましょう。

2022/11/5時点のAWS CDKの最新バージョン2.50.0のパラメーターグループ、オプショングループのL2 Constructは、まだ名前の指定をサポートしていませんでした。そのため、escape hatchesを参考にaddPropertyOverride()で名前を指定します。

実際のコードは以下の通りです。

./lib/rds-stack.ts

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";

export class RdsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Parameter Group
    const dbParameterGroup = new cdk.aws_rds.ParameterGroup(
      this,
      "Parameter Group",
      {
        engine: cdk.aws_rds.DatabaseInstanceEngine.mysql({
          version: cdk.aws_rds.MysqlEngineVersion.VER_8_0,
        }),
      }
    );
    dbParameterGroup.bindToInstance({});

    // Parameter Group Name
    const cfnDbParameterGroup = dbParameterGroup.node
      .defaultChild as cdk.aws_rds.CfnDBParameterGroup;

    cfnDbParameterGroup.addPropertyOverride(
      "DBParameterGroupName",
      "rds-db-pg"
    );

    // Option Group
    const dbOptionGroup = new cdk.aws_rds.OptionGroup(this, "Option Group", {
      engine: cdk.aws_rds.DatabaseInstanceEngine.mysql({
        version: cdk.aws_rds.MysqlEngineVersion.VER_8_0,
      }),
      configurations: [
        {
          name: "MARIADB_AUDIT_PLUGIN",
          settings: {
            SERVER_AUDIT_EVENTS:
              "CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL,QUERY_DML_NO_SELECT",
            SERVER_AUDIT_FILE_ROTATE_SIZE: "1000000",
            SERVER_AUDIT_FILE_ROTATIONS: "10",
          },
        },
      ],
    });

    // Option Group Name
    const cfnDbOptionGroup = dbOptionGroup.node
      .defaultChild as cdk.aws_rds.CfnOptionGroup;

    cfnDbOptionGroup.addPropertyOverride("OptionGroupName", "rds-db-og");
  }
}

cdk diffで差分を比較してみます。

>  (master →⚡) npx cdk diff
Stack RdsStack
Resources
[~] AWS::RDS::DBParameterGroup Parameter Group ParameterGroupC75674B9
 └─ [+] DBParameterGroupName
     └─ rds-db-pg
[~] AWS::RDS::OptionGroup Option Group OptionGroup1111E12F
 └─ [+] OptionGroupName
     └─ rds-db-og

名前が差分になっていますね。

cdk deployでデプロイすると、物理IDがそれぞれ指定した名前になりました。

名前を指定した場合の物理ID

AWS CLIで名前を指定して各リソースを参照してみます。

# パラメーターグループ
$ aws rds describe-db-parameter-groups \
    --db-parameter-group-name rds-db-pg
{
    "DBParameterGroups": [
        {
            "DBParameterGroupName": "rds-db-pg",
            "DBParameterGroupFamily": "mysql8.0",
            "Description": "Parameter group for mysql8.0",
            "DBParameterGroupArn": "arn:aws:rds:us-east-1:<AWSアカウントID>:pg:rds-db-pg"
        }
    ]
}

# オプショングループ
$ aws rds describe-option-groups \
    --option-group-name rds-db-og
{
    "OptionGroupsList": [
        {
            "OptionGroupName": "rds-db-og",
            "OptionGroupDescription": "Option group for mysql 8.0",
            "EngineName": "mysql",
            "MajorEngineVersion": "8.0",
            "Options": [
                {
                    "OptionName": "MARIADB_AUDIT_PLUGIN",
                    "OptionDescription": "MariaDB Audit Plugin",
                    "Persistent": false,
                    "Permanent": false,
                    "OptionSettings": [
                        {
                            "Name": "SERVER_AUDIT_EXCL_USERS",
                            "Description": "Exclude specified users",
                            "ApplyType": "DYNAMIC",
                            "DataType": "STRING",
                            "IsModifiable": true,
                            "IsCollection": true
                        },
                        {
                            "Name": "SERVER_AUDIT_FILE_PATH",
                            "Value": "/rdsdbdata/log/audit/",
                            "DefaultValue": "/rdsdbdata/log/audit/",
                            "Description": "File location for logs",
                            "ApplyType": "DYNAMIC",
                            "DataType": "STRING",
                            "IsModifiable": false,
                            "IsCollection": false
                        },
                        {
                            "Name": "SERVER_AUDIT_QUERY_LOG_LIMIT",
                            "Value": "1024",
                            "DefaultValue": "1024",
                            "Description": "Limit on the length of the query string in a record.",
                            "ApplyType": "DYNAMIC",
                            "DataType": "INTEGER",
                            "AllowedValues": "0-2147483647",
                            "IsModifiable": true,
                            "IsCollection": false
                        },
                        {
                            "Name": "SERVER_AUDIT",
                            "Value": "FORCE_PLUS_PERMANENT",
                            "DefaultValue": "FORCE_PLUS_PERMANENT",
                            "Description": "This setting is enabled for security and ensures that the plugin cannot be uninstalled at runtime",
                            "ApplyType": "STATIC",
                            "DataType": "STRING",
                            "AllowedValues": "FORCE_PLUS_PERMANENT",
                            "IsModifiable": false,
                            "IsCollection": false
                        },
                        {
                            "Name": "SERVER_AUDIT_INCL_USERS",
                            "Description": "Include specified users",
                            "ApplyType": "DYNAMIC",
                            "DataType": "STRING",
                            "IsModifiable": true,
                            "IsCollection": true
                        },
                        {
                            "Name": "SERVER_AUDIT_LOGGING",
                            "Value": "ON",
                            "DefaultValue": "ON",
                            "Description": "Determines if logging is turned on",
                            "ApplyType": "DYNAMIC",
                            "DataType": "STRING",
                            "AllowedValues": "ON",
                            "IsModifiable": false,
                            "IsCollection": false
                        },
                        {
                            "Name": "SERVER_AUDIT_FILE_ROTATE_SIZE",
                            "Value": "1000000",
                            "Description": "Size limit of a log file before rotating",
                            "ApplyType": "DYNAMIC",
                            "DataType": "INTEGER",
                            "AllowedValues": "1-1000000000",
                            "IsModifiable": true,
                            "IsCollection": false
                        },
                        {
                            "Name": "SERVER_AUDIT_EVENTS",
                            "Value": "CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL,QUERY_DML_NO_SELECT",
                            "DefaultValue": "CONNECT,QUERY",
                            "Description": "Types of actions to be logged (connect, query, or table)",
                            "ApplyType": "DYNAMIC",
                            "DataType": "STRING",
                            "AllowedValues": "CONNECT,QUERY,QUERY_DDL,QUERY_DML,QUERY_DCL,QUERY_DML_NO_SELECT",
                            "IsModifiable": true,
                            "IsCollection": true
                        },
                        {
                            "Name": "SERVER_AUDIT_FILE_ROTATIONS",
                            "Value": "10",
                            "Description": "Number of log rotations to save",
                            "ApplyType": "DYNAMIC",
                            "DataType": "INTEGER",
                            "AllowedValues": "0-100",
                            "IsModifiable": true,
                            "IsCollection": false
                        }
                    ],
                    "DBSecurityGroupMemberships": [],
                    "VpcSecurityGroupMemberships": []
                }
            ],
            "AllowsVpcAndNonVpcInstanceMemberships": false,
            "OptionGroupArn": "arn:aws:rds:us-east-1:<AWSアカウントID>:og:rds-db-og"
        }
    ]
}

どちらも正しく設定を参照できました。

しっかりとした命名規約がある環境待望のアップデート

CloudFormationでRDSのパラメーターグループとオプショングループの名前が指定できるようになったアップデートを紹介しました。

しっかりと命名規約がある環境では、パラメーターグループとオプショングループだけコンソールもしくはAWS CLIで作成するといったこともあったのではないでしょうか。これで心置きなくCloudFormationでRDS周りを定義できますね。

こういった痒いところに手が届くようになるアップデートはありがたいです。Transit Gateway Flow LogsやSite-to-Site VPNのトンネルオプションなどCloudFormationでサポートして欲しいリソースはたくさんあるので期待して待ちましょう。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!