# CloudFormation による動的サイトの構築自動化
> AWS CloudFormation は Amazon Web Services リソースのモデル化およびセットアップに役立つサービスです。リソース管理に割く時間を減らし、AWS で実行するアプリケーションにさらに注力できるようになります。使用するすべての AWS リソース (Amazon EC2 インスタンスや Amazon RDS DB インスタンスなど) を記述するテンプレートを作成すれば、AWS CloudFormation がお客様に代わってこれらのリソースのプロビジョニングや設定を受け持ちます。AWS リソースを個別に作成、設計して、それぞれの依存関係を考える必要はありません。
>
> [AWS ドキュメント CloudFormation ユーザーズガイド](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/Welcome.html) より
## 目的
CloudFormation を使用し、従来、個別に作成していたネットワークやインスタンス等のリソースを、自動で作成する仕組みを学びます。
## 前提事項
* [構成図スライド](https://hackmd.io/@XPx55BOdQVm_Flkoze74_A/ry2fAgQmr#/) の構成を元に環境を構築します
* [AWS 無料枠](https://aws.amazon.com/jp/free/)の範囲で構築します
* ブラウザは Google Chrome を使用します
* CloudFormation デザイナーの機能は使用しません
## 注意事項
* AWS 無料枠でリソースを作成しますが、リソースの起動時間によって、無料枠を越えて使用した場合は課金が発生するため、使用しない期間は小まめにリソースを削除するようにしてください
* RDS インスタンス作成時の自動データーベースバックアップにより、軽微ではありますが、バックアップ使用量に対する課金が発生しますので、RDS インスタンスについては、リソースの削除忘れがないか確認するようにしてください
## 1. AWS コンソールへのログイン
:::info
URL: 別途配布
アカウント名: 別途配布
パスワード: 別途配布
:::
## 2. リージョンの選択
#### 画面右上のメニューよりサイトを構築するリージョンを選択する。
```=
admin01 ~ admin04:アジアパシフィック(東京)
admin05 ~ admin08:アジアパシフィック(ソウル)
admin09 ~ admin12:アジアパシフィック(シンガポール)
Lect01 〜 Lect04 :アジアパシフィック(シドニー)
```
:::warning
VPC は 1 リージョンに 5 つまでの登録が上限です。
VPC は デフォルトで 1 つの VPC が存在するため、新規に作成できるのは 4 つまでです。
:::
|[](https://i.imgur.com/68X8KkK.png)|
|:-:|
## 3. EC2 キーペアの作成
### 3.1. サービスメニューより、EC2 をクリックする。
|[](https://i.imgur.com/VYnOJmd.png)|
|:-:|
### 3.2. 左メニューより、キーペアをクリックする。
|[](https://i.imgur.com/8kyxcD0.png)|
|:-:|
### 3.3. キーペアを作成 ボタンをクリックする。
|[](https://i.imgur.com/3CLThpa.png)
|:-:|
### 3.4. 以下のとおり入力し、キーペアを作成 ボタンをクリックする。
```=
名前: stack-(アカウント名)
ファイル形式: pem
```
:::warning
(アカウント名)は、ログインユーザー名 admin01 などに置き換えて入力します。
:::
|[](https://i.imgur.com/hneVK0l.png)|
|:-:|
### 3.5 stack-(アカウント名).pem ファイルがダウンロードされるため、任意の場所に保存する。
:::warning
キーペアファイルのダウンロードは作成時のみであるため、紛失しないように注意してください。作成済みのキーペアファイルを再度ダウンロードすることはできません。紛失した場合、キーペアと紐つくインスタンスには ssh でログインできなくなります。
:::
### 3.6. キーペアが作成されたことを確認する。
|[](https://i.imgur.com/HdsN45v.png)
|:-:|
## 4. CloudFormation による構築
CloudFormation で各種リソースを作成するには、テンプレートというファイルを記述し、CloudFormation のスタックとして実行します。
1 度作成したテンプレートは何度でも再利用可能です。
テンプレートは可読性のあるテキストとして記述するため、ソースコードとして管理できます。
このようにインフラリソースをソースコードで管理し、プロビジョニングを自動化することを IaC (Infrastructure as Code) と呼びます。
### 4.1. テンプレートの記述方法
ここでは、CloudFormation のスタックとして利用するために記述するテンプレートの記述方法について説明します。
### 4.1.1. JSON 形式または YAML 形式
テンプレートは JSON または YAML という形式で記述します。
JSON 形式
```json=
{
"AWSTemplateFormatVersion" : "version date",
"Description" : "JSON string",
"Metadata" : {
template metadata
},
"Parameters" : {
set of parameters
},
"Mappings" : {
set of mappings
},
"Conditions" : {
set of conditions
},
"Transform" : {
set of transforms
},
"Resources" : {
set of resources
},
"Outputs" : {
set of outputs
}
}
```
YAML 形式
```yaml=
AWSTemplateFormatVersion: "version date"
Description:
String
Metadata:
template metadata
Parameters:
set of parameters
Mappings:
set of mappings
Conditions:
set of conditions
Transform:
set of transforms
Resources:
set of resources
Outputs:
set of outputs
```
今回は YAML 形式を採用して進めます。
### 4.1.2. バージョン宣言
CloudFormation テンプレートでは、任意ではあります、以下のようにファイルの冒頭に利用するバージョンを宣言するのが一般的です。
```json=
AWSTemplateFormatVersion: 2010-09-09
```
:::info
最新のテンプレートの形式バージョンは 2010-09-09 であり、現時点で唯一の有効な値です。
:::
### 4.1.3. リソースの定義
リソースは以下の例のように、リソース単位で記述します。
```yaml=
Resources: # <- 必ず最初に Resources: を記述する
# VPC のリソース
VpcWordpress: # <- リソースのID(一意)を記述する
Type: AWS::EC2::VPC # <- リソースのタイプを記述する
Properties: # <- リソースのプロパティを記述する
CidrBlock: 10.0.0.0/16 # <- プロパティの詳細(CIDR)
EnableDnsSupport: true # <- プロパティの詳細(DNSでのアクセスサポート)
EnableDnsHostnames: true # <- プロパティの詳細(ホスト名でのアクセスサポート)
Tags: # <- タグ(メタ情報)を記述する
- Key: Name # <- タグのキー名
Value: vpc-lect01 # <- キーに対応する値
# EC2 インスタンスのリソース
WebServer01:
Type: AWS::EC2::Instance
Properties:
AvailabilityZone: ap-northeast-1a
KeyName: stack-lect01
ImageId: ami-011facbea5ec0363b
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
SubnetId: !ImportValue public-subnet01-id
GroupSet:
- !ImportValue web-sec-group-id
Monitoring: false
Tags:
- Key: Name
Value: wp-web01
```
### 4.1.4 クロススタック参照
クロススタック参照は、あるテンプレートで定義したリソース ID 等の値を出力して、別のテンプレートでその値を利用する機能のことです。
例えば、VPC を定義したテンプレートから、VPC の ID を出力し、その ID を セキュリティグループを定義するテンプレートで利用して、セキュリティグループが属する VPC を自動で決定するといった使い方ができます。
### 4.1.4.1. アウトプット(エクスポート)
アウトプットを行う際の記載は以下のとおりです。
```yaml=
Resources:
VpcWordpress:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: vpc-lect01
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VpcWordpress # <- 出力する値の指定(ここでは VPC の ID)
Export:
Name: vpc-id # <- 出力する変数名
```
### 4.1.4.2. インプット(インポート)
インプットを行う際の記載は以下のとおりです。
```yaml=
Resources:
ElbSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: ElbWeb
GroupDescription: ELB Server Security Group
VpcId: !ImportValue vpc-id # <- 出力された値のインポート
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: wp01-elb-sg
```
> リファレンス
> [AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)
## 5. ColudFormation テンプレートの作成
ここでは、ColudFormation で使用するテンプレートファイルを作成します。
テンプレートファイルは Windows であれば、メモ帳等のテキストエディタ(テキスト編集可能であれば何でも構いません)を使用して作成します。
テンプレートファイルの保存先として、任意の場所に aws-work というフォルダを作成してください。
:::warning
* テンプレート内で (リージョンコード) と記述されている箇所については、割り当てられたリージョンのリージョンコードを指定します。
```
東京: ap-northeast-1
ソウル: ap-northeast-2
シンガポール: ap-southeast-1
シドニー: ap-southeast-2
```
```
例) 東京リージョンの場合
(リージョンコード)a -> ap-northeast-1a
```
* テンプレート内で (アカウント名) と記述されている箇所については、割り当てられたアカウント名を指定します。
```
例) 割り当てられたアカウント名が admin01 の場合
vpc-(アカウント名) -> vpc-admin01
```
* テンプレート内で (リージョン固有の AMI ID) と記述されている箇所については、後で確認する AMI ID を指定します。
```
例) AMI ID が ami-011facbea5ec0363b の場合
(リージョン固有の AMI ID) -> ami-011facbea5ec0363b
```
:::
### 5.1. ネットワークテンプレートの作成
ネットワークテンプレートでは、「VPC」、「Internet Gateway」、「Route Table」、「Availability Zone」、「Public Subnet」、「Private Subnet」といった、AWS を構成する基礎となる、ネットワーク関連の設定を行います。
|[](https://i.imgur.com/y88FcNI.png)
|:-:|
aws-work フォルダ内に、以下のファイル名でテンプレートを作成します。
```=
ファイル名: network.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
VpcWordpress:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: vpc-(アカウント名) # <- (アカウント名) を置換する
PublicSubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: (リージョンコード)a # <- (リージョンコード) を置換する
VpcId: !Ref VpcWordpress
CidrBlock: 10.0.1.0/24
Tags:
- Key: Name
Value: wp01-public-subnet01-(アカウント名) # <- (アカウント名) を置換する
PublicSubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: (リージョンコード)c # <- (リージョンコード) を置換する
VpcId: !Ref VpcWordpress
CidrBlock: 10.0.2.0/24
Tags:
- Key: Name
Value: wp01-public-subnet02-(アカウント名) # <- (アカウント名) を置換する
PrivateSubnet01:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: (リージョンコード)a # <- (リージョンコード) を置換する
VpcId: !Ref VpcWordpress
CidrBlock: 10.0.3.0/24
Tags:
- Key: Name
Value: wp01-private-subnet01-(アカウント名) # <- (アカウント名) を置換する
PrivateSubnet02:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: (リージョンコード)c # <- (リージョンコード) を置換する
VpcId: !Ref VpcWordpress
CidrBlock: 10.0.4.0/24
Tags:
- Key: Name
Value: wp01-private-subnet02-(アカウント名) # <- (アカウント名) を置換する
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: wp01-internet-gateway-(アカウント名) # <- (アカウント名) を置換する
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VpcWordpress
InternetGatewayId: !Ref InternetGateway
InternetGatewayRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VpcWordpress
Tags:
- Key: Name
Value: wp01-internet-gateway-route-table-(アカウント名) # <- (アカウント名) を置換する
InternetGatewayRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref InternetGatewayRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableAssoc01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet01
RouteTableId: !Ref InternetGatewayRouteTable
RouteTableAssoc02:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet02
RouteTableId: !Ref InternetGatewayRouteTable
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VpcWordpress
Export:
Name: vpc-id-(アカウント名) # <- (アカウント名) を置換する
PublicSubnetId01:
Description: Public Subnet 01 ID
Value: !Ref PublicSubnet01
Export:
Name: public-subnet01-id-(アカウント名) # <- (アカウント名) を置換する
PublicSubnetId02:
Description: Public Subnet 02 ID
Value: !Ref PublicSubnet02
Export:
Name: public-subnet02-id-(アカウント名) # <- (アカウント名) を置換する
PrivateSubnetId01:
Description: Private Subnet 01 ID
Value: !Ref PrivateSubnet01
Export:
Name: private-subnet01-id-(アカウント名) # <- (アカウント名) を置換する
PrivateSubnetId02:
Description: Private Subnet 02 ID
Value: !Ref PrivateSubnet01
Export:
Name: private-subnet02-id-(アカウント名) # <- (アカウント名) を置換する
```
### 5.2. セキュリティグループテンプレートの作成
セキュリティグループテンプレートでは、「Internat Gateway」から Web サーバへの通信許可と、Web サーバから DB サーバへの通信許可を設定するための、セキュリティグループを作成します。
|[](https://i.imgur.com/YyjCPXE.png)
|:-:|
aws-work フォルダ内に、以下のファイル名でテンプレートを作成します。
```=
ファイル名: security.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
ElbSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: ElbWeb
GroupDescription: ELB Server Security Group
VpcId: !ImportValue vpc-id-(アカウント名) # <- (アカウント名) を置換する
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: wp01-elb-sg-(アカウント名) # <- (アカウント名) を置換する
WebSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: Ec2Web
GroupDescription: Web Server Security Group
VpcId: !ImportValue vpc-id-(アカウント名) # <- (アカウント名) を置換する
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: wp01-web-sg-(アカウント名) # <- (アカウント名) を置換する
MysqlSecGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: Rdsdb
GroupDescription: MySQL Server Security Group
VpcId: !ImportValue vpc-id-(アカウント名) # <- (アカウント名) を置換する
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref WebSecGroup
Tags:
- Key: Name
Value: wp01-db-sg-(アカウント名) # <- (アカウント名) を置換する
Outputs:
ElbSecGroup:
Description: Elb Security Group ID
Value: !Ref ElbSecGroup
Export:
Name: elb-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
WebSecGroup:
Description: Web Security Group ID
Value: !Ref WebSecGroup
Export:
Name: web-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
MysqlSecGroup:
Description: MySQL Security Group ID
Value: !Ref MysqlSecGroup
Export:
Name: mysql-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
```
### 5.3. インスタンステンプレートの作成
インスタンステンプレートでは、パブリックサブネットに Web サーバを構築を作成します。また、「PHP」、「Nginx」、「MySQL」、「Wordpress」といった、ブログサービスを提供するためのソフトウェアをインストール/セットアップするための内容も記述します。
|[](https://i.imgur.com/HjRyXV9.png)
|:-:|
EC2 インスタンスを起動するための AMI (Amazon Machine Image) を指定しますが、AMI の ID は、セキュリティ確保のために、定期的にパッチ適用などで更新されます。これにより、AMI ID は固定されないため、事前に以下の手順で、現在の AMI ID を確認してからテンプレートの作成を行います。
サービスメニューより、EC2 をクリックする。
|[](https://i.imgur.com/VYnOJmd.png)|
|:-:|
インスタンスの起動ボタンより、インスタンスの起動を選択する。
|[](https://i.imgur.com/vuNakuD.png)|
|:-:|
Amazon Linux 2 AMI (HVM), SSD Volume Type の AMI ID を確認する。
|[](https://i.imgur.com/ysCjnsu.png)|
|:-:|
:::info
Linux AMI の検索
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/finding-an-ami.html
:::
aws-work フォルダ内に、以下のファイル名でテンプレートを作成します。
```=
ファイル名: instance.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
WebServer01:
Type: AWS::EC2::Instance
Metadata:
# Comment: Configure the bootstrap helpers to install the Nginx and PHP, MySQL.
AWS::CloudFormation::Init:
config:
files:
/etc/nginx/conf.d/wordpress.conf:
content: !Sub |
server {
listen 80 default_server;
server_name wordpress;
root /usr/share/nginx/wordpress;
location / {
try_files $uri $uri/ /index.php?$args;
}
location = /wp-config.php {
deny all;
}
include /etc/nginx/default.d/*.conf;
}
mode: "000644"
owner: nginx
group: nginx
services:
sysvinit:
php-fpm:
enabled: true
ensureRunning: true
nginx:
enabled: true
ensureRunning: true
Properties:
AvailabilityZone: (リージョンコード)a # <- (リージョンコード) を置換する
KeyName: stack-(アカウント名) # <- (アカウント名) を置換する
ImageId: (リージョン固有の AMI ID) # <- (リージョン固有の AMI ID) を置換する
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
SubnetId: !ImportValue public-subnet01-id-(アカウント名) # <- (アカウント名) を置換する
GroupSet:
- !ImportValue web-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
Monitoring: false
Tags:
- Key: Name
Value: wp-web01-(アカウント名) # <- (アカウント名) を置換する
UserData:
Fn::Base64: !Sub |
#!/bin/bash -vxe
whoami
# extra package install
amazon-linux-extras install -y php7.2
amazon-linux-extras install -y nginx1.12
# yum -y update
yum install -y aws-cfn-bootstrap
yum install -y mysql
# Download Wordpress
cd /usr/share/nginx/
curl -O https://ja.wordpress.org/latest-ja.tar.gz
tar zxf latest-ja.tar.gz
chown -R nginx:nginx wordpress/
# Setup Nginx
cd /etc/nginx
cp -p nginx.conf nginx.conf.org
sed -i 's/ default_server//' nginx.conf
# diff nginx.conf nginx.conf.org
# Setup PHP
cd /etc/php-fpm.d
cp -p www.conf www.conf.org
sed -i 's/user = apache/user = nginx/' www.conf
sed -i 's/group = apache/group = nginx/' www.conf
sed -i 's/;listen.owner = nobody/listen.owner = nginx/' www.conf
sed -i 's/;listen.group = nobody/listen.group = nginx/' www.conf
# diff www.conf www.conf.org
# Install the files and packages from the metadata
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer01 --region ${AWS::Region}
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServer01 --region ${AWS::Region}
CreationPolicy:
ResourceSignal:
Timeout: PT10M
# DeletionPolicy: Retain
WebServer02:
Type: AWS::EC2::Instance
Metadata:
# Comment: Configure the bootstrap helpers to install the Nginx and PHP, MySQL.
AWS::CloudFormation::Init:
config:
files:
/etc/nginx/conf.d/wordpress.conf:
content: !Sub |
server {
listen 80 default_server;
server_name wordpress;
root /usr/share/nginx/wordpress;
location / {
try_files $uri $uri/ /index.php?$args;
}
location = /wp-config.php {
deny all;
}
include /etc/nginx/default.d/*.conf;
}
mode: "000644"
owner: nginx
group: nginx
services:
sysvinit:
php-fpm:
enabled: true
ensureRunning: true
nginx:
enabled: true
ensureRunning: true
Properties:
AvailabilityZone: (リージョンコード)c # <- (リージョンコード) を置換する
KeyName: stack-(アカウント名) # <- (アカウント名) を置換する
ImageId: (リージョン固有の AMI ID) # <- (リージョン固有の AMI ID) を置換する
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
SubnetId: !ImportValue public-subnet02-id-(アカウント名) # <- (アカウント名) を置換する
GroupSet:
- !ImportValue web-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
Monitoring: false
Tags:
- Key: Name
Value: wp-web02-(アカウント名) # <- (アカウント名) を置換する
UserData:
Fn::Base64: !Sub |
#!/bin/bash -vxe
whoami
# extra package install
amazon-linux-extras install -y php7.2
amazon-linux-extras install -y nginx1.12
# yum -y update
yum install -y aws-cfn-bootstrap
yum install -y mysql
# Download Wordpress
cd /usr/share/nginx/
curl -O https://ja.wordpress.org/latest-ja.tar.gz
tar zxf latest-ja.tar.gz
chown -R nginx:nginx wordpress/
# Setup Nginx
cd /etc/nginx
cp -p nginx.conf nginx.conf.org
sed -i 's/ default_server//' nginx.conf
# diff nginx.conf nginx.conf.org
# Setup PHP
cd /etc/php-fpm.d
cp -p www.conf www.conf.org
sed -i 's/user = apache/user = nginx/' www.conf
sed -i 's/group = apache/group = nginx/' www.conf
sed -i 's/;listen.owner = nobody/listen.owner = nginx/' www.conf
sed -i 's/;listen.group = nobody/listen.group = nginx/' www.conf
# diff www.conf www.conf.org
# Install the files and packages from the metadata
/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServer02 --region ${AWS::Region}
# Signal the status from cfn-init
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServer02 --region ${AWS::Region}
CreationPolicy:
ResourceSignal:
Timeout: PT10M
# DeletionPolicy: Retain
Outputs:
WebServer01Id:
Description: Web Server 01 Instance ID
Value: !Ref WebServer01
Export:
Name: web01-instance-id-(アカウント名) # <- (アカウント名) を置換する
WebServer02Id:
Description: Web Server 02 Instance ID
Value: !Ref WebServer02
Export:
Name: web02-instance-id-(アカウント名) # <- (アカウント名) を置換する
WebServer01DnsName:
Value: !GetAtt WebServer01.PublicDnsName
Export:
Name: web01-dns-name-(アカウント名) # <- (アカウント名) を置換する
WebServer02DnsName:
Value: !GetAtt WebServer02.PublicDnsName
Export:
Name: web02-dns-name-(アカウント名) # <- (アカウント名) を置換する
```
### 5.4. データベーステンプレートの作成
データベーステンプレートでは、データベースが所属する専用のDBサブネットと、AWS のマネージドサービスである RDS を作成します。データベースのエンジンは MySQL を選択しています。
|[](https://i.imgur.com/C4EvIIc.png)
|:-:|
aws-work フォルダ内に、以下のファイル名でテンプレートを作成します。
```=
ファイル名: database.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
DbSubnetGroup01:
Type: AWS::RDS::DBSubnetGroup
Properties:
SubnetIds:
- !ImportValue public-subnet01-id-(アカウント名) # <- (アカウント名) を置換する
- !ImportValue public-subnet02-id-(アカウント名) # <- (アカウント名) を置換する
DBSubnetGroupDescription: DB Subnet
DbServer01:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: wp-instance-(アカウント名) # <- (アカウント名) を置換する
DBSubnetGroupName: !Ref DbSubnetGroup01
Tags:
- Key: Name
Value: wp-db01-(アカウント名) # <- (アカウント名) を置換する
AllocatedStorage: 20
DBInstanceClass: db.t2.micro
Engine: MySQL
EngineVersion: 5.7.22
DBName: wordpress
MasterUsername: admin
MasterUserPassword: password
VPCSecurityGroups:
- !ImportValue mysql-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
DeletionPolicy: Delete
Outputs:
DbInstanceEndpoint:
Value: !GetAtt DbServer01.Endpoint.Address
Export:
Name: db-server01-endpoint-(アカウント名) # <- (アカウント名) を置換する
```
### 5.5. ロードバランサーテンプレートの作成
ロードバランサーテンプレートでは、Web サーバへのアクセスを、負荷によって振り分ける機能を持つ、ロードバランサーを作成します。
|[](https://i.imgur.com/0QyZaW2.png)
|:-:|
aws-work フォルダ内に、以下のファイル名でテンプレートを作成します。
```=
ファイル名: loadbalancer.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
LoadBalancer01:
Type: AWS::ElasticLoadBalancing::LoadBalancer
Properties:
Instances:
- !ImportValue web01-instance-id-(アカウント名) # <- (アカウント名) を置換する
- !ImportValue web02-instance-id-(アカウント名) # <- (アカウント名) を置換する
Subnets:
- !ImportValue public-subnet01-id-(アカウント名) # <- (アカウント名) を置換する
- !ImportValue public-subnet02-id-(アカウント名) # <- (アカウント名) を置換する
SecurityGroups:
- !ImportValue elb-sec-group-id-(アカウント名) # <- (アカウント名) を置換する
Listeners:
- LoadBalancerPort: 80
InstancePort: 80
Protocol: HTTP
LoadBalancerName: elb01-(アカウント名) # <- (アカウント名) を置換する
Outputs:
ElbDnsName:
Value: !GetAtt LoadBalancer01.DNSName
Export:
Name: elb01-dns-name-(アカウント名) # <- (アカウント名) を置換する
```
## 6. S3 バケットへのテンプレートファイルのアップロード
### 6.1. サービスメニューより、S3 をクリックする。
|[](https://i.imgur.com/dCZn4oO.png)|
|:-:|
### 6.2. バケットを作成するボタンをクリックする。
|[](https://i.imgur.com/xt1QFrW.png)|
|:-:|
### 6.3. バケット名に以下の内容を入力して、次へボタンをクリックする。
```=
バケット名: s3-cf-template-(アカウント名)
```
|[](https://i.imgur.com/HkcZVT8.png)|
|:-:|
### 6.4. そのまま次へボタンをクリックする。
|[](https://i.imgur.com/z3BcA7b.png)|
|:-:|
### 6.5. そのまま次へボタンをクリックする。
|[](https://i.imgur.com/My1B2jt.png)|
|:-:|
### 6.6. そのままバケットを作成ボタンをクリックする。
|[](https://i.imgur.com/PWsnD2r.png)|
|:-:|
### 6.7. 作成されたバケットをクリックする。
|[](https://i.imgur.com/LE8icJx.png)|
|:-:|
### 6.8. アップロードボタンをクリックする。
|[](https://i.imgur.com/5ixIKkY.png)|
|:-:|
### 6.9. アップロードウィンドウに作成したテンプレートファイルを赤枠の箇所にドラッグ & ドロップする。
:::info
Internet Explorer を使用している場合、ドラッグ & ドロップに対応していない可能性があるため、ファイルを追加ボタンよりファイルを選択してアップロードします。
:::
|[](https://i.imgur.com/A3c1feA.png)|
|:-:|
### 6.10. 選択したファイルが表示されていることを確認してアップロードボタンをクリックする。
|[](https://i.imgur.com/yl8sZmS.png)|
|:-:|
### 6.11. テンプレートファイルがアップロードされたことを確認する。
|[](https://i.imgur.com/zJuqSwB.png)|
|:-:|
:::warning
S3 バケット画面は引き続き利用するため、開いたままにしておきます。
:::
## 7. スタックの作成
### 7.1. サービスメニューより、CloudFormation を右クリックし、新しいタブまたはウィンドウを開く。
|[](https://i.imgur.com/4x3jVnO.png)|
|:-:|
### 7.2. スタックの作成ボタンをクリックする。
|[](https://i.imgur.com/Jc8RQs4.png)|
|:-:|
### 7.3. S3 バケットの画面を開き、network.yaml のチェックボックスをオンにする。
|[](https://i.imgur.com/oCX9v1G.png)|
|:-:|
### 7.4. 画面右に表示されたウィンドウより、オブジェクトの URL を右クリックし、リンクのアドレスをコピーする。
|[](https://i.imgur.com/A6mBA4N.png)|
|:-:|
### 7.5. スタックの作成画面に戻り、Amazon S3 URL にペーストして、次へボタンをクリックする。
|[](https://i.imgur.com/7ac8Vy9.png)
|:-:|
### 7.6. スタック名に以下を入力して、次ボタンをクリックする。
```=
スタック名: stack-(リソース種別)-(アカウント名)
```
:::info
リソース種別は、network.yaml を選択している場合であれば network とします。
:::
|[](https://i.imgur.com/CGfASWN.png)|
|:-:|
### 7.7. そのまま画面下部の次へボタンをクリックする。
|[](https://i.imgur.com/frK79hO.png)|
|:-:|
### 7.8. そのまま画面下部のスタックの作成ボタンをクリックする。
|[](https://i.imgur.com/ZsrRZax.png)|
|:-:|
### 7.9. スタックの作成が開始し、CREATE_IN_PROGRESS と表示されることを確認する。
|[](https://i.imgur.com/5zWgkc6.png)|
|:-:|
### 7.10. スタックの状態が CREATE_COMPLETE と表示されるまで待つ。
|[](https://i.imgur.com/QE807uY.png)|
|:-:|
### 7.11. 上記 7.1 〜 7.10 までの手順を以下の記載順で繰り返し実施する。
```=
security.yaml (作成完了予測時間: 1 分)
instance.yaml (作成完了予測時間: 2 分)
database.yaml (作成完了予測時間: 10 分)
loadbalancer.yaml (作成完了予測時間: 1分)
```
:::info
スタック作成は、画面右上のスタックの作成ボタンをクリックします。
:::
## 8. Wordpress のセットアップ
### 8.1. スタック画面より、stack-loadbalancer-(アカウント名)をクリックし、画面右の出力タブより、ロードバランサー DNS 名をコピーする。
|[](https://i.imgur.com/LmlqpbQ.png)|
|:-:|
:::info
スタック画面は引き続き確認するため、開いておく。
:::
### 8.2. 新たにウェブブラウザを起動し、アドレスバーに、コピーした DNS 名をペーストして WoredPress にアクセスする。
|[](https://i.imgur.com/eVMhR62.png)|
|:-:|
### 8.3. スタック画面より、stack-database-(アカウント名)をクリックし、画面右の出力タブより、データベースのエンドポイント名をコピーする。
|[](https://i.imgur.com/rzqbatc.png)|
|:-:|
### 8.4. WordPress の画面に戻り、さあ、始めましょう! ボタンをクリックする。
|[](https://i.imgur.com/kYXDdbP.png)|
|:-:|
### 8.5. 以下の内容を入力して、送信ボタンをクリックする。
```=
データベース名: wordpress
ユーザー名: admin
パスワード: password
データベースのホスト名: (コピーしたデータベースのエンドポイント名)
```
|[](https://i.imgur.com/6ZEKX3D.png)|
|:-:|
### 8.6. インストール実行ボタンをクリックする。
|[](https://i.imgur.com/pHd3qlX.png)|
|:-:|
### 8.7. 以下の内容を入力して、WordPress をインストールボタンをクリックする。
```
サイトのタイトル: CloudFormation
ユーザ名: admin
パスワード: cf-wp-password
メールアドレス: (別途通知)
```
|[](https://i.imgur.com/GuUnSpH.png)|
|:-:|
### 8.8. ログインボタンをクリックする。
|[](https://i.imgur.com/ZnulY9V.png)|
|:-:|
### 8.9. 以下の内容を入力して、ログインボタンをクリックする。
```=
ユーザー名: admin
パスワード: cf-wp-password
```
|[](https://i.imgur.com/ZxPaMDB.png)|
|:-:|
### 8.10. 以下の画面が表示されることを確認し、画面左上のサイトタイトルをクリックする。
|[](https://i.imgur.com/agach6B.png)|
|:-:|
### 8.11. 以下の画面が表示されることを確認する。
|[](https://i.imgur.com/AcEbCn4.png)|
|:-:|
## 9. スタックの削除
以下の順で作成したスタックを削除する。
```=
stack-loadbalancer
stack-database
stack-instance
stack-security
stack-network
```
スタックの削除は、削除するスタックを選択して、削除ボタンをクリックする。
|[](https://i.imgur.com/N30hT86.png)|
|:-:|
:::warning
スタックで作成したリソースには依存関係があるため、削除の順序に気をつける必要があります。例えば、最初にネットワークを削除しようとした場合、ネットワークに属するインスタンスが存在している状態では、削除エラーとなります。
:::
## 10. ネストされたスタックを使用して共通テンプレートパターンを再利用する
上記までのスタック作成では、5 つのテンプレートファイルがあれば、スタックの作成も 5 回実施する必要がありました。これをより効率化するために、1 つのテンプレートでスタックを作成する方法を説明します。
### 10.1. 統合テンプレートの作成
:::warning
* TemplateURL の (リージョンコード) の箇所を以下の内容を確認して指定します。
```
東京: ap-northeast-1
ソウル: ap-northeast-2
シンガポール: ap-southeast-1
```
* TemplateURL の (アカウント名) の箇所に、割り当てられたアカウント名を指定します。
:::
aws-work フォルダ内に、以下のファイル名でテンプレートファイルを作成します。
```=
ファイル名: master.yaml
```
テンプレートファイルに以下の内容を記述します。
```yaml=
AWSTemplateFormatVersion: 2010-09-09
Resources:
Network:
Type: AWS::CloudFormation::Stack # <- 他のテンプレートを読み込むためのタイプ
Properties:
TemplateURL: "https://s3-cf-template-(アカウント名).s3-(リージョンコード).amazonaws.com/network.yaml"
SecurityGroup:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: "https://s3-cf-template-(アカウント名).s3-(リージョンコード).amazonaws.com/security.yaml"
DependsOn: # <- 依存関係を定義するプロパティ(この場合は Network テンプレートのリソースの作成が完了してから実行する)
- Network
Instance:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: "https://s3-cf-template-(アカウント名).s3-(リージョンコード).amazonaws.com/instance.yaml"
DependsOn:
- SecurityGroup
Database:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: "https://s3-cf-template-(アカウント名).s3-(リージョンコード).amazonaws.com/database.yaml"
DependsOn:
- SecurityGroup
Loadbalancer:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: "https://s3-cf-template-(アカウント名).s3-(リージョンコード).amazonaws.com/loadbalancer.yaml"
DependsOn:
- Instance
```
### 10.2. テンプレートのアップロードとスタックの作成
「7. S3 バケットへのテンプレートファイルのアップロード」、「8. スタックの作成」の手順を参考に作成したテンプレートでスタックを作成する。
スタック名には以下を入力する。
```=
スタック名: stack-master-(アカウント名)
```
### 10.3. スタックの削除
個別テンプレートでスタックを作成した場合と異なり、統合テンプテートを使用してスタックを作成した場合は、統合テンプレートを削除することで、下位のテンプレートで作成されたスタックも依存関係を考慮して削除される。
|[](https://i.imgur.com/GN3l5wV.png)|
|:-:|
全てのスタックリソースが削除される旨のメッセージが表示されるので、スタックの削除ボタンをクリックする。
|[](https://i.imgur.com/B2r1lLA.png)|
|:-:|
## 11. 参考
* [AWS CloudFormation ベストプラクティス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/stacksets-bestpractices.html)
###### tags: `AWS` `NWS` `CloudFormation`