# 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)](https://i.imgur.com/68X8KkK.png)| |:-:| ## 3. EC2 キーペアの作成 ### 3.1. サービスメニューより、EC2 をクリックする。 |[![](https://i.imgur.com/VYnOJmd.png)](https://i.imgur.com/VYnOJmd.png)| |:-:| ### 3.2. 左メニューより、キーペアをクリックする。 |[![](https://i.imgur.com/8kyxcD0.png)](https://i.imgur.com/8kyxcD0.png)| |:-:| ### 3.3. キーペアを作成 ボタンをクリックする。 |[![](https://i.imgur.com/3CLThpa.png)](https://i.imgur.com/3CLThpa.png) |:-:| ### 3.4. 以下のとおり入力し、キーペアを作成 ボタンをクリックする。 ```= 名前: stack-(アカウント名) ファイル形式: pem ``` :::warning (アカウント名)は、ログインユーザー名 admin01 などに置き換えて入力します。 ::: |[![](https://i.imgur.com/hneVK0l.png)](https://i.imgur.com/hneVK0l.png)| |:-:| ### 3.5 stack-(アカウント名).pem ファイルがダウンロードされるため、任意の場所に保存する。 :::warning キーペアファイルのダウンロードは作成時のみであるため、紛失しないように注意してください。作成済みのキーペアファイルを再度ダウンロードすることはできません。紛失した場合、キーペアと紐つくインスタンスには ssh でログインできなくなります。 ::: ### 3.6. キーペアが作成されたことを確認する。 |[![](https://i.imgur.com/HdsN45v.png)](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)](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)](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)](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/VYnOJmd.png)| |:-:| インスタンスの起動ボタンより、インスタンスの起動を選択する。 |[![](https://i.imgur.com/vuNakuD.png)](https://i.imgur.com/vuNakuD.png)| |:-:| Amazon Linux 2 AMI (HVM), SSD Volume Type の AMI ID を確認する。 |[![](https://i.imgur.com/ysCjnsu.png)](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)](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)](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)](https://i.imgur.com/dCZn4oO.png)| |:-:| ### 6.2. バケットを作成するボタンをクリックする。 |[![](https://i.imgur.com/xt1QFrW.png)](https://i.imgur.com/xt1QFrW.png)| |:-:| ### 6.3. バケット名に以下の内容を入力して、次へボタンをクリックする。 ```= バケット名: s3-cf-template-(アカウント名) ``` |[![](https://i.imgur.com/HkcZVT8.png)](https://i.imgur.com/HkcZVT8.png)| |:-:| ### 6.4. そのまま次へボタンをクリックする。 |[![](https://i.imgur.com/z3BcA7b.png)](https://i.imgur.com/z3BcA7b.png)| |:-:| ### 6.5. そのまま次へボタンをクリックする。 |[![](https://i.imgur.com/My1B2jt.png)](https://i.imgur.com/My1B2jt.png)| |:-:| ### 6.6. そのままバケットを作成ボタンをクリックする。 |[![](https://i.imgur.com/PWsnD2r.png)](https://i.imgur.com/PWsnD2r.png)| |:-:| ### 6.7. 作成されたバケットをクリックする。 |[![](https://i.imgur.com/LE8icJx.png)](https://i.imgur.com/LE8icJx.png)| |:-:| ### 6.8. アップロードボタンをクリックする。 |[![](https://i.imgur.com/5ixIKkY.png)](https://i.imgur.com/5ixIKkY.png)| |:-:| ### 6.9. アップロードウィンドウに作成したテンプレートファイルを赤枠の箇所にドラッグ & ドロップする。 :::info Internet Explorer を使用している場合、ドラッグ & ドロップに対応していない可能性があるため、ファイルを追加ボタンよりファイルを選択してアップロードします。 ::: |[![](https://i.imgur.com/A3c1feA.png)](https://i.imgur.com/A3c1feA.png)| |:-:| ### 6.10. 選択したファイルが表示されていることを確認してアップロードボタンをクリックする。 |[![](https://i.imgur.com/yl8sZmS.png)](https://i.imgur.com/yl8sZmS.png)| |:-:| ### 6.11. テンプレートファイルがアップロードされたことを確認する。 |[![](https://i.imgur.com/zJuqSwB.png)](https://i.imgur.com/zJuqSwB.png)| |:-:| :::warning S3 バケット画面は引き続き利用するため、開いたままにしておきます。 ::: ## 7. スタックの作成 ### 7.1. サービスメニューより、CloudFormation を右クリックし、新しいタブまたはウィンドウを開く。 |[![](https://i.imgur.com/4x3jVnO.png)](https://i.imgur.com/4x3jVnO.png)| |:-:| ### 7.2. スタックの作成ボタンをクリックする。 |[![](https://i.imgur.com/Jc8RQs4.png)](https://i.imgur.com/Jc8RQs4.png)| |:-:| ### 7.3. S3 バケットの画面を開き、network.yaml のチェックボックスをオンにする。 |[![](https://i.imgur.com/oCX9v1G.png)](https://i.imgur.com/oCX9v1G.png)| |:-:| ### 7.4. 画面右に表示されたウィンドウより、オブジェクトの URL を右クリックし、リンクのアドレスをコピーする。 |[![](https://i.imgur.com/A6mBA4N.png)](https://i.imgur.com/A6mBA4N.png)| |:-:| ### 7.5. スタックの作成画面に戻り、Amazon S3 URL にペーストして、次へボタンをクリックする。 |[![](https://i.imgur.com/7ac8Vy9.png)](https://i.imgur.com/7ac8Vy9.png) |:-:| ### 7.6. スタック名に以下を入力して、次ボタンをクリックする。 ```= スタック名: stack-(リソース種別)-(アカウント名) ``` :::info リソース種別は、network.yaml を選択している場合であれば network とします。 ::: |[![](https://i.imgur.com/CGfASWN.png)](https://i.imgur.com/CGfASWN.png)| |:-:| ### 7.7. そのまま画面下部の次へボタンをクリックする。 |[![](https://i.imgur.com/frK79hO.png)](https://i.imgur.com/frK79hO.png)| |:-:| ### 7.8. そのまま画面下部のスタックの作成ボタンをクリックする。 |[![](https://i.imgur.com/ZsrRZax.png)](https://i.imgur.com/ZsrRZax.png)| |:-:| ### 7.9. スタックの作成が開始し、CREATE_IN_PROGRESS と表示されることを確認する。 |[![](https://i.imgur.com/5zWgkc6.png)](https://i.imgur.com/5zWgkc6.png)| |:-:| ### 7.10. スタックの状態が CREATE_COMPLETE と表示されるまで待つ。 |[![](https://i.imgur.com/QE807uY.png)](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)](https://i.imgur.com/LmlqpbQ.png)| |:-:| :::info スタック画面は引き続き確認するため、開いておく。 ::: ### 8.2. 新たにウェブブラウザを起動し、アドレスバーに、コピーした DNS 名をペーストして WoredPress にアクセスする。 |[![](https://i.imgur.com/eVMhR62.png)](https://i.imgur.com/eVMhR62.png)| |:-:| ### 8.3. スタック画面より、stack-database-(アカウント名)をクリックし、画面右の出力タブより、データベースのエンドポイント名をコピーする。 |[![](https://i.imgur.com/rzqbatc.png)](https://i.imgur.com/rzqbatc.png)| |:-:| ### 8.4. WordPress の画面に戻り、さあ、始めましょう! ボタンをクリックする。 |[![](https://i.imgur.com/kYXDdbP.png)](https://i.imgur.com/kYXDdbP.png)| |:-:| ### 8.5. 以下の内容を入力して、送信ボタンをクリックする。 ```= データベース名: wordpress ユーザー名: admin パスワード: password データベースのホスト名: (コピーしたデータベースのエンドポイント名) ``` |[![](https://i.imgur.com/6ZEKX3D.png)](https://i.imgur.com/6ZEKX3D.png)| |:-:| ### 8.6. インストール実行ボタンをクリックする。 |[![](https://i.imgur.com/pHd3qlX.png)](https://i.imgur.com/pHd3qlX.png)| |:-:| ### 8.7. 以下の内容を入力して、WordPress をインストールボタンをクリックする。 ``` サイトのタイトル: CloudFormation ユーザ名: admin パスワード: cf-wp-password メールアドレス: (別途通知) ``` |[![](https://i.imgur.com/GuUnSpH.png)](https://i.imgur.com/GuUnSpH.png)| |:-:| ### 8.8. ログインボタンをクリックする。 |[![](https://i.imgur.com/ZnulY9V.png)](https://i.imgur.com/ZnulY9V.png)| |:-:| ### 8.9. 以下の内容を入力して、ログインボタンをクリックする。 ```= ユーザー名: admin パスワード: cf-wp-password ``` |[![](https://i.imgur.com/ZxPaMDB.png)](https://i.imgur.com/ZxPaMDB.png)| |:-:| ### 8.10. 以下の画面が表示されることを確認し、画面左上のサイトタイトルをクリックする。 |[![](https://i.imgur.com/agach6B.png)](https://i.imgur.com/agach6B.png)| |:-:| ### 8.11. 以下の画面が表示されることを確認する。 |[![](https://i.imgur.com/AcEbCn4.png)](https://i.imgur.com/AcEbCn4.png)| |:-:| ## 9. スタックの削除 以下の順で作成したスタックを削除する。 ```= stack-loadbalancer stack-database stack-instance stack-security stack-network ``` スタックの削除は、削除するスタックを選択して、削除ボタンをクリックする。 |[![](https://i.imgur.com/N30hT86.png)](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/GN3l5wV.png)| |:-:| 全てのスタックリソースが削除される旨のメッセージが表示されるので、スタックの削除ボタンをクリックする。 |[![](https://i.imgur.com/B2r1lLA.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`