LoginSignup
11
4

More than 3 years have passed since last update.

【AWS CloudFormation】EC2とRDSの自動構築

Last updated at Posted at 2020-09-19

目標

CloudFormationを利用してEC2とRDSを自動構築するテンプレートを作成する。

前提

・VPC、及びサブネット(パブリック1つ、複数AZにプライベート2つ)が構築済みであること。
・サブネットグループ(RDSを配置する、複数AZにまたがるサブネット集合体)が構築済みであること

CloudFormationとは

AWSインフラの構成要素一式をテンプレートコードによって自動構築するサービスです。
一度テンプレートを作成すれば、同一構成のAWSインフラを簡易的に作成することが可能です。
テンプレート実行により作成されるAWSリソースの集合体をスタックといいます。

作成するスタックの仕様

・パブリックサブネットにEC2インスタンスを1台、プライベートサブネットにRDSインスタンス(MySQL、シングルAZ)を1台作成

EC2、RDS用のセキュリティグループを2つ新規作成し、上記EC2及びRDSインスタンスにアタッチする。

RDSインスタンスへの通信は、テンプレートによって作成されたEC2のセキュリティグループがアタッチされたEC2インスタンスからの通信のみを許可

・以下の値はテンプレート実行毎のユーザ入力による可変値とする。
 -EC2インスタンスタイプ
 -EC2に接続可能な送信元IPアドレス
 -EC2接続キーペア
 -RDSインスタンス識別子
 -RDSサブネットグループ
 -RDSで利用するDBポート
 -RDSで利用する管理者パスワード

参考サイト

・AWSドキュメント
CloudFormationでのパラメータと、EC2及びRDSリソース作成コードのリファレンスです
CloudFormationユーザガイド①(パラメータ)
CloudFormationユーザガイド②(AWS::EC2::Instance)
CloudFormationユーザガイド③(AWS::RDS::DBInstance)

・Qiita記事
初学者のためのAWS入門(2) CloudFormation入門-1

作業の流れ

項番 タイトル
1 テンプレートの作成
2 テンプレート実行
3 簡単な動作確認

手順

1.テンプレートの作成

テンプレートファイルの作成を行います。
本記事ではjsonファイルを利用しています。

<デフォルトのサブネットグループ名><VPC ID><AZ名><サブネットID>の部分は環境に応じて詰め替えを行ってください。

EC2_RDS_Create.json
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "Simple Setup for EC2 and RDS. ",

  "Parameters" : {
    "EC2InstanceType" : {
      "Type" : "String",
      "Default" : "t2.micro",
      "AllowedValues" : ["t2.micro", "m1.small", "m1.large"],
      "Description" : "Enter EC2 InstanceType."
    },

    "EC2SSHLocation" : {
      "Type": "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default": "0.0.0.0/0",
      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x.",
      "Description" : " Enter the IP address range that is allowed to connect to EC2"
    },

    "EC2KeyName": {
      "Type": "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription" : "must be the name of an existing EC2 KeyPair.",
      "Description" : "Enter the name of an existing EC2 KeyPair to enable SSH access to the instance"
    },

    "RDSInstanceIdentifier" : {
      "Type" : "String",
      "Default" : "database-1",
      "Description" : "Enter RDS InstanceIdentifier to identify RDS."
    }, 

    "RDSSubnetGroupName": {
      "Type": "String",
      "Default": "<デフォルトのサブネットグループ名>",
      "Description" : "Enter the subnet group where you want to place the RDS."
    },

    "RDSInstanceType" : {
      "Type" : "String",
      "Default" : "db.t2.small",
      "AllowedValues" : ["db.t2.small", "db.t2.medium", "db.t3.small", "db.t3.medium"],
      "Description" : "Enter RDS InstanceType"
    },

    "RDSDBPort" : {
      "Default" : "3306",
      "Type" : "Number",
      "MinValue" : "1150",
      "MaxValue" : "65535",
      "Description" : "Enter TCP/IP port used to connect DB in RDS."
    },

    "RDSDBPwd" : {
      "NoEcho" : "true",
      "Type" : "String",
      "MinLength" : "1",
      "MaxLength" : "41",
      "AllowedPattern" : "^[a-zA-Z0-9]*$",
      "Description" : "Enter the database admin account password in RDS"
    }
  },

  "Resources" : {
    "EC2SecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "VpcId" : "<VPC ID>",
        "GroupDescription" : "Enable SSH access via port 22",
        "SecurityGroupIngress" : [
          {"IpProtocol" : "tcp", "FromPort" : "22", "ToPort" : "22", "CidrIp" : { "Ref" : "EC2SSHLocation"}}
         ]
      }
    },

    "RDSSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "SecurityGroup rds-grp",
        "VpcId" : "<VPC ID>",
        "SecurityGroupIngress" : [
          { "IpProtocol" : "tcp",
            "FromPort" : { "Ref" : "RDSDBPort" },
            "ToPort" : { "Ref" : "RDSDBPort" },
            "SourceSecurityGroupId" : { "Ref" : "EC2SecurityGroup" } }
        ]
      }
    },

    "RDSInstance": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
          "Engine": "mysql",
          "DBInstanceClass": { "Ref" : "RDSInstanceType" },
          "AllocatedStorage": "20",
          "StorageType": "gp2",
          "DBInstanceIdentifier": { "Ref" : "RDSInstanceIdentifier" },
          "MasterUsername": "admin",
          "MasterUserPassword": {"Ref": "RDSDBPwd"},
          "DBSubnetGroupName": { "Ref": "RDSSubnetGroupName" },
          "PubliclyAccessible": false,
          "AvailabilityZone": "<AZ名>",
          "VPCSecurityGroups": [
              {
                  "Ref": "RDSSecurityGroup"
              }
          ],
          "CopyTagsToSnapshot": true,
          "BackupRetentionPeriod": 7,
          "Tags" : [ { "Key" : "Application", "Value" : "string" } ]
      },
      "DeletionPolicy": "Snapshot"
    },

    "EC2Instance" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "<AMI ID>",
        "SubnetId" : "<サブネットID>",
        "InstanceType" : { "Ref" : "EC2InstanceType" },
        "KeyName" : { "Ref" : "EC2KeyName" },
        "SecurityGroupIds": [{"Ref": "EC2SecurityGroup"}],
        "Tags" : [ { "Key" : "Application", "Value" : "string" } ]
         }
      }
   }
}

テンプレートの書式内容説明です。


{
  # テンプレートのバージョンと説明文
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "Simple Setup for EC2 and RDS.",

  "Parameters" : {
      # テンプレート実行時にユーザ入力を求めるパラメータ定義
      # パラメータ名は自由だが、パラメータの属性名(Type、Default等)は書式に沿う必要がある。
      # これを利用することでDBユーザ名やパスワードをテンプレート実行毎の可変値とすることが可能
  },

  "Resources" : {
      # 必須定義。テンプレートによって実際に構築されるAWSリソース群(スタック)を記載する。
      # リソース名は自由だが、リソースの属性名(Type、Propertiesの中身等)は書式に沿う必要がある。
      #  { "Ref" : <パラメータ名やリソース名> }を利用することで、テンプレート内で事前に定義したパラメータやリソース内容を値として利用することが可能
      # 上から順に構築が実施され、途中テンプレートの実行に失敗した場合、途中まで作成済みのAWSリソースもロールバックされ全て削除される。

      # ※なお、RDSSecurityGroupリソース内プロパティである「"SourceSecurityGroupId" : { "Ref" : "EC2SecurityGroup" }」という定義を利用して、
      #   本テンプレートで作成したEC2セキュリティグループがアタッチされたEC2インスタンスのみRDSへの通信を許可するよう設定している。
  }
}

2.テンプレート実行

CloudFormationコンソールからスタックの作成を開始
tempsnip.png

②作成したテンプレートファイルをアップロード
tempsnip.png

③スタック名と各種パラメータを入力
任意のスタック名とパラメータ(テンプレート内でParametersによって定義された項目)値を入力していきます。
tempsnip.png

④スタックオプションの設定
作成するリソースに共通のタグだけ付与し、その他はデフォルト値とします。入力が終わったら次へ。
tempsnip.png

次画面でスタック作成開始を実行
tempsnip.png

⑤スタック作成状態確認
スタックが作成されるまでしばらく待機し、状態がCREATE_COMPLETEになるまで待ちます。
tempsnip.png

⑥スタック内リソース確認
EC2コンソール及び、RDSコンソールから正常にAWSリソースが作成されていることを確認します。
image.png
image.png

3.簡単な動作確認

作成したスタック内EC2インスタンスにOSログインし、MySQLクライアントをインストールします。

sudo yum install mysql

その後、スタック内RDSインスタンスへのログインを検証しログイン出来ればOKです。

# RDSエンドポイントは作成したスタック内のRDSエンドポイントに詰め替える
mysql -h <RDSエンドポイント> -P 3306 -u admin -p

# 以下、正常出力例
[ec2-user@ip-172-31-34-74 ~]$ mysql -h database-4.cgfjapta11py.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.20 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)]>

※念のため、他インスタンスからのRDSインスタンス接続が拒否されることも確認しました。


# スタック内EC2インスタンス以外からの接続は拒否される
[ec2-user@ip-172-31-40-97 ~]$ mysql -h database-4.cgfjapta11py.ap-northeast-1                                                                                .rds.amazonaws.com -P 3306 -u admin -p
Enter password:

ERROR 2003 (HY000): Can't connect to MySQL server on 'database-4.cgfjapta11py.ap-northeast-1.rds.amazonaws.com' (110)
11
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
4