はじめに
今回は【AWS環境のコード管理 AWS CloudFormationでWebシステムを構築する】のハンズオン資料を見ながら、CloudFormationでWebシステムを構築していきたいと思います。
学習するサービス
- AWS CloudFormation
- AWS Cloud9
- ELB
- RDS
【AWS環境のコード管理 AWS CloudFormationでWebシステムを構築する】の概要
このハンズオンはCloudFormationを使って、以下のシステムを構築します。
このハンズオンは以下の構成になっております。
Session | 分:秒 | |
---|---|---|
1 | ハンズオンで構築する構成とクラウドにおける構成管理について | 13:12 |
2 | CloudFormation概要 | 08:29 |
3 | 開発環境の構築 | 11:41 |
4 | テンプレートの実行方法、VPCの作成方法 | 11:17 |
5 | EC2の作成 その1 | 12:59 |
6 | EC2の作成 その2 | 08:55 |
7 | RDS、ELBの作成、スタックのライフサイクル・分割 | 07:11 |
8 | まとめ、削除 | 04:19 |
座学動画についてはこの記事では触れませんが、とても分かりやすいと思うので
気になった方はぜひAWS Hands-on for Beginners - AWS環境のコード管理 AWS CloudFormationでWebシステムを構築する をご覧ください。
ハンズオン実践
細かいやり方や設定については省略させていただきます。
詳細については、ハンズオン動画をご覧いただければと思います。
3.開発環境の構築
Cloud9を開発環境として、構築します。
1.すべてデフォルト値でCloud9のインスタンスを作成する。
2.yaml形式で記述するため、yaml形式での一般的なインデントの深さにするためCloud9の設定でSoft Tabsをスペース4つから2つに変更する。
4.テンプレートの実行方法、VPCの作成方法
マネジメントコンソールからVPC用のスタックを作成したり、AWSCLIを使用してスタックの更新を行っていきます。
- マネジメントコンソールからテンプレート「01_vpc.yml」を使ってVPCのスタック「handson-cfn」を作成する。
- Cloud9にテンプレートファイルをアップロードする。
- Cloud9にて、テンプレート「01_vpc.yml」のネームタグの値を変更する。
- AWS CLIを使用してスタック「handson-cfn」を更新する。
CloudFormationのマネジメントコンソールにて、下記のテンプレート「01_vpc.yml」を使用して、VPCのスタック「handson-cfn」を作成しました。※こちらのテンプレートはハンズオンで提供されたyamlファイルです。
テンプレートを表示
AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on template for VPC
Resources:
CFnVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
InstanceTenancy: default
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: handson-cfn
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.0.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [ 0, !GetAZs ]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.1.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [ 1, !GetAZs ]
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet2
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.2.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [ 0, !GetAZs ]
Tags:
- Key: Name
Value: PrivateSubnet1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: 10.0.3.0/24
VpcId: !Ref CFnVPC
AvailabilityZone: !Select [ 1, !GetAZs ]
Tags:
- Key: Name
Value: PrivateSubnet2
CFnVPCIGW:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: handson-cfn
CFnVPCIGWAttach:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref CFnVPCIGW
VpcId: !Ref CFnVPC
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref CFnVPC
Tags:
- Key: Name
Value: Public Route
PublicRoute:
Type: AWS::EC2::Route
DependsOn: CFnVPCIGW
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref CFnVPCIGW
PublicSubnet1Association:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2Association:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
Outputs:
VPCID:
Description: VPC ID
Value: !Ref CFnVPC
Export:
Name: !Sub ${AWS::StackName}-VPCID
PublicSubnet1:
Description: PublicSubnet1
Value: !Ref PublicSubnet1
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet1
PublicSubnet2:
Description: PublicSubnet2
Value: !Ref PublicSubnet2
Export:
Name: !Sub ${AWS::StackName}-PublicSubnet2
PrivateSubnet1:
Description: PrivateSubnet1
Value: !Ref PrivateSubnet1
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet1
PrivateSubnet2:
Description: PrivateSubnet2
Value: !Ref PrivateSubnet2
Export:
Name: !Sub ${AWS::StackName}-PrivateSubnet2
以下のコマンドをCloud9のターミナルで実行して、テンプレートファイルがあるフォルダに移動します。
cd cfn
テンプレート「01_vpc.yml」のResources
PublicSubnet1
Properties
Tags
のValue
をPublecSubnet1
からPublecSubnet1-update
に変更する。
変更したテンプレート「01_vpc.yml」が正しく記述されているか検証するため以下のコマンドを実行します。
aws cloudformation validate-template --template-body file://01_vpc.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば、テンプレートは正しく記述されています。
{
"Description": "Hands-on template for VPC",
"Parameters": []
}
続いて、スタックの更新を行っていきます。
以下のコマンドを実行し、スタックの更新を行います。
aws cloudformation update-stack --stack-name handson-cfn --template-body file://01_vpc.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの更新が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn/67ff5ad0-3863-11ee-a561-0673bbff0e97"
}
マネジメントコンソールでも、スタックの更新がされているか確認していきます。
マネジメントコンソールでCloudFormationを開き、「スタック」から、今回作成したスタック「handson-cfn」をクリックします。
するとスタックの詳細が表示されるので、「リソース」から「PublicSubnet1」の物理IDをクリックします。
無事に「PublicSubnet1」のネームタグの値が「PublecSubnet1-update」に更新されているのが確認できました。
5. EC2の作成 その1
テンプレートの実行方法、VPCの作成方法で作成したVPCにEC2を作成します。
1.AWS CLIを使用してスタック「handson-cfn-ec2」を作成しEC2を起動する。
2.EC2はデフォルトのVPCで起動されているため、作成したVPC「handson-cfn」の「PublicSubnet1-update」で起動するように、テンプレート「02_ec2.yml」を修正する。
3.インスタンス起動時、スクリプトを実行するためにテンプレート「02_ec2.yml」にUserDataプロパティを追加する。
4.AWS CLIにて、スタック「handson-cfn-ec2」の更新を行う。
Cloud9のターミナルで以下のコマンドを実行して、テンプレートファイルがあるフォルダに移動します。
cd cfn
下記のテンプレート「02_ec2.yml」を使用して、VPCのスタック「handson-cfn-ec2」を作成します。※こちらのテンプレートはハンズオンで提供されたyamlファイルです。
テンプレートを表示
AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on template for EC2
Parameters:
VPCStack:
Type: String
Default: handson-cfn
EC2AMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2
Resources:
EC2WebServer01:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2AMI
InstanceType: t2.micro
Outputs:
EC2WebServer01:
Value: !Ref EC2WebServer01
Export:
Name: !Sub ${AWS::StackName}-EC2WebServer01
以下のコマンドを実行して、EC2用のスタック「handson-cfn-ec2」を作成します。
aws cloudformation create-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの作成が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-ec2/f453c160-38e5-11ee-b460-06ad44770f53"
}
CloudFormationのマネジメントコンソールでも、無事にスタックが作成されていることが確認できました。
作成したEC2を作成したVPC「handson-cfn」のサブネット「PublicSubnet1-update」で起動するように、テンプレート「02_ec2.yml」を修正していきます。
CloudFormationのマネジメントコンソールから、スタック「handson-cfn」を選択し、「出力」タブを選択します。「PublicSubnet1」の「値」をコピーします。
テンプレート「02_ec2.yml」にSubnetId
として先ほどコピーした「PublicSubnet1」の「値」を指定します。
Resources:
EC2WebServer01:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2AMI
InstanceType: t2.micro
SubnetId: subnet-06bb6ddf7db2d641d
以下のコマンドを実行し、テンプレートの検証を行います。
aws cloudformation validate-template --template-body file://02_ec2.yml
レスポンスとして下記のように、エラーが返ってこなければテンプレートは正しく記述されています。
{
"Description": "Hands-on template for EC2",
"Parameters": [
{
"DefaultValue": "handson-cfn",
"NoEcho": false,
"ParameterKey": "VPCStack"
},
{
"DefaultValue": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"NoEcho": false,
"ParameterKey": "EC2AMI"
}
]
}
続いて、EC2インスタンス起動時にスクリプトを実行するように、テンプレート「02_ec2.yml」にUserData
プロパティを追加していきます。
また、追加したスクリプトをエンコードするため、組み込み関数Fn::Base64の短縮形である!Base64
を記述しています。
Resources:
EC2WebServer01:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2AMI
InstanceType: t2.micro
SubnetId: subnet-06bb6ddf7db2d641d
UserData: !Base64 |
#! /bin/bash
yum update -y
amazon-linux-extras install php7.2 -y
yum -y install mysql httpd php-mbstring php-xml
wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
tar zxvf /tmp/latest-ja.tar.gz -C /tmp
cp -r /tmp/wordpress/* /var/www/html/
touch /var/www/html/.check_alive
chown apache:apache -R /var/www/html
systemctl enable httpd.service
systemctl start httpd.service
以下のコマンドを実行し、テンプレートの検証を行います。
aws cloudformation validate-template --template-body file://02_ec2.yml
下記のようにエラーが返ってこなければテンプレートは正しく記述されています。
{
"Description": "Hands-on template for EC2",
"Parameters": [
{
"DefaultValue": "handson-cfn",
"NoEcho": false,
"ParameterKey": "VPCStack"
},
{
"DefaultValue": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"NoEcho": false,
"ParameterKey": "EC2AMI"
}
]
}
変更したテンプレートをスタックに反映させるため、AWS CLIにてコマンドを実行し、スタック「handson-cfn-ec2」の更新を行っていきます。
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの更新が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-ec2/f453c160-38e5-11ee-b460-06ad44770f53"
}
CloudFormationのマネジメントコンソールでもスタックが更新されているか確認できました。
無事に指定したVPC「handson-cfn」のサブネット「PublicSubnet1-update」でEC2が起動されていることを確認できました。
ユーザーデータについても確認してみます。
「アクション」→「インスタンスの設定」→「ユーザーデータ」を選択します。
5. EC2の作成 その2
EC2のセキュリティーグループ作成・設定をしていきます。
- セキュリティーグループ「EC2SG」を作成するためにテンプレート「02_ec2.yml」の
Resource
に値を追加します。 - AWS CLIを使ってスタック「handson-cfn-ec2」を更新し、セキュリティーグループを作成する。
- 作成したセキュリティーグループをEC2に関連付けるためにテンプレート「02_ec2.yml」を修正する。
- AWS CLIを使ってスタック「handson-cfn-ec2」を更新し、セキュリティーグループの関連付けを行う。
セキュリティーグループのプロパティとして、「VPCId」を使用するのでCloudFormationのマネジメントコンソールからスタック「handson-cfn」→「VPCID」の「値」をコピーしておきます。
テンプレート「02_ec2.yml」のResource
セクションに以下のようにプロパティを追加します。
ここでVpcId
に先ほどコピーした「VPCID」を指定します。
EC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: sg for web server
VpcId: vpc-03be38ee3e4427d3c
SecurityGroupIngress:
- IpProtocol: tcp
CidrIp: 10.0.0.0/16
FromPort: 80
ToPort: 80
以下のコマンドを実行し、テンプレートの検証を行います。
aws cloudformation validate-template --template-body file://02_ec2.yml
下記のようにエラーが返ってこなければテンプレートは正しく記述されています。
{
"Description": "Hands-on template for EC2",
"Parameters": [
{
"DefaultValue": "handson-cfn",
"NoEcho": false,
"ParameterKey": "VPCStack"
},
{
"DefaultValue": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"NoEcho": false,
"ParameterKey": "EC2AMI"
}
]
}
変更したテンプレートをスタックに反映させるため、スタック「handson-cfn-ec2」の更新を行っていきます。
AWS CLIにて以下のコマンドを実行します。
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの更新が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-ec2/f453c160-38e5-11ee-b460-06ad44770f53"
}
スタックの「リソース」タブからもセキュリティーグループが作成されているのが確認できます。
セキュリティーグループ「EC2SG」をEC2に関連付けます。
テンプレート「02_ec2.yml」のResource
EC2WebServer01
Properties
にSecurityGroupIds
プロパティの値を追加します。
組み込み関数を使い、セキュリティーグループ「EC2SG」のIDを指定します。
SecurityGroupIds:
- !Ref EC2SG
以下のコマンドを実行し、テンプレートの検証を行います。
aws cloudformation validate-template --template-body file://02_ec2.yml
下記のようにエラーが返ってこなければテンプレートは正しく記述されています。
{
"Description": "Hands-on template for EC2",
"Parameters": [
{
"DefaultValue": "handson-cfn",
"NoEcho": false,
"ParameterKey": "VPCStack"
},
{
"DefaultValue": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2",
"NoEcho": false,
"ParameterKey": "EC2AMI"
}
]
}
変更したテンプレートをスタックに反映させるため、スタック「handson-cfn-ec2」の更新を行っていきます。
AWS CLIにて以下のコマンドを実行します。
aws cloudformation update-stack --stack-name handson-cfn-ec2 --template-body file://02_ec2.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの更新が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-ec2/f453c160-38e5-11ee-b460-06ad44770f53"
}
EC2のマネジメントコンソールからも無事に関連付けできていることが確認できました。
7.RDS、ELBの作成、スタックのライフサイクル・分割
AWS CLIを使用して、RDSとELBのスタックを作成していきます。
- AWS CLIを使ってRDSのスタック「handson-cfn-rds」を作成する。
- AWS CLIを使ってELBのスタック「handson-cfn-elb」を作成する。
- ELBからEC2に接続し、EC2にWordPressをインストールし、WordPressにログインする。
下記のテンプレート「03_rds.yml」を使用します。
AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on template for RDS
Parameters:
VPCStack:
Type: String
Default: handson-cfn
DBUser:
Type: String
Default: dbmaster
DBPassword:
Type: String
Default: H&ppyHands0n
NoEcho: true
Resources:
DBInstance:
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
Properties:
DBInstanceClass: db.t2.micro
AllocatedStorage: "10"
StorageType: gp2
Engine: MySQL
MasterUsername: !Ref DBUser
MasterUserPassword: !Ref DBPassword
DBName: wordpress
BackupRetentionPeriod: 0
DBSubnetGroupName: !Ref DBSubnetGroup
VPCSecurityGroups:
- !Ref DBSecurityGroup
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: DB Subnet Group for Private Subnet
SubnetIds:
- Fn::ImportValue: !Sub ${VPCStack}-PrivateSubnet1
- Fn::ImportValue: !Sub ${VPCStack}-PrivateSubnet2
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub ${AWS::StackName}-MySQL
VpcId:
Fn::ImportValue: !Sub ${VPCStack}-VPCID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
CidrIp: 10.0.0.0/16
Outputs:
DBEndpoint:
Value: !GetAtt DBInstance.Endpoint.Address
Export:
Name: !Sub ${AWS::StackName}-DBEndpoint
下記のテンプレート「04_elb.yml」を使用します。
AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on template for ALB
Parameters:
VPCStack:
Type: String
Default: handson-cfn
EC2Stack:
Type: String
Default: handson-cfn-ec2
Resources:
FrontLB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Ref AWS::StackName
Subnets:
- Fn::ImportValue: !Sub ${VPCStack}-PublicSubnet1
- Fn::ImportValue: !Sub ${VPCStack}-PublicSubnet2
SecurityGroups:
- !Ref SecurityGroupLB
FrontLBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref FrontLB
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref FrontLBTargetGroup
FrontLBTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub ${AWS::StackName}-tg
VpcId:
Fn::ImportValue: !Sub ${VPCStack}-VPCID
Port: 80
Protocol: HTTP
HealthCheckPath: /.check_alive
Targets:
- Id:
Fn::ImportValue: !Sub ${EC2Stack}-EC2WebServer01
SecurityGroupLB:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Ref AWS::StackName
VpcId:
Fn::ImportValue: !Sub ${VPCStack}-VPCID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Outputs:
FrontLBEndpoint:
Value: !GetAtt FrontLB.DNSName
Export:
Name: !Sub ${AWS::StackName}-Endpoint
Cloud9のターミナルで以下のコマンドを実行して、テンプレートファイルがあるフォルダに移動します。
cd cfn
以下のコマンドを実行し、テンプレート「03_rds.yml」からRDSのスタック「handson-cfn-rds」を作成します。
aws cloudformation create-stack --stack-name handson-cfn-rds --template-body file://03_rds.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの作成が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-rds/d10689f0-398e-11ee-a250-0e98c60575d9"
}
以下のコマンドを実行し、テンプレート「03_rds.yml」からRDSのスタック「handson-cfn-elb」を作成します。
aws cloudformation create-stack --stack-name handson-cfn-elb --template-body file://04_elb.yml
以下のようにエラーが発生することなくレスポンスが返ってこれば無事にスタックの作成が開始されています。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:571504036579:stack/handson-cfn-elb/e550a170-398e-11ee-a9fc-0a5a4ab5f0af"
}
CloudFormationのコンソールでも無事にリソースが作成されているのが確認できました。
handson-cfn-rds-dbinstance-nhqsw4zvmtpa.cbfpkicusoxk.ap-northeast-1.rds.amazonaws.com
handson-cfn-rds-dbinstance-dx0lmesvfalc.cbfpkicusoxk.ap-northeast-1.rds.amazonaws.com
dbmaster
H&ppyHands0n
続いて、EC2にWordPressをインストールしていきます。
後ほど必要となる「DBEndPoint」と「DBUser」、「DBPassword」を取得していきます。
CloudFormationのコンソールからスタック「handson-cfn-rds」を選択し、「出力」タブのキー「DBEndpoint」のURLをコピーします。
テンプレート「03_rds.yml」のDBUser
の「dbmaster」とDBPassword
の「H&ppyHands0n」をコピーします。
CloudFormationのコンソールに戻り、スタック「handson-cfn-elb」を選択し、「出力」タブからelbのURLを開きます。
データベース名に「wordpress」と入力します。
先ほどコピーしている値を使用して、ユーザー名にDBUser
の「dbmaster」、パスワードにDBPassword
の「H&ppyHands0n」、データベースのホスト名にDBEndpoint
のURLをそれぞれ入力し、「送信」をクリックします。
サイトのタイトルを「Hello World」、ユーザー名を「admin」、メールアドレスを「admin@example.org」と入力します。
ここでパスワードをコピーしておきます。
「WordPressをインストール」をクリックし、インストールを開始します。
インストールが完了したので、WordPressにログインしていきます。
先ほど設定したユーザー名「admin」とコピーしているパスワードを入力し、「ログイン」をクリックします。
8.まとめ、削除
今まで作成したリソースを削除します。
今回は、CloudFormationでリソースを構築したので、スタックを削除することで簡単にリソースを削除することができます。
CloudFormationのコンソールにて、作成した順番と、逆の順序でスタックを削除していきます。
順番 | スタック名 |
---|---|
1 | handson-cfn-elb |
2 | handson-cfn-rds |
3 | handson-cfn-ec2 |
4 | handson-cfn |
5 | aws-cloud9-hanson-* |
終わりに
一つ一つリソースを削除するのに少し手間がかかっていたのが、今回はスタックを削除して簡単にリソースを削除でき、とても感動しました。。
また、ハンズオンは非常にわかりやすいので、CloudFormationを触ったことがない!という方にもおすすめです!