IaC: Packer、Terraform、Ansible で AWS EC2 をプロビジョニングする

IaC: Packer、Terraform、Ansible で AWS EC2 をプロビジョニングする

以下を実施する手順をまとめます。(なお本記事のローカルの作業環境は Mac です)

  1. Node.js アプリを作成する。Node.js アプリは Systemd のサービスとして登録し、起動するための Ansible の Playbook も用意する。
  2. Packer を使って AMI を作成する。インストール処理は Ansible で実施する。AMI には Ansible と Node.js をインストールする。
  3. Terraform を使って AMI から EC2 インスタンスを起動する。インスタンス起動時の Cloud-init で GitHub から自分のコードを clone する。その後 Ansible を実行してアプリを実行する。

本記事の手順を実施すると、最終的に以下のようなファイル構成になります。

my-iac/
├── 1_app/
│   ├── main.js
│   ├── package.json
│   └── site.yml
├── 2_terraform-vpc/
│   ├── main.tf
│   └── output.json
├── 3_terraform-iam/
│   ├── main.tf
│   └── output.json
├── 4_packer-ami/
│   ├── main.pkr.hcl
│   ├── manifest.json
│   └── site.yml
├── 5_terraform-ec2/
│   ├── cloud-init.yml
│   └── main.tf
├── main.js      # 1_app/main.js のコピー
├── package.json # 1_app/package.json のコピー
└── site.yml     # 1_app/site.yml のコピー

0-1. 事前準備 - ツールのインストール #

必要なツールをインストールしておきましょう。ここではすべて Homebrew でインストールします。

# AWS CLI
brew install awscli

# AWS SSM Session Manager Plugin
brew install --cask session-manager-plugin

# Packer
brew tap hashicorp/tap
brew install hashicorp/tap/packer

# Terraform
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

インストールできたことのチェックとして、各コマンドを実行して成功することを確認します。

aws --version
session-manager-plugin --version
packer --version
terraform --version

0-2. 事前準備 - AWS の環境準備 #

0-2-1. AWS CLI 用 IAM ユーザの作成とアクセスキーの取得 #

IAM > Users からユーザを作成します。ここでは my-aws-cli-user という名前でユーザを作成しました。AdministratorAccess のポリシーをアタッチしています。

AWS Console - IAM 1

作成したユーザのアクセスキーを発行します。(以下のアクセスキーはすでに削除済みです)

AWS Console - IAM 2

発行した内容を使って aws configure を実行し、AWS CLI の設定を行います。

AWS Access Key ID [****************FFC4]: AKIAUB35HC3KPZGRHBXA
AWS Secret Access Key [****************iEe8]: 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
Default region name [None]:
Default output format [None]:

0-2-2. Terraform 用 S3 バケットの作成 #

Amazon S3 ページにて、Terraform のリモートステート用のバケットを作成します。

ここでは my-good-terraform-remote-state-bucket という名前でバケットを作成しました。

AWS Console - S3

補足:AWS CLI でやるならこちらのコマンドです
aws s3 mb s3://my-good-terraform-remote-state-bucket --region ap-northeast-1

0-2-3. SSM Parameter Store に GitHub の情報を登録 #

GitHub で Personal Access Token を発行します。repo 権限を付与しておきます。

AWS Systems Manager > Parameter Store から、発行したアクセストークンと、さらに GitHub のユーザ名を登録します。

AWS Console - S3

補足:AWS CLI でやるならこちらのコマンドです
aws ssm put-parameter \
  --region "ap-northeast-1" \
  --name "/my-parameter/github/user-name" \
  --value "MY_GITHUB_USER_NAME" \
  --type "String"

aws ssm put-parameter \
  --region "ap-northeast-1" \
  --name "/my-parameter/github/access-token" \
  --value "MY_GITHUB_PERSONAL_ACCESS_TOKEN" \
  --type "SecureString"

1. アプリケーションの準備 #

今回デプロイするアプリケーションとして、Node.js の簡易なスクリプトを用意します。実行するとずっと動き続け、30 秒ごとにログファイルにタイムスタンプを書き込むだけのシンプルなスクリプトです。

また、EC2 起動時に実行される Ansible の Playbook も用意します。この Playbook は EC2 起動時の cloud-init から実行されることになります。Playbook のなかでアプリを Systemd のサービスとして登録し、起動します。

以下のディレクトリとファイルを用意します。

my-iac/
└── 1_app/
    ├── main.js
    ├── package.json
    └── site.yml
package.json
{
  "type": "module"
}
main.js
import fs from "fs";

const logFilePath = "./my-app.log";

function addLog() {
  const now = new Date().toISOString();
  fs.appendFileSync(logFilePath, `${now}\n`, "utf8");
  console.log(`Log added: ${now}`);
}

addLog();
setInterval(addLog, 30_000);
site.yml
---
- hosts: localhost
  connection: local
  become: true
  gather_facts: false

  vars:
    app_group: my-app-group
    app_user: my-app-user
    app_service_name: my-app
    exec_file_name: main.js
    exec_file_path: "{{ playbook_dir }}/{{ exec_file_name }}"

  tasks:
    - name: Create app system group
      group:
        name: "{{ app_group }}"
        system: true

    - name: Create app system user
      user:
        name: "{{ app_user }}"
        group: "{{ app_group }}"
        system: true
        shell: /usr/sbin/nologin
        create_home: true

    - name: Change ownership of app directory
      file:
        path: "{{ playbook_dir }}"
        owner: "{{ app_user }}"
        group: "{{ app_group }}"
        recurse: true

    - name: Create systemd unit for the app
      copy:
        dest: "/etc/systemd/system/{{ app_service_name }}.service"
        mode: "0644"
        content: |
          [Unit]
          Description=My App
          After=network.target

          [Service]
          ExecStart=/usr/bin/env node {{ exec_file_path }}
          WorkingDirectory={{ playbook_dir }}
          User={{ app_user }}
          Group={{ app_group }}
          Restart=always
          RestartSec=2
          StandardOutput=journal
          StandardError=journal

          [Install]
          WantedBy=multi-user.target
      notify: Reload systemd and restart my-app

    - name: Enable and start service
      systemd:
        name: "{{ app_service_name }}"
        enabled: true
        state: started

  handlers:
    - name: Reload systemd and restart my-app
      systemd:
        name: "{{ app_service_name }}"
        state: restarted
        daemon_reload: true

ここまでファイルを作成したら、それらをプロジェクトのルートディレクトリ直下にコピーします。

my-iac/
├── 1_app/
│   ├── main.js
│   ├── package.json
│   └── site.yml
├── main.js      # 1_app/main.js のコピー
├── package.json # 1_app/package.json のコピー
└── site.yml     # 1_app/site.yml のコピー

そして GitHub にプライベートリポジトリを作成し、そこに push してください。

ルート直下にコピーした理由について補足しておきます。本来であればアプリケーションのコードと IaC のコードは別リポジトリにすることが多いと思いますが、今回は簡略化のために同じディレクトリで開発します。

後述の IaC 定義のなかでは GitHub から clone する処理がありますが、そこではアプリケーションのコード単独のリポジトリとして管理されている想定で作っていて、プロジェクトのディレクトリ直下に site.yml と main.js というエントリポイントがあることを前提にしています。

今回はアプリケーション単独のリポジトリという状況を擬似的に再現するためにルート直下にコピーしています。

2. Terraform で VPC、サブネット、セキュリティグループ を作成する #

VPC、サブネット、セキュリティグループを作成します。

以下のディレクトリとファイルを用意します。

my-iac/
└── 2_terraform-vpc/
    └── main.tf
main.tf
################################################################################
# Root configurations
################################################################################

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    region = "ap-northeast-1"
    bucket = "my-good-terraform-remote-state-bucket" # ✅ TODO: Set the actual value before running
    key    = "vpc/terraform.tfstate"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

################################################################################
# Definitions - VPC, Subnet, Security Group
################################################################################

resource "aws_vpc" "this" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true
}

resource "aws_internet_gateway" "this" {
  vpc_id = aws_vpc.this.id
}

resource "aws_subnet" "this" {
  vpc_id                  = aws_vpc.this.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true
}

resource "aws_route_table" "this" {
  vpc_id = aws_vpc.this.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.this.id
  }
}

resource "aws_route_table_association" "this" {
  subnet_id      = aws_subnet.this.id
  route_table_id = aws_route_table.this.id
}

resource "aws_security_group" "this" {
  vpc_id = aws_vpc.this.id

  ###############################
  # Prohibit all inbound traffic
  ###############################
  # ingress {
  # }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

################################################################################
# Outputs of the results
################################################################################

output "subnet_id" {
  value = aws_subnet.this.id
}

output "security_group_id" {
  value = aws_security_group.this.id
}

ファイルを用意したら、以下のコマンドを順に実行してリソースを作成します。

  1. cd 2_terraform-vpc/
  2. 初期化:terraform init
  3. 検証:terraform plan
  4. 実行:terraform apply -auto-approve
  5. 実行結果確認:terraform output -json > output.json

今回 output.json には以下のような内容が出力されました(必要部分のみ抜粋)。値は人によって異なります。以降に作成する定義で利用します。

{
  "security_group_id": {
    "value": "sg-004a816e59eb88611"
  },
  "subnet_id": {
    "value": "subnet-059327c2ea7fc6263"
  }
}

3. Terraform で IAM を作成する #

次に EC2 インスタンスで使用するための IAM ロールを作成します。

以下のディレクトリとファイルを用意します。

my-iac/
└── 3_terraform-iam/
    └── main.tf
main.tf
################################################################################
# Root configurations
################################################################################

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    region = "ap-northeast-1"
    bucket = "my-good-terraform-remote-state-bucket" # ✅ TODO: Set the actual value before running
    key    = "iam/terraform.tfstate"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

################################################################################
# Definitions - IAM
################################################################################

###################
# IAM Role for EC2
###################
data "aws_iam_policy_document" "ec2" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "ec2" {
  assume_role_policy = data.aws_iam_policy_document.ec2.json
}

############################
# Instance Profile for EC2
############################
resource "aws_iam_instance_profile" "ec2" {
  role = aws_iam_role.ec2.name
}

################################################
# Attach SSM Session Manager Policy to IAM Role
################################################
resource "aws_iam_role_policy_attachment" "ssm_manager" {
  role       = aws_iam_role.ec2.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

##########################################
# Attach SSM Parameter Policy to IAM Role
##########################################
data "aws_kms_key" "ssm_parameter" {
  key_id = "alias/aws/ssm"
}

data "aws_iam_policy_document" "ssm_parameter" {
  statement {
    sid = "ReadAllParameters"
    actions = [
      "ssm:GetParameter",
      "ssm:GetParameters",
      "ssm:GetParametersByPath",
    ]
    resources = ["*"]
  }

  statement {
    sid       = "DecryptSecureStringWithDefaultAlias"
    actions   = ["kms:Decrypt"]
    resources = [data.aws_kms_key.ssm_parameter.arn]
  }
}

resource "aws_iam_policy" "ssm_parameter" {
  policy = data.aws_iam_policy_document.ssm_parameter.json
}

resource "aws_iam_role_policy_attachment" "ssm_parameter" {
  role       = aws_iam_role.ec2.name
  policy_arn = aws_iam_policy.ssm_parameter.arn
}

################################################################################
# Outputs of the results
################################################################################

output "iam_instance_profile" {
  value = aws_iam_instance_profile.ec2.name
}

ファイルを用意したら、以下のコマンドを順に実行してリソースを作成します。

  1. cd 3_terraform-iam/
  2. 初期化:terraform init
  3. 検証:terraform plan
  4. 実行:terraform apply -auto-approve
  5. 実行結果確認:terraform output -json > output.json

今回 output.json には以下のような内容が出力されました(必要部分のみ抜粋)。値は人によって異なります。以降に作成する定義で利用します。

{
  "iam_instance_profile": {
    "value": "terraform-20250925014517689700000003"
  }
}

4. Packer で AMI を作成する #

Packer を使って AMI を作成します。インストール処理は Ansible で実施します。AMI には Ansible と Node.js をインストールします。

Packer 定義を記述する前に、ベースとなる AMI の ID を調べておきます。ここでは Amazon Linux の最新の AMI を使うことにします。

ローカルで AWS CLI コマンドを以下のように実行して調べることができます。(または AWS コンソールから AMI の一覧を確認できます。EC2 > Images > AMI Catalog)

aws ec2 describe-images \
  --region ap-northeast-1 \
  --owners amazon \
  --filters "Name=name,Values=al*-ami-*" "Name=architecture,Values=x86_64" \
  --query 'sort_by(Images, &CreationDate)[-1]' \
  --output table

この記事を書いている時点では以下のような結果が得られました。AMI ID は ami-0925d63721690c5b8 だとわかります。

---------------------------------------------------------------------------------------
|                                   DescribeImages                                    |
+---------------------+---------------------------------------------------------------+
|  Architecture       |  x86_64                                                       |
|  BootMode           |  uefi-preferred                                               |
|  CreationDate       |  2025-09-16T21:01:07.000Z                                     |
|  DeprecationTime    |  2027-09-16T21:01:07.000Z                                     |
|  Description        |  Amazon Linux AMI 2023.0.20250916 x86_64 ECS HVM EBS          |
|  EnaSupport         |  True                                                         |
|  FreeTierEligible   |  True                                                         |
|  Hypervisor         |  xen                                                          |
|  ImageId            |  ami-0925d63721690c5b8                                        |
|  ImageLocation      |  amazon/al2023-ami-ecs-hvm-2023.0.20250916-kernel-6.1-x86_64  |
|  ImageOwnerAlias    |  amazon                                                       |
|  ImageType          |  machine                                                      |
|  ImdsSupport        |  v2.0                                                         |
|  Name               |  al2023-ami-ecs-hvm-2023.0.20250916-kernel-6.1-x86_64         |
|  OwnerId            |  591542846629                                                 |
|  PlatformDetails    |  Linux/UNIX                                                   |
|  Public             |  True                                                         |
|  RootDeviceName     |  /dev/xvda                                                    |
|  RootDeviceType     |  ebs                                                          |
|  SourceImageId      |  ami-03d7a4be0d871c897                                        |
|  SourceImageRegion  |  us-west-1                                                    |
|  SriovNetSupport    |  simple                                                       |
|  State              |  available                                                    |
|  UsageOperation     |  RunInstances                                                 |
|  VirtualizationType |  hvm                                                          |
+---------------------+---------------------------------------------------------------+
||                                BlockDeviceMappings                                ||
|+------------------------------------------+----------------------------------------+|
||  DeviceName                              |  /dev/xvda                             ||
|+------------------------------------------+----------------------------------------+|
|||                                       Ebs                                       |||
||+-------------------------------------+-------------------------------------------+||
|||  DeleteOnTermination                |  True                                     |||
|||  Encrypted                          |  False                                    |||
|||  Iops                               |  3000                                     |||
|||  SnapshotId                         |  snap-0857677d6f9f45184                   |||
|||  Throughput                         |  125                                      |||
|||  VolumeSize                         |  30                                       |||
|||  VolumeType                         |  gp3                                      |||
||+-------------------------------------+-------------------------------------------+||

以下のディレクトリとファイルを用意します。

my-iac/
└── 4_packer-ami/
    ├── main.pkr.hcl
    └── site.yml
main.pkr.hcl

locals の部分は各自の値で置き換えてください。

################################################################################
# Root Configurations
################################################################################

packer {
  required_version = ">= 1.9.0"

  required_plugins {
    amazon = {
      source  = "github.com/hashicorp/amazon"
      version = ">= 1.3.0"
    }
    ansible = {
      source  = "github.com/hashicorp/ansible"
      version = ">= 1.1.0"
    }
  }
}

################################################################################
# Required variables
################################################################################

locals {
  subnet_id            = "subnet-059327c2ea7fc6263"             # ✅ TODO: Set the actual value before running
  security_group_id    = "sg-004a816e59eb88611"                 # ✅ TODO: Set the actual value before running
  iam_instance_profile = "terraform-20250925014517689700000003" # ✅ TODO: Set the actual value before running
}

################################################################################
# Definitions - AMI
################################################################################

source "amazon-ebs" "this" {
  source_ami    = "ami-0925d63721690c5b8" # ✅ TODO: Update if necessary
  region        = "ap-northeast-1"
  instance_type = "t3.micro"
  ssh_username  = "ec2-user"
  ami_name      = "my-ami-{{timestamp}}"

  force_deregister      =  true
  force_delete_snapshot = true

  subnet_id            = local.subnet_id
  security_group_id    = local.security_group_id
  associate_public_ip_address = true
  ssh_interface        = "session_manager"
  iam_instance_profile = local.iam_instance_profile
}

build {
  sources = ["source.amazon-ebs.this"]

  # 1. Install Ansible
  provisioner "shell" {
    execute_command = "sudo -E sh -c '{{ .Vars }} {{ .Path }}'" # Run as root
    inline = [
      "dnf -y update",
      "dnf -y install ansible-core",
      "ansible --version"
    ]
  }

  # 2. Run Ansible Playbook
  provisioner "ansible-local" {
    playbook_file = "./site.yml"
  }

  # 3. Output results to a file
  post-processor "manifest" {
    output = "manifest.json"
  }
}
site.yml
- hosts: localhost
  connection: local
  become: true
  gather_facts: false

  tasks:
    - name: Install AWS CLI
      block:
        - ansible.builtin.dnf:
            name: awscli
            state: present
        - ansible.builtin.command: aws --version
          register: aws_cli_result
        - ansible.builtin.debug:
            msg: "AWS CLI version: {{ aws_cli_result.stdout }}"

    - name: Install Git
      block:
        - ansible.builtin.dnf:
            name: git
            state: present
        - ansible.builtin.command: git --version
          register: git_result
        - ansible.builtin.debug:
            msg: "Git version: {{ git_result.stdout }}"

    - name: Install Node.js
      block:
        - ansible.builtin.dnf:
            name: nodejs
            state: present
        - ansible.builtin.command: node --version
          register: node_result
        - ansible.builtin.debug:
            msg: "Node.js version: {{ node_result.stdout }}"

ファイルを用意したら、以下のコマンドを順に実行してリソースを作成します。

  1. cd 4_packer-ami/
  2. 初期化:packer init .
  3. 検証:packer validate .
  4. 実行:packer build .

今回 manifest.json には以下のような内容が出力されました(必要部分のみ抜粋)。作成された AMI の ID が分かります。値は人によって異なります。以降に作成する定義で利用します。

{
  "builds": [
    {
      "artifact_id": "ap-northeast-1:ami-098e641373fce0096"
    }
  ]
}

5. Terraform で EC2 インスタンスを作成する #

Terraform を使って、作成した AMI から EC2 インスタンスを起動します。インスタンス起動時の Cloud-init で GitHub から自分のコードを clone します。その後 Ansible を実行します。ここで実行している Ansible の Playbook は Node.js アプリ作成時に用意したもの(Systemd のサービスとしてアプリを登録し、起動するもの)です。

以下のディレクトリとファイルを用意します。

my-iac/
└── 5_terraform-ec2/
    ├── cloud-init.yml
    └── main.tf
main.tf

locals の部分は各自の値で置き換えてください。

################################################################################
# Root configurations
################################################################################

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    region = "ap-northeast-1"
    bucket = "my-good-terraform-remote-state-bucket" # ✅ TODO: Set the actual value before running
    key    = "ec2/terraform.tfstate"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

################################################################################
# Required variables
################################################################################

locals {
  ami_id               = "ami-098e641373fce0096"                # ✅ TODO: Set the actual value before running
  subnet_id            = "subnet-059327c2ea7fc6263"             # ✅ TODO: Set the actual value before running
  security_group_id    = "sg-004a816e59eb88611"                 # ✅ TODO: Set the actual value before running
  iam_instance_profile = "terraform-20250925014517689700000003" # ✅ TODO: Set the actual value before running
}

################################################################################
# Definitions - EC2
################################################################################

resource "aws_instance" "this" {
  ami           = local.ami_id
  instance_type = "t3.micro"

  subnet_id              = local.subnet_id
  vpc_security_group_ids = [local.security_group_id]

  associate_public_ip_address = true
  iam_instance_profile        = local.iam_instance_profile

  user_data                   = file("${path.module}/cloud-init.yml")
  user_data_replace_on_change = true
}

################################################################################
# Outputs of the results
################################################################################

output "aws_instance" {
  value = aws_instance.this.id
}
cloud-init.yml

設定値定義の部分は各自の値で置き換えてください。

#cloud-config
package_update: false
package_upgrade: false
packages: []

write_files:
  - path: /root/my-bootstrap.sh
    permissions: "0755"
    owner: root:root
    content: |
      #!/usr/bin/env bash
      set -euo pipefail

      ##########################################################################
      SSM_REGION="ap-northeast-1"
      SSM_PARAMETER_STORE_KEY_GITHUB_USER_NAME="/my-parameter/github/user-name"       # ✅ TODO: Set the actual value before running
      SSM_PARAMETER_STORE_KEY_GITHUB_ACCESS_TOKEN="/my-parameter/github/access-token" # ✅ TODO: Set the actual value before running
      GITHUB_ORGANIZATION_NAME="my-org"                                               # ✅ TODO: Set the actual value before running
      GITHUB_REPOSITORY_NAME="my-repo"                                                # ✅ TODO: Set the actual value before running
      PLAYBOOK_FILE_PATH="site.yml"                                                   # ✅ TODO: Set the actual value before running
      ##########################################################################

      # Create directory
      CHECKOUT_DIRECTORY="/opt/my-app"
      rm -rf "${CHECKOUT_DIRECTORY}"
      mkdir -p "${CHECKOUT_DIRECTORY}"

      # Fetch GitHub credentials from SSM Parameter Store
      # Use --with-decryption option for SecureString
      GITHUB_USER_NAME="$(aws ssm get-parameter --region "${SSM_REGION}" --name "${SSM_PARAMETER_STORE_KEY_GITHUB_USER_NAME}" --query 'Parameter.Value' --output text)"
      GITHUB_ACCESS_TOKEN="$(aws ssm get-parameter --region "${SSM_REGION}" --with-decryption --name "${SSM_PARAMETER_STORE_KEY_GITHUB_ACCESS_TOKEN}" --query 'Parameter.Value' --output text)"

      # Clone repository
      cd "${CHECKOUT_DIRECTORY}"
      GITHUB_REPOSITORY_URL_WITH_CREDENTIAL="https://${GITHUB_USER_NAME}:${GITHUB_ACCESS_TOKEN}@github.com/${GITHUB_ORGANIZATION_NAME}/${GITHUB_REPOSITORY_NAME}.git"
      git clone --depth=1 "${GITHUB_REPOSITORY_URL_WITH_CREDENTIAL}" .

      # Run Ansible
      cd "${CHECKOUT_DIRECTORY}"
      ansible-playbook "${PLAYBOOK_FILE_PATH}"

runcmd:
  - [bash, -lc, "/root/my-bootstrap.sh >> /var/log/my-bootstrap.log 2>&1"]

ファイルを用意したら、以下のコマンドを順に実行してリソースを作成します。

  1. cd 5_terraform-ec2/
  2. 初期化:terraform init
  3. 検証:terraform plan
  4. 実行:terraform apply -auto-approve
  5. 実行結果確認:terraform output

最終的に以下のような内容が出力されます。作成された EC2 インスタンスの ID です。

aws_instance = "i-0b1d05f12fdc1e6a0"

これで作業は完了です。では結果を確認しましょう。

AWS コンソールの EC2 ページから、作成されたインスタンスを確認します。

  1. 先ほど表示された ID のインスタンスが起動していることを確認します。
  2. インスタンスのページ(EC2 > Instances > i-0b1d05f12fdc1e6a0)を開き、「Connect」ボタンを押します。
  3. 「Session Manager」タブを選択し、「Connect」ボタンを押して接続します。
  4. インスタンスにログインできたら、root ユーザに切り替えます:sudo su - root
  5. サービスの起動状態を確認します:systemctl status my-app
  6. 少し時間を置いてからログファイルを確認します:cat /opt/my-app/my-app.log

定期的にログが書き込まれていれば成功です。

99. 後片付け #

今回作成したリソースをすべて削除する手順を示します。

EC2 インスタンスの削除 #

まずは EC2 インスタンスを削除します。

cd 5_terraform-ec2/
terraform destroy

削除してよいか確認されますので yes と答えます。

AMI の削除 #

AMI を削除します。Packer には AMI を削除するコマンドがないため手動で削除します。AWS コンソールの EC2 > AMIs から Deregister しましょう。このとき、AMI に紐づくスナップショットも削除するかどうか聞かれますので、あわせて削除しておきましょう。

IAM の削除 #

IAM ロールを削除します。

cd 3_terraform-iam/
terraform destroy

削除してよいか確認されますので yes と答えます。

VPC、サブネット、セキュリティグループの削除 #

VPC、サブネット、セキュリティグループを削除します。

cd 2_terraform-vpc/
terraform destroy

削除してよいか確認されますので yes と答えます。

SSM Parameter Store、S3 バケット、AWS CLI 用の IAM と GitHub のリポジトリとアクセストークンの削除 #

最後に、SSM Parameter Store に登録したパラメータ、S3 バケット、AWS CLI 用の IAM ユーザと、GitHub のリポジトリとアクセストークンを削除します。

AWS コンソールや GitHub の画面から手動で削除しましょう。