【EC2+RDS+CloudFormation】EC2を踏み台にしてRDSに接続する

# はじめに
何度か同じことを調べることがあったので簡単にまとめました。


# ファイル

```yaml:base.yml

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/22
      Tags:
        - Key: "qiita"
          Value: "test"

  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "myapp-qiita-igw"
  InternetGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: "qiita"
          Value: !Sub "myapp-qiita-private-subnetA"
  PrivateSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24

      AvailabilityZone: ap-northeast-1c
      Tags:
        - Key: "qiita"
          Value: !Sub "myapp-qiita-private-subnetC"
  PrivateSubnetD:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24

      AvailabilityZone: ap-northeast-1d
      Tags:
        - Key: "qiita"
          Value: !Sub "myapp-qiita-private-subnetD"

  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: "Name"
          Value: !Sub "myapp-qiita-public-subnet"

  PublicRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: "Name"
          Value: !Sub "myapp-qiita-public-routetableA"
  PublicRouteA:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

  PublicRouteAssociationA:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      SubnetId: !Ref PublicSubnetA

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SecurityGroup
      VpcId: !Ref VPC
      Tags:
        - Key: "qiita"
          Value: !Sub "myapp-qiita-sg"

```

```yaml:ec2.yml
Parameters:
  ProjectName:
    Description: Type of this ProjectName.
    Type: String
  KeyName:
    Description: The EC2 Key Pair to allow SSH access to the instance
    Type: "AWS::EC2::KeyPair::KeyName"
  PubSub:
    Type: "AWS::EC2::Subnet::Id"
  VPC:
    Type: "AWS::EC2::VPC::Id"

Resources:
  EC2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-078296f82eb463377
      KeyName: !Ref KeyName
      InstanceType: t2.micro
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref PubSub
          GroupSet:
            - !Ref EC2SG
      UserData: !Base64 |
        #!/bin/bash
        sudo yum install -y mysql
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-ec2"

  EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${ProjectName}-ec2-sg"
      GroupDescription: Allow SSH access only MyIP
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: hogehoge/32
Outputs:
  EC2PublicIP:
    Value: !GetAtt EC2.PublicIp
    Description: Public IP of EC2 instance
```

```yaml:rds.yml
Parameters:
  VPC:
    Type: "AWS::EC2::VPC::Id"
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
  RdsDbMasterUsername:
    Description: RdsDbMasterUsername
    Type: String
  RdsDbMasterUserPassword:
    Description: RdsDbMasterUserPassword
    Type: String
    NoEcho: true

Resources:
  DBParameterGroup:
    Type: AWS::RDS::DBClusterParameterGroup
    Properties:
      Family: aurora-mysql8.0
      Description: Database Parameter Group
      Parameters:
        character_set_database: utf8mb4
        character_set_client: utf8mb4
        character_set_connection: utf8mb4
        character_set_results: utf8mb4
        character_set_server: utf8mb4
        time_zone: Asia/Tokyo
  RdsDbParameterGroup:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      Description: CloudFormation Aurora Cluster Parameter Group
      Family: aurora-mysql8.0

  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupName: myapp-qiita-db-subnet-group
      DBSubnetGroupDescription: for db
      SubnetIds: !Split [",", !Join [",", !Ref SubnetIds]]

  AuroraSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SecurityGroup for Aurora
      VpcId: !Sub "${VPC}"
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          CidrIp: 10.0.1.0/24
      Tags:
        - Key: "Name"
          Value: myapp-qiita-db-sg
  DBCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      DBClusterIdentifier: Myappqiita-db-cluster
      DBSubnetGroupName: !Ref "DBSubnetGroup"
      DatabaseName: myappqiita
      Engine: aurora-mysql
      EngineVersion: "8.0.mysql_aurora.3.02.0"
      DBClusterParameterGroupName: !Ref DBParameterGroup
      MasterUsername: !Ref 'RdsDbMasterUsername'
      MasterUserPassword: !Ref 'RdsDbMasterUserPassword'
      StorageEncrypted: true
      VpcSecurityGroupIds:
        - !Ref AuroraSecurityGroup
      DBSubnetGroupName: !Ref DBSubnetGroup
    DeletionPolicy: Delete

  RDSDBInstance1: 
    Type: "AWS::RDS::DBInstance"
    Properties: 
      DBClusterIdentifier: !Ref DBCluster
      DBInstanceClass: db.r5.large
      DBParameterGroupName: !Ref RdsDbParameterGroup
      DBSubnetGroupName: !Ref DBSubnetGroup
      Engine: aurora-mysql
      PubliclyAccessible: false

Outputs:
  Endpoint:
    Value: !GetAtt DBCluster.Endpoint.Address
```


# EC2スタックの作成

パラメータを入力します
- PubSub：予めbase.ymlで作成したpublic subnetを選択します
- VPC：予めbase.ymlで作成したVPCを選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/166604a1-efb4-f3a6-ed69-923b008e772b.png)


# RDSスタックの作成

パラメータを入力します
- SubnetIds：予めbase.ymlで作成したprivate subnetを選択します
- VPC：予めbase.ymlで作成したVPCを選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/b559e2e7-a908-1bc5-24de-971dc8bcbdcf.png)

RDSはおよそ10分程度でスタックが作成されると思います。


# EC2への接続
EC2のインスタンスに接続する手順をAWSコンソールから確認することができます

インスタンスが起動している状態で「接続」をクリックすると手順が表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/84facb00-937c-4d8c-4ef1-6e7a2bb10347.png)

```
SSH クライアントを開きます。
プライベートキーファイルを見つけます。このインスタンスの起動に使用されるキーは hogehoge.pem です。
必要に応じて、このコマンドを実行して、キーが公開されていないことを確認します。
chmod 400 hogehoge.pem
ご使用のインスタンスの パブリック IP を使用してインスタンスに接続

例：ssh -i "hogehoge.pem" ec2-user@12.123.123.123
```


例の通りsshコマンドをpemファイルのあるディレクトリで実行します。
接続に成功すると以下の表示がされます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/0b958f2f-0544-698d-edf4-4c2bb70228ad.png)

EC2への接続がタイムアウトする場合はインスタンスにアタッチされているセキュリティグループのインバウンドルールが適切でない可能性があります。
セキュリティグループの「インバウンドルール」から「インバウンドのルールを編集」をクリック」します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/1dce1e42-d891-537d-d8eb-0caa8c8c10d5.png)

「ソース」で指定されているIPでEC2にアクセスしているかを確認します。
「マイIP」を選択することでグローバルIPが指定できます。状況に合わせて確認してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/38c9fa0c-a2da-e270-770b-df6374da2cd3.png)

# EC2とRDSの接続
次にEC2とRDSの接続を行います。
AWSコンソールから、RDSの「接続とセキュリティ」タブの下部にある「接続されたコンピューティングリソース」を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/0e3f20fd-e958-5c49-5e50-edecf72d4dba.png)

「EC2接続のセットアップ」をクリック後、接続したいEC2インスタンスを入力し「確認とセットアップ」をクリックします

この状態でEC2からRDSへ接続するコマンドを実行します

```
[ec2-user@ip-hogehoge ~]$ mysql -h RDSのエンドポイント -P 3306 -u admin -p
```

接続に成功すると以下の表示がされます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/fd3ae9d3-d8e8-bbea-b1fc-017ad00b534f.png)



# おわりに
RDSのスタック作成やEC2への接続の箇所で詰まりました。試行錯誤していると時間が溶けていきますね…。