CloudFormationを使ってEC2インスタンスを構築し、起動時にApacheをインストールする

今回はCloudFormaitonを使ってEC2インスタンスを構築し、起動時にApacheをインストールする手順を説明します。
Parametersのボリュームを増やし、Ref関数によってResousesの記載をシンプルにさせました。
これにより、スタック作成時に設定値をカスタマイズ出来るようなテンプレートとなっております。

#前提条件
- Windows10を使用。
- PCはDELLを使用。
- ファイルの拡張子は.ymlを使用。
- 東京リージョンを使用。
- アベイラビリティゾーンは1aと1cを使用。

#料金
テンプレート自体に料金は発生しないが、作成後のAWSリソースに関しては料金が発生しますのでご注意下さい。

#事前準備
- AWSアカウントを所持していること。
- Amazon VPCへのアクセス権限（書き込み・読み取り）を許可していること。
- AWS Cloudformationへのアクセス権限（書き込み・読み取り）を許可していること。
- AWS EC2へのアクセス権限（書き込み・読み取り）を許可していること。
- VPCとpublic subnetとprivate subnetが作成済みであること。
- EC2インスタンスはLinuxであること。
- public subnetはIGWを介してインターネットアクセスできること。
- private subnetはNatGatewayを介してインターネットにアクセスできること。

#構築内容
- 東京リージョンにEC2インスタンスを構築。
- 起動時にApacheをインストールし、index.htmlに"Hello World from user data"を出力させる。

#テンプレート
EC2の作成のスタックは以下の通りです。

```yml:EC2_create.yml
AWSTemplateFormatVersion: "2010-09-09"
Description:
  Cloudformation EC2 for Linux

#各種メタデータ一覧
Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          default: "EC2 Configuration"
        Parameters:
          - ImageId
          - InstanceType
          - SubnetId
          - DeviceName
          - VolumeType
          - VolumeSize
          - KeyName
          - SSHLocation
          - HTTPLocation
          - HTTPSLocation
          - MysqlLocation 


    ParameterLabels:
      ImageId:
        default: "ImageId"
      InstanceType:
        default: "InstanceType"
      SubnetId:
        default: "SubnetId"
      DeviceName:
        default: "DeviceName"
      VolumeType:
        default: "VolumeType"
      VolumeSize:
        default: "VolumeSize"
      KeyName:
        default: "KeyName"
      SSHLocation:
        default: "SSHLocation"
      HTTPLocation:
        default: "HTTPLocation"
      HTTPSLocation:
        default: "HTTPSLocation"
      MysqlLocation:
        default: "MysqlLocation"

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  PJPrefix:
    Type: String
    Default: "EC2" 

# AMIイメージは事前に用意したイメージIDを指定
  ImageId:
    Type: String
    Default: "ami-0049cb4d1005fe191"

# インスタンスタイプはt2.microを使用
  InstanceType:
    Type: String
    Default: "t2.micro" 
# サブネットは４つpublic subnet またはprivate subnetを選択する
  SubnetId:
    Type: String
    Default: subnet-09655585fa4f1ddb3
    AllowedValues:
    - subnet-09655585fa4f1ddb3
    - subnet-0b04d42bccacc5e83
    - subnet-0aa2aec1b9dcc3043
    - subnet-0159719dde06b542e

# EBSボリュームのデバイスは/dev/xvdaとする
  DeviceName:
    Type: String
    Default: "/dev/xvda" 
        
# EBSボリュームは汎用SSD(gp2)を使用
  VolumeType:
    Type: String
    Default: "gp2"

# EBSボリュームサイズは8GB
  VolumeSize:
    Type: String
    Default: "8"

#　事前に作成したキーペアを選択する
  KeyName: 
    Description : Name of an existing EC2 KeyPair.
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription : Can contain only ASCII characters.

# SSH接続のセキュリティグループのIPアドレスの範囲を指定する。
  SSHLocation:
      Description: IP address range that can be used to SSH to the EC2 instances
      Type: String
      MinLength: '9'
      MaxLength: '18'
      Default: 0.0.0.0/0
      AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
      ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.

# HTTP接続のセキュリティグループのIPアドレスの範囲を指定する。
  HTTPLocation:
      Description: IP address range that can be used to SSH to the EC2 instances
      Type: String
      MinLength: '9'
      MaxLength: '18'
      Default: 0.0.0.0/0
      AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
      ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.

# HTTPS接続のセキュリティグループのIPアドレスの範囲を指定する。
  HTTPSLocation:
      Description: IP address range that can be used to SSH to the EC2 instances
      Type: String
      MinLength: '9'
      MaxLength: '18'
      Default: 0.0.0.0/0
      AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
      ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.

# MysqlのセキュリティグループのIPアドレスの範囲を指定する。
  MysqlLocation:
      Description: IP address range that can be used to SSH to the EC2 instances
      Type: String
      MinLength: '9'
      MaxLength: '18'
      Default: 0.0.0.0/0
      AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
      ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.


Resources:
# ------------------------------------------------------------#
#  EC2Instance Linux
# ------------------------------------------------------------#
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: !Ref ImageId
      InstanceType: !Ref InstanceType
      NetworkInterfaces:
        - AssociatePublicIpAddress: "true"
          DeviceIndex: "0"
          SubnetId: !Ref SubnetId
          GroupSet:
            - !Ref EC2SecurityGroup

# 起動時にApache HTTP Serverをインストール後、index.htmlに"Hello World from user data"を出力させる。
      UserData:
        Fn::Base64: |-
          #!/bin/bash
          sudo yum update -y
          sudo yum install -y httpd
          sudo systemctl start httpd
          sudo systemctl enable httpd
          sudo echo "Hello World from user data" > /var/www/html/index.html

      BlockDeviceMappings:
        - DeviceName: !Ref DeviceName
          Ebs:
            VolumeType: !Ref VolumeType
            VolumeSize: !Ref VolumeSize  
      Tags: 
        - Key: "Name"
          Value: !Ref PJPrefix
      KeyName: !Ref KeyName

# ------------------------------------------------------------#
#  SecurityGroup for EC2 (Linux)
# ------------------------------------------------------------#
  EC2SecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "CloudFormation-vpc" }   #事前に作成したVPCを指定
      GroupDescription: "-"
      Tags:
        - Key: "Name"
          Value: !Sub "${PJPrefix}-sg"
# インバウントルール
# Mysql/Auroraの接続を許可
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          CidrIp: !Ref MysqlLocation
# SSH接続を許可
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHLocation
# HTTP通信の接続を許可
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref HTTPLocation
# HTTPS通信の接続を許可
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref HTTPSLocation

```

#スタック作成後の動作確認

１、EC2のコンソールにアクセスし、セキュリティグループの項目へ移動後、テンプレートで指定したセキュリティグループが作成されていることを確認する。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/96e915b2-757e-51c9-7471-77c83739f2c3.png)

２、作成したセキュリティグループのインバウントルールがテンプレート通りに設定されていることを確認する。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/ac771dff-2a3d-d681-d446-623480276e3d.png)

３、インスタンスの項目へ移動し、テンプレートで指定したEC2インスタンスが作成されていることを確認する。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/fda89067-0267-6f58-a454-8df369798b36.png)

４、ネットワーキングのパブリックIPv4アドレスをコピーする。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/e0e01c23-05c1-7cf2-2067-aa048ed0a8d2.png)

５、Tera Tarmを開き、ホストに先ほどコピーしたパブリックIPv4アドレスを貼り付ける。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/efdf08b6-ef3b-e6e5-326b-ebe574b1553c.png)

６、ユーザ名を入力し、RSA/DSA/ECDSA/ED25519鍵を使うを選択後、秘密鍵(K)の横にある「...」をクリックする。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/aaf0a95c-ce52-f4a5-2e6a-503334e185e3.png)

７、事前に選択した、秘密鍵を指定して「開く」をクリックする。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/e596ebce-2671-ebf7-abb3-158581f59557.png)

８、選択したらOKをクリックする。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/92984f0f-696c-e290-249c-5eb9a4b34d52.png)

９、作成したEC2インスタンスにSSH接続出来たことを確認する。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/3ee05713-aa5f-7b66-9068-d4499b8ceba0.png)

１０、ルートユーザにスイッチする。

```
$ sudo su
```

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/dc69cf86-0dd4-8d4c-7fa6-882f700fc8d0.png)

１１、下記コマンドを入力し、Apacheが起動していることを確認する。

```
# systemctl is-active httpd
```
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/69e4e480-41ae-c9ee-e850-21eb65898fee.png)

１２、任意のブラウザを開き、作成したEC2インスタンスのパブリックIPv4アドレスをURLに指定してHTTP経由でアクセスし、"Hello World from user data"が表示されていることを確認する。
URL：http://<パブリックIPv4アドレス>
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1408197/2ff70a72-a33f-cc18-80c7-42856c1761de.png)

#終わりに
CloudFormaitonを使ってEC2インスタンスを構築し、起動時にApacheをインストールする手順を説明しました。
今回はParametersのボリュームを増やし、Ref関数によってResousesの記載をシンプルにさせました。
他のAWSリソースでコード化が実現出来たら随時Qiitaに投稿します♪