CloudFormationを使ってWordPress環境を構築

## はじめに
2020年のハンズオンを使用してCloudFormationを使ってWebサイト環境を構築しました。2020年作成だったためテンプレートファイルを書き加える必要があったり、変更点がいくつかあったりしたので改修しました。
また公式ではCloud9を使用してますが、2024年7月から新規でCloud9の使用ができなくなっているため、今回はCloudShellを使用しております。
CloudFormationを触ってみたい方はぜひ試してみてください。

## 記事の対象者
- IaCに興味のある方
- CloudFormationを触ってみたい方

## 作成する環境
![IMG_1433.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/3200e849-85f9-3efd-6959-03b42fb153fc.jpeg)


## 手順
- VPCの作成
- EC2の作成
- RDSの作成
- ELBの作成

## テンプレートファイル
以下のリンクからテンプレートファイルを事前にダウンロードしておいてください。
[AWS環境のコード管理AWS CloudFormationでWebシステムを構築する](https://pages.awscloud.com/JAPAN-event-OE-Hands-on-for-Beginners-cfn-2022-reg-event.html?trk=aws_introduction_page)

CloudShellにダウンロードしておいたcfnの中身をすべてアップロードします。

### VPCの作成
CloudFormationのスタック作成からダウンロードしておいたファイルを使用してVPCのスタックを作成します。
![スクリーンショット (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/492788a6-c618-6acc-4e86-23904c3d6e06.png)
- スタックの名前はなんでもよいですが以降の作成でもテンプレートファイルに名前を反映する必要があります
![スクリーンショット (30).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/c0fe7522-3078-988f-bcfa-3250e4285475.png)
- 作成完了です
![スクリーンショット (31).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/f3d12d49-8cac-9113-cf0c-3c61e37149fd.png)





### EC2の作成
行うこと
- EC2用スタックの作成
- 配布したテンプレートでEC2を起動
- 不足設定を書き加えてテンプレートを完成させる

スタック作成
```
aws cloudformation create-stack --stack-name test-cfn-ec2 --template-body file://02_ec2.yml
```
- CloudFormationからスタックの確認
![スクリーンショット (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/19945ed9-f5b2-ba59-1d67-932168a24476.png)


スタックを確認できた後下記3つを書き加えなければなりません。
- サブネットIDの指定
- ユーザーデータのスクリプト
- セキ
- セキュリティグループの追加、アタッチ
＞テンプレートリファレンスを見ながら必須の項目を追記していきます。
[AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)
#### サブネットIDの指定
テンプレートのあるファイルにcdで移動してからvi操作で編集して更新します。
```
[cloudshell-user@ip-10-130-57-170 ~]$ vi 01_vpc.yml
Resources:
  EC2WebServer01:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2AMI
      InstanceType: t2.micro
      SubnetId: subnet-07ab0c7140f070798
```
※サブネットIDはCloudFormationのコンソールから作成したパブリックサブネットの値を入れます。
![スクリーンショット (43).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/759b9443-0b8f-f790-7972-602b72510ce9.png)


#### ユーザーデータのスクリプト
スクリプトの追加をします。
02_ec2_userdata.shを全コピーしてUserDataに貼り付けます。
インデントはSubnetIdの下です。
※Base64エンコードの後ろのパイプもつけてください
```
Resources:
  EC2WebServer01:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref EC2AMI
      InstanceType: t2.micro
      SubnetId: subnet-07ab0c7140f070798
      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       
```  
 
 

 
#### セキュリティグループの追記
EC2SGをユーザーデータスクリプトの下に追記します。

```
　EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP access
      VpcId: vpc-048cf1d9c88a3e6bd
      SecurityGroupIngress:
        - IpProtocol: tcp
          CidrIp: 10.0.0.0/16
          FromPort: 80
          ToPort: 80
```
※sshアクセスも許可したい場合はsshとポート22も同じように追記してください
下の画像のようにインデントがあっていれば大丈夫です。
- SubnetId
- ユーザーデータ
![スクリーンショット (64).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/76256ee9-a8f6-25d7-ca7c-a01068c85b36.png)

- セキュリティグループ
![スクリーンショット (65).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/7b91d289-ea37-201a-0075-b32d4a2bcca1.png)
-----
最後に作成したセキュリティグループをEC2インスタンスにアタッチします。
UserDataの列に加えます。
```
 SecurityGroupIds:
   - !Ref EC2SG
```
画像のように書き加えます。
![スクリーンショット (66).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/6809271c-c0e9-ed80-49f1-b789a5b9f736.png)


- ここまで書き加えたらスタックの更新を行います
- 構文の検証
```
aws cloudformation validate-template --template-body file://02_ec2.yml
```
- 更新
```
aws cloudformation update-stack --stack-name test-cfn-ec2 --template-body file://02_ec2.yml
```
##### CloudFormationで変更した3点の確認を行います。
- サブネットIDがスタックのものになっている
![スクリーンショット (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/cb4d8668-610f-f885-ad4e-de48a05b2098.png)

- ユーザーデータにスクリプトが入っている
![スクリーンショット (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/d6e465d7-3021-440d-f933-cc043ab5324e.png)

- セキュリティグループが作成されておりEC2インスタンスにアタッチしていること
![スクリーンショット (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/d6e13808-bb73-c0c5-17af-64cf16483cf4.png)



### RDSの作成
※上のファイルを使用している方はインスタンスクラスをdb.t2.microからdb.3.microに変更する必要があります。（2024年3月にt2は廃止しているため）
```
vi 03_rds.yml
```
```
Resources:
  DBInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Delete
    Properties:
      DBInstanceClass: db.t3.micro
      AllocatedStorage: "10"
      StorageType: gp2
      Engine: MySQL
      MasterUsername: !Ref DBUser
      MasterUserPassword: !Ref DBPassword
      DBName: wordpress
      BackupRetentionPeriod: 0
      DBSubnetGroupName: !Ref DBSubnetGroup
      VPCSecurityGroups:
        - !Ref DBSecurityGroup
```

変更完了したらスタック作成します。
```
aws cloudformation create-stack --stack-name test-cfn-rds --template-body file://03_rds.yml
```
CloudFormationからリソースとCloudShellの03_rds.ymlを参照して以下をコピーします。
※WordPressのログイン時に使用します。

- パラメータのユーザ名とパスワード
```
Default: dbmaster
Default: H&ppyHands0n
```
- DBエンドポイント


### ELBの作成
```
aws cloudformation create-stack --stack-name test-cfn-elb --template-body file://04_elb.yml
```
※VPCやEC2の名前を変更した方はviコマンドでパラメータを編集する必要があります。

### 接続
ここまでできたらCloudFormationコンソールからELBエンドポイントを押下してWordPressのログインが求められる画面まで行きます。
```
データベース名：wordpress
ユーザー名：dbmaster
パスワード：H&ppyHands0n
データベースのホスト名：控えておいたDBエンドポイント
```
上の情報にてログインします。
![IMG_1431.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/ebad1a25-8dc6-831d-fafc-9679301e52bd.jpeg)
- ユーザー名はadminでパスワードは控えておきます。
![IMG_1432.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812406/b373d81d-07b1-6728-e5c0-b0ce88ad37c8.jpeg)
次のログイン画面でadminと控えたパスワードからログインできます。

### 削除
コンソールから削除か`aws cloudformation delete-stack --stack-name test-cfn-xxx`を使用して作成した順番とは逆でスタック消していきます。

### 感想
テンプレートリファレンスを参照しながら、最低限のものならテンプレートの記述をできるようになった。
またテンプレートの細かい変更を反映していきながらスタックの更新を繰り返すことで、フィードバックを素早く行えるメリットを感じることができた。

### 参考記事
[AWS リソースおよびプロパティタイプのリファレンス](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html)
[AWS ハンズオン資料](https://aws.amazon.com/jp/events/aws-event-resource/hands-on/)