はじめに
今回は、AWSの入門でよくみかけるWeb3層構成にオートスケーリングの要素を追加しCloudFormationで、20分程度(爆速?)で構築したいと思います。
スタックの作成手順を簡素化するためにネストされたスタックを使用します。以下を参考にご覧いただければと思います。
テンプレートの更新箇所は以下を参考に作成していきます。
AWS CloudFormation で Auto Scaling グループを作成する - Amazon EC2 Auto Scaling
AWS CloudFormation を使用して Auto Scaling グループを作成する方法について説明します。
構成図

事前準備
CloudFormationテンプレートのダウンロード
CloudFormationテンプレートは以下にございます。
ダウンロードしてデスクトップなど任意のフォルダに保存します。
aws-improvement-tips/nestedstack-basic-struct-autoscaling at main · kosments/aws-improvement-tips
Contribute to kosments/aws-improvement-tips development by creating an account on GitHub.
※その他のファイルも後述の手順で使用するためダウンロードしておきます
CloudFormation:YAMLテンプレートのポイント
以前から追加されたYAMLテンプレートのポイントを記述します。
- LaunchTemplate:
- AWS::EC2::LaunchTemplateリソースを使用して、EC2インスタンスの起動テンプレートを定義しています。
- KeyName、ImageId、InstanceType、IamInstanceProfile、NetworkInterfacesなどのプロパティを指定しています。
- UserDataセクションでは、EC2インスタンス起動時に実行されるスクリプトを定義しています。このスクリプトは、WordPressの設定、EFSのマウント、DBパラメータの取得などを行っています。
- EFSについては、WordPressのコンテンツデータが配置されていることを想定してマウントしています。
- AutoScalingGroup:
- AWS::AutoScaling::AutoScalingGroupリソースを使用して、AutoScalingグループを定義しています。
- VPCZoneIdentifierプロパティでは、!Split関数と!ImportValue関数を使用して、パブリックサブネットIDのリストを取得しています。
- LaunchTemplateプロパティでは、先ほど定義したLaunchTemplateを参照しています。
- TargetGroupARNsプロパティでは、!ImportValue関数を使用して、HTTP用のターゲットグループをインポートしています。
- DesiredCapacity、MaxSize、MinSizeプロパティを使用して、AutoScalingグループの desired/max/min のインスタンス数を設定しています。
- Tagsプロパティでは、AutoScalingグループとそのインスタンスにタグを割り当てています。PropagateAtLaunch: trueを指定することで、これらのタグが起動されたインスタンスに伝播されます。
Resources:
# ------------------------------ #
# LaunchTemplate
# ------------------------------ #
LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateName: !Join ["-", [!Ref TagEnv, !Ref TagApplication, launchtemplate]]
LaunchTemplateData:
KeyName: !Ref Keypair
ImageId: !Ref AmiId
InstanceType: t2.micro
IamInstanceProfile:
Arn: !GetAtt Ec2InstanceProfile.Arn
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
SubnetId: !ImportValue testPublicSubnet1a
Groups:
- !ImportValue testEC2SecurityGroup
TagSpecifications:
- ResourceType: instance
Tags:
- Key: Name
Value: !Join ["-", [!Ref TagEnv, !Ref TagApplication, ec2-webap-server]]
UserData:
Fn::Base64: |
#!/bin/bash
# Set variables
aws configure set region ap-northeast-1
DB_NAME_PARAM="/wordpress/DB_NAME"
DB_USER_PARAM="/wordpress/DB_USER"
DB_PASSWORD_PARAM="/wordpress/DB_PASSWORD"
DB_HOST_PARAM="/wordpress/DB_HOST"
EFS_ID_PARAM="/wordpress/EFS_ID"
EFS_ID=$(aws ssm get-parameter --with-decryption --name $EFS_ID_PARAM --query "Parameter.Value" --output text)
WEB_ROOT="/var/www/html/"
WP_CONFIG_SAMPLE="$WEB_ROOTwp-config-sample.php"
WP_CONFIG="$WEB_ROOTwp-config.php"
yum -y update
amazon-linux-extras install php7.2 -y
yum -y install mysql httpd php-mbstring php-xml gd php-gd
systemctl enable httpd.service
systemctl start httpd.service
systemctl status httpd.service
wget <http://ja.wordpress.org/latest-ja.tar.gz> ~/
tar zxvf /latest-ja.tar.gz
yum -y install amazon-efs-utils
# Add EFS mount to /etc/fstab
echo "$EFS_ID:/ /var/www/html efs _netdev,noresvport,tls,iam 0 0" >> /etc/fstab
sudo mount -fav
mount -t efs $EFS_ID $WEB_ROOT
chown apache:apache -R /var/www/html
cd /var/www/html
# Get parameter values from SSM Parameter Store
DB_NAME=$(aws ssm get-parameter --name $DB_NAME_PARAM --query "Parameter.Value" --output text)
DB_USER=$(aws ssm get-parameter --with-decryption --name $DB_USER_PARAM --query "Parameter.Value" --output text)
DB_PASSWORD=$(aws ssm get-parameter --with-decryption --name $DB_PASSWORD_PARAM --query "Parameter.Value" --output text)
DB_HOST=$(aws ssm get-parameter --with-decryption --name $DB_HOST_PARAM --query "Parameter.Value" --output text)
# Copy wp-config-sample.php to wp-config.php
cp $WP_CONFIG_SAMPLE $WP_CONFIG
# Update wp-config.php file
sed -i -e "s/define( 'DB_NAME', '.*' );/define('DB_NAME', '$DB_NAME');/" $WP_CONFIG
sed -i -e "s/define( 'DB_USER', '.*' );/define('DB_USER', '$DB_USER');/" $WP_CONFIG
sed -i -e "s/define( 'DB_PASSWORD', '.*' );/define('DB_PASSWORD', '$DB_PASSWORD');/" $WP_CONFIG
sed -i -e "s/define( 'DB_HOST', '.*' );/define('DB_HOST', '$DB_HOST');/" $WP_CONFIG
#memory config fix
sed -i -e "s/pm = dynamic/pm = static/" /etc/php-fpm.d/www.conf
sed -i -e "s/pm.max_children = 50/pm.max_children = 3/" /etc/php-fpm.d/www.conf
systemctl restart php-fpm
# ------------------------------------------------------------#
# AutoScaling Group
# ------------------------------------------------------------#
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: !Join ["-", [!Ref TagOwner, !Ref TagApplication, !Ref TagEnv, !Ref TagUser, asg]]
VPCZoneIdentifier: !Split [",", !ImportValue testPublicSubnetIds]
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt LaunchTemplate.LatestVersionNumber
TargetGroupARNs:
- !ImportValue testHttpTargetGroup
DesiredCapacity: 2
MaxSize: 2
MinSize: 2
Tags:
- Key: Name
Value: !Join ["-", [!Ref TagOwner, !Ref TagApplication, !Ref TagEnv, !Ref TagUser, asg]]
PropagateAtLaunch: true
構築手順
1.S3バケットの作成
任意のターミナルを開きをカレントディレクトリに以下のファイルを配置して、コマンドを実行します。
test-cfn-template-bucket.yml
aws cloudformation create-stack --region ap-northeast-1 --stack-name test-cfn-template-bucket --template-body file://test-cfn-template-bucket.yml

2.テンプレートをS3にアップロード
作成したバケットに子テンプレートとなる以下のファイルをアップロードしておきます。
- test-nw.yml
- test-rds.yml
- test-alb.yml
- test-asg.yml

3.親スタックの作成
- 任意のターミナルソフトを開き、保存しておいた以下のYAMLテンプレートをカレントディレクトリに配置します。
$ ls
root-stack.yml
- リソースの作成:以下のコマンドを実行します。
aws cloudformation create-stack --region ap-northeast-1 --stack-name test-root-stack --template-body file://test-root-stack.yml

各リソースが作成されました。
補足:スタックの作成_GUI
マネジメントコンソールからスタックの作成を行う手順も記載していますので、GUIの方がわかりやすいという方はこちらをお試しください。
手順は、以下の通りで、リンクにも詳細がございます。
- CloudFormation画面を開きスタックの作成>新しいソースを使用(標準)を選択
- テンプレートの準備完了>テンプレートファイルのアップロードを選択して、保存したymlを選択
- スタックに任意の名称を入力して、パラメータは環境に合わせて変更>次へを選択。
- スタックオプションは特に変更せず、次へを選択
- レビュー画面を確認して送信を選択
まとめ
今回は、NestedStackを用いて、AutoScaling構成を作成しました。
NestedStackはS3に子テンプレートを配置する必要があるため、こちらを自動化も含めたPipelineの作成なども検証してみたいと思います。
最後までご覧いただきありがとうございました。
コメント