独自ドメインでアクセス：AWS CloudFormationを使ったVPC設定、Apacheサーバーのデプロイ、ALBおよびACM証明書の設定

## はじめに
ITスクールでのハッカソン経験を通じて、限られた時間の中でコストを抑えつつ、迅速にデプロイする必要がありました。

:::note warn
**その中で、AWSのCloudFormationを活用し、ALB、ACM、Route53などを駆使して、セキュアな通信環境をコード化する方法を実践しました。**
:::

本記事では、CloudFormationを用いて、効率的でセキュアなインフラをどのように構築したかを紹介します。

## テンプレート概要
このCloudFormationテンプレートは簡易的な構成ではありますが、以下をコードで構築しています。

:::note
- **VPC (Virtual Private Cloud)：**
ネットワーク基盤
- **サブネット：**
2つのパブリックサブネット
- **インターネットゲートウェイとルートテーブル：**
外部アクセスを可能にする
- **EC2インスタンス：**
Apacheサーバーをホスト
- **ALB：**
トラフィックの分散
- **ACM証明書：**
HTTPS接続を実現
:::

今回は、事前に取得しておいた独自ドメインでのRoute53登録は手動で実行します。

## テンプレートのセクションごとの説明

### 1. VPCとサブネットの作成
テンプレートでは、1つのVPCと2つのパブリックサブネットを作成します。

```yaml
HondaVpc:
  Type: "AWS::EC2::VPC"
  Properties:
    CidrBlock: "10.0.0.0/16"
    EnableDnsSupport: true
    EnableDnsHostnames: true
    Tags:
      - Key: "Name"
        Value: "honda-vpc"
```

サブネットは、それぞれ異なるアベイラビリティゾーン（ap-northeast-1a、ap-northeast-1c）に配置しています。

### 2. インターネットゲートウェイとルートテーブル
作成したVPCをインターネットに接続するため、インターネットゲートウェイとデフォルトルートを設定します。

```yaml
HondaInternetGateway:
  Type: "AWS::EC2::InternetGateway"
```

ここでは割愛しますが、サブネットをルートテーブルに関連付けも必要になります。

### 3. ApacheサーバーのEC2インスタンス
UserDataスクリプトを使用して、EC2インスタンスにApacheを自動インストールし、デフォルトのウェブページを設定します。

```yaml
ApacheInstance:
  Type: "AWS::EC2::Instance"
  Properties:
    InstanceType: "t2.micro"
    SubnetId: !Ref HondaSubnetPublic1
    UserData:
      Fn::Base64: !Sub |
        #!/bin/bash
        yum update -y
        yum install -y httpd
        systemctl start httpd
        echo "<html><body><h1>CloudFormation面白い!!</h1></body></html>" > /var/www/html/index.html
```

### 4. ALBの構成
ALB（アプリケーションロードバランサ）を作成し、ターゲットグループとリスナーを構成します。

HTTPSリスナーは、ACM証明書を使用して安全な接続を提供します。

```yaml
HondaALB:
  Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
  Properties:
    Name: "honda-alb"
    Subnets:
      - Ref: HondaSubnetPublic1
      - Ref: HondaSubnetPublic2
    SecurityGroups:
      - Ref: ALBSecurityGroup
```

ターゲットグループでは、Apacheサーバーのヘルスチェックも設定されています。

```yaml
HondaALBTargetGroup:
  Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
  Properties:
    Port: 80
    Protocol: "HTTP"
    HealthCheckProtocol: "HTTP"
    HealthCheckPath: "/"
```

### 5. ACM証明書の統合
HTTPSリスナーを作成し、ACM証明書を適用します。

```yaml
HondaALBListener:
  Type: "AWS::ElasticLoadBalancingV2::Listener"
  Properties:
    Port: 443
    Protocol: "HTTPS"
    Certificates:
      - CertificateArn: !Ref ACMCertificate
```

## 完成したコード

ここまでの上記内容を踏まえて、最終的に完成したコードは以下になります。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: "Honda VPC Setup, Apache Server Deployment, ALB and ACM Certificate Configuration"

Parameters:
  ACMCertificate:
    Type: String
    Default: "arn:aws:acm:ap-northeast-1:340823193247:certificate/4c8e465b-6926-47c7-87e8-06ae27b895bd"
    Description: "ARN of the ACM Certificate"

Resources:
  # VPCの作成
  HondaVpc:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: "10.0.0.0/16"
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: "Name"
          Value: "honda-vpc"

  # パブリックサブネット1の作成
  HondaSubnetPublic1:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref HondaVpc
      CidrBlock: "10.0.0.0/20"
      AvailabilityZone: "ap-northeast-1a"
      MapPublicIpOnLaunch: true
      Tags:
        - Key: "Name"
          Value: "honda-subnet-public1-ap-northeast-1a"

  # パブリックサブネット2の作成
  HondaSubnetPublic2:
    Type: "AWS::EC2::Subnet"
    Properties:
      VpcId: !Ref HondaVpc
      CidrBlock: "10.0.16.0/20"
      AvailabilityZone: "ap-northeast-1c"
      MapPublicIpOnLaunch: true
      Tags:
        - Key: "Name"
          Value: "honda-subnet-public2-ap-northeast-1c"

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

  # インターネットゲートウェイとVPCを接続
  AttachInternetGateway:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref HondaVpc
      InternetGatewayId: !Ref HondaInternetGateway

  # パブリックルートテーブルの作成
  HondaRouteTablePublic:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref HondaVpc
      Tags:
        - Key: "Name"
          Value: "honda-rtb-public"

  # デフォルトルートの設定（インターネットへの接続）
  HondaRoute:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref HondaRouteTablePublic
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref HondaInternetGateway

  # パブリックサブネット1にルートテーブルを関連付け
  AssociateRouteTable1:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref HondaRouteTablePublic
      SubnetId: !Ref HondaSubnetPublic1

  # パブリックサブネット2にルートテーブルを関連付け
  AssociateRouteTable2:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref HondaRouteTablePublic
      SubnetId: !Ref HondaSubnetPublic2

  # ALB用セキュリティグループ
  ALBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Allow HTTPS traffic"
      VpcId: !Ref HondaVpc
      SecurityGroupIngress:
        - IpProtocol: "tcp"
          FromPort: 443
          ToPort: 443
          CidrIp: "0.0.0.0/0"

  # EC2用セキュリティグループ
  EC2SecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Allow HTTP from ALB and SSH"
      VpcId: !Ref HondaVpc
      SecurityGroupIngress:
        - IpProtocol: "tcp"
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref ALBSecurityGroup
        - IpProtocol: "tcp"
          FromPort: 22
          ToPort: 22
          CidrIp: "0.0.0.0/0"

  # ApacheサーバーをセットアップするEC2インスタンス
  ApacheInstance:
    Type: "AWS::EC2::Instance"
    Properties:
      InstanceType: "t2.micro"
      SubnetId: !Ref HondaSubnetPublic1
      SecurityGroupIds:
        - !Ref EC2SecurityGroup
      ImageId: "ami-0b6fe957a0eb4c1b9"  # Amazon Linux 2 (Tokyo)
      KeyName: "honda"
      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>CloudFormation面白い!</h1></body></html>" > /var/www/html/index.html

  # ALB (Application Load Balancer)を作成
  HondaALB:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: "honda-alb"
      Subnets:
        - Ref: HondaSubnetPublic1
        - Ref: HondaSubnetPublic2
      SecurityGroups:
        - Ref: ALBSecurityGroup
      LoadBalancerAttributes:
        - Key: "idle_timeout.timeout_seconds"
          Value: "60"
      Scheme: "internet-facing"
      Type: "application"
      IpAddressType: "ipv4"

  # ALBターゲットグループ
  HondaALBTargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      Name: "honda-alb-target-group"
      Port: 80
      Protocol: "HTTP"
      VpcId: !Ref HondaVpc
      HealthCheckProtocol: "HTTP"
      HealthCheckPort: "80"
      HealthCheckPath: "/"
      Matcher:
        HttpCode: "200"
      Targets:
        - Id: !Ref ApacheInstance

  # ALBリスナーを作成（HTTPSを使用）
  HondaALBListener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      DefaultActions:
        - Type: "forward"
          TargetGroupArn: !Ref HondaALBTargetGroup
      LoadBalancerArn: !Ref HondaALB
      Port: 443
      Protocol: "HTTPS"
      Certificates:
        - CertificateArn: !Ref ACMCertificate
```

## 実際にやってみた

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/65a5919d-5bb1-1fa0-af9d-f537205a1a44.png)

### Route 53 のホストゾーンに A レコードを追加

ホストゾーンの画面からAレコードを登録します。まず、ホストゾーンを選択し、「レコードを追加」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/dd3a9a07-bf5d-a6cf-a8ab-03917a650383.png)

その後、Aレコードとして作成したALBを登録します。ルーティング設定はシンプルに進めます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0317ba55-a34a-8910-44fb-7f1a96c4056e.png)

## ブラウザからアクセスしてみる

すべての手順が完了したら、ブラウザで取得したドメイン名（例: ``https://honda333.blog/``）にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/5690150f-1f34-170c-d84a-cac707d31954.png)

また、ALBやACMも問題なくインフラのコード化が成功していることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/b127be0f-2338-af34-606d-4879fdc80b70.png)

## まとめ

今回ご紹介したCloudFormationテンプレートでは、基本的なネットワーク構成の作成からウェブサーバーのデプロイ、HTTPS対応のALB設定までを一貫してコードで構築するプロセスを解説しました。

:::note
**このテンプレートを活用すれば、再現性のある効率的なインフラ構築が可能です。**
:::

次回は、さらに難易度の高いコード化に挑戦し、スケーラブルで複雑なシステムの構築方法を探っていきたいと思います！

## 関連記事

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