##目標
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>
の部分は環境に応じて詰め替えを行ってください。
{
"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コンソールからスタックの作成を開始
③スタック名と各種パラメータを入力
任意のスタック名とパラメータ(テンプレート内でParameters
によって定義された項目)値を入力していきます。
④スタックオプションの設定
作成するリソースに共通のタグだけ付与し、その他はデフォルト値とします。入力が終わったら次へ。
⑤スタック作成状態確認
スタックが作成されるまでしばらく待機し、状態がCREATE_COMPLETEになるまで待ちます。
⑥スタック内リソース確認
EC2コンソール及び、RDSコンソールから正常にAWSリソースが作成されていることを確認します。
###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)