CloudformationでRDSの作成

# はじめに

この記事の続きです。Cloudformationを学習中です。
[CloudformationでEC2、ALBを作成する](https://qiita.com/gogo-muscle/items/f82f677e9ca89610bd96)

- SSMのパラメータストアからRDSのパスワードを指定しています。
- RDSセキュリティグループはEC2作成時にエクスポートしたセキュリティグループをソースにしています。

# コード
~~~yaml:Create-rds.yml
AWSTemplateFormatVersion: "2010-09-09"
Description:
  RDS for  MySQL Create
  # ------------------------------------------------------------#
  # Input Parameters
  # ------------------------------------------------------------#
Parameters:
  DBInstanceName:
    Type: String
    Default: "rds"
  MySQLMajorVersion:
    Type: String
    Default: "5.7"
    AllowedValues: ["5.5", "5.6", "5.7"]
  MySQLMinorVersion:
    Type: String
    Default: "22"
  DBInstanceClass:
    Type: String
    Default: "db.t2.micro"
  DBInstanceStorageSize:
    Type: String
    Default: "30"
  DBInstanceStorageType:
    Type: String
    Default: "gp2"
  DBName:
    Type: String
    Default: "db"
  DBMasterUserName:
    Type: String
    Default: "admin"
  MultiAZ:
    Default: "false"
    Type: String
    AllowedValues: ["true", "false"]

# ------------------------------------------------------------#
#  DBInstance MySQL
# ------------------------------------------------------------#
Resources:
  DBInstance:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceIdentifier: !Ref DBInstanceName
      Engine: MySQL
      EngineVersion: !Sub "${MySQLMajorVersion}.${MySQLMinorVersion}"
      DBInstanceClass: !Ref DBInstanceClass
      AllocatedStorage: !Ref DBInstanceStorageSize
      StorageType: !Ref DBInstanceStorageType
      DBName: !Ref DBName
      MasterUsername: !Ref DBMasterUserName
      MasterUserPassword: "{{resolve:ssm-secure:rds-master-user-password:1}}"
      DBSubnetGroupName: !Ref DBSubnetGroup
      PubliclyAccessible: false
      MultiAZ: !Ref MultiAZ
      AutoMinorVersionUpgrade: false
      DBParameterGroupName: !Ref DBParameterGroup
      VPCSecurityGroups:
        - !Ref RDSSecurityGroup
      CopyTagsToSnapshot: true
      BackupRetentionPeriod: 7
      Tags:
        - Key: "Name"
          Value: !Ref DBInstanceName
    DeletionPolicy: "Delete"

  # ------------------------------------------------------------#
  #  DBParameterGroup
  # ------------------------------------------------------------#
  DBParameterGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: !Sub "MySQL${MySQLMajorVersion}"
      Description: !Ref DBInstanceName

  # ------------------------------------------------------------#
  #  SecurityGroup for RDS (MySQL)
  # ------------------------------------------------------------#
  RDSSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: !ImportValue TESTSTACK-VPCID
      GroupName: !Sub "${DBInstanceName}-sg"
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${DBInstanceName}-sg"
      # Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !ImportValue web-sg

  # ------------------------------------------------------------#
  #  DBSubnetGroup
  # ------------------------------------------------------------#
  DBSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupName: !Sub "${DBInstanceName}-subnet"
      DBSubnetGroupDescription: "-"
      SubnetIds:
        - !ImportValue TESTSTACK-PrivateSubnet0
        - !ImportValue TESTSTACK-PrivateSubnet1

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
  #DBInstance
  DBInstanceID:
    Value: !Ref DBInstance
    Export:
      Name: !Sub "${DBInstanceName}-id"

  DBInstanceEndpoint:
    Value: !GetAtt DBInstance.Endpoint.Address
    Export:
      Name: !Sub "${DBInstanceName}-endpoint"

  DBName:
    Value: !Ref DBName
    Export:
      Name: !Sub "${DBInstanceName}-dbname"
~~~

# スタックの登録

## SSMにRDSパスワードの登録

個人管理なので、テンプレート直接書いても良かったのですが
折角なのでSSMのパラメータストアで管理してみます。

* ８文字以上である必要がある。（スタック登録時にエラーが出る）
* どこにでも埋め込めれるわけではなく、`AWS :: RDS :: DBInstance`リソースには、`MasterUserPassword`プロパティでしか使えない。

~~~shell
% aws ssm put-parameter --name rds-master-user-password --value 'test1234' --type SecureString
{
    "Version": 1,
    "Tier": "Standard"
}
~~~

## スタックの登録

~~~shell
% aws cloudformation create-stack \ 
--tags Key="name",Value="test" \
--stack-name TESTRDS \
--template-body file://Create-rds.yml
~~~

エクスポートしたエンドポイントの確認

~~~shell
aws cloudformation describe-stacks --stack-name TESTRDS \
| jq -r '.Stacks[].Outputs[]|select(.OutputKey == "DBInstanceEndpoint").OutputValue'

> rds.cxxlsm6y0wym.ap-northeast-1.rds.amazonaws.com
~~~

## EC2からMysqlにログイン出来るか確認

~~~shell
% ssh -i ~/.ssh/test-ssh-key.pem ec2-user@xxx.xxx.xx.xxx

[ec2-user@ip-10-1-0-213 ~]$ sudo yum install -y mysql-devel mysql
[ec2-user@ip-10-1-0-213 ~]$ mysql -u admin -h rds.cxxlsm6y0wym.ap-northeast-1.rds.amazonaws.com -p
Enter password:

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.22-log Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>
~~~

## 削除方法

~~~shell
% aws cloudformation delete-stack --stack-name TESTRDS
~~~


# 参考文献
* [CloudFormationを使ってMySQLのRDSを構築する](https://qiita.com/okubot55/items/87d4bd7a3649992bc5f7)
* [動的参照を使用してテンプレート値を指定する](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html)
* [CloudFormationテンプレートに秘密情報を渡す方法](https://techblog.zozo.com/entry/pass_secrets_to_cloudformation)