インフラのコード化：CloudFormationを使用してEC2インスタンスを構築し、Apacheをインストールする設定

## はじめに
[前回の記事](https://qiita.com/free-honda/items/7770f57db0b9e619cfb4)では、Terraformを用いてAWSインフラのコード化を行いました。

本記事ではこれをCloudFormationに置き換え、同様の構成をコード化して自動的に構築する手順を解説します。

:::note warn 
**特に、CloudFormationではリソース間の依存関係やテンプレート構文の理解が重要で、初めて取り組む場合には注意が必要です。** 
:::

ゴールは、パブリックサブネットに配置されたApacheがインストールされたEC2インスタンスを構築し、ブラウザからテストページを確認することです。

## 自動化する構成について

今回は、AWSのインフラを構築するために、以下の構成を自動化しました。

:::note info
- **VPC（仮想プライベートクラウド）:** 
10.0.0.0/16のCIDRを持つネットワークを構成します。

- **サブネット:** 
パブリックサブネット（10.0.1.0/24）を作成し、EC2インスタンスを配置します。

- **インターネットゲートウェイ（IGW）:** 
インターネットとVPCを接続します。

- **ルートテーブル:** 
サブネットからインターネットへのルートを設定します。

- **セキュリティグループ:** 
HTTP（80番ポート）およびSSH（22番ポート）アクセスを許可します。

- **EC2インスタンス:** 
Amazon Linux 2を使用し、Apache HTTPサーバーをインストールします。
:::

実際に作成したVPCのリソースマップは以下の通りです。パブリックサブネットにApacheがインストールされたEC2インスタンスが構築されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/3d8e9887-b73c-273b-55d8-2e872b662d58.png)

この構成を手動で作成するのは時間がかかり、管理も煩雑になります。

:::note warn
**CloudFormationを使うことで、インフラをコードとして管理し、再現性のあるインフラを実現できます。**
:::

## CloudFormationテンプレート

以下は、構成全体を自動化するためのCloudFormationテンプレートです。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Create VPC, Subnet, Internet Gateway, Security Group, and EC2 instance with Apache using CloudFormation.

Resources:
  # VPC作成
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: cloudformation-main-vpc

  # パブリックサブネット作成
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: cloudformation-public-subnet

  # インターネットゲートウェイ作成
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: cloudformation-igw

  # インターネットゲートウェイとVPCの関連付け
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref InternetGateway

  # ルートテーブル作成
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC
      Tags:
        - Key: Name
          Value: cloudformation-public-route-table

  # インターネットへのルート設定
  Route:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  # サブネットとルートテーブルの関連付け
  SubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # セキュリティグループ作成
  PublicSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP and SSH
      VpcId: !Ref MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: -1
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: cloudformation-public-sg

  # EC2インスタンス作成
  ApacheInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !GetAtt PublicSecurityGroup.GroupId
      ImageId: ami-0b6fe957a0eb4c1b9 # Amazon Linux 2 (Tokyo)
      KeyName: <YourKeyName> # 必要に応じて設定
      Tags:
        - Key: Name
          Value: cloudformation-apache-ec2
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          echo "<html><body><h1>Welcome to Apache Server powered by CloudFormation!</h1></body></html>" > /var/www/html/index.html
```

CloudFormationでは、サブネット単位でパブリックIPの割り当てを管理します。そのため、サブネット作成時に設定する ``MapPublicIpOnLaunch`` に依存します。

一方、Terraformではインスタンス単位でパブリックIPの割り当てを管理し、インスタンス作成時に個別に設定する必要があります（``associate_public_ip_address``）。

## 実際にスタックを実行してみた

CloudFormationのサービス画面からスタックの作成に進み、作成した``yamlファイル``をアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/1f238e06-6895-82e7-2628-fa85366f6ac7.png)

スタック名は任意で設定できます。ここでは私の名前「``honda``」としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/1c75259d-d21d-c09a-f4ca-e962527617fb.png)

画面遷移後のスタックオプション設定は、個別の設定に依存するため、今回は設定せずに進めます。

最後に確認を行い、問題がなければ最下部までスクロールし、「``送信``」をクリックして完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0f0a08f4-d6e4-cf96-b900-11e27e0176db.png)

スタックの実行後、イベントタブで成功を確認できました（実行には少し時間がかかります）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8bd70c7a-6b12-d0a6-7f46-3e3e711f3bea.png)

## 検証結果の確認

作業が完了したので、実際にマネジメントコンソールで確認します。VPCが想定通りに作成されていることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c99b72ac-4b13-3604-f079-b06ffeaa3392.png)

また、コード内で作成したEC2インスタンスも確認できました。パブリックIPアドレスをブラウザに入力し、アクセスができるか確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/342b4c43-3676-f39e-96af-5587d9d4e7f4.png)

今回は検証のため、HTTPS通信ではなくHTTP通信でアクセスしています。

```bash
http://35.78.209.29/
```

実際に、``cloudformation-apache-ec2``の``index.html``ファイルの内容が表示されていることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/5ef789f7-a272-c3f8-a325-3662d7c6453c.png)

この確認をもって、検証は大成功です！

## まとめ
今回は、CloudFormationを使用してAWSのEC2インスタンスを自動化する構成を作成しました。

:::note warn
**Terraformとの構文の違いに悩まされながらも、無事にインフラをコード化することができました。**
:::

今後は、より複雑な構成に挑戦し、さらに自動化を進めていきたいと思います！

## 関連記事

CloudFormationによるインフラのコード化についても過去の記事で解説しているため、より深く知りたい方は読んでみてください！

https://qiita.com/free-honda/items/5a8c69df40c631549663

https://qiita.com/free-honda/items/06d092c82d1dcb1e77fe

https://qiita.com/free-honda/items/da70f65d9d93a89abd23

https://qiita.com/free-honda/items/d0a10b8db9579b525d58

https://qiita.com/free-honda/items/a2563c86c6d8eda89a96