Terraformを使ってAWSにEC2をデプロイしてみる

Terraformを使ってAWSにEC2をデプロイしてみる

PublicサブネットにEC2をデプロイするTeraformのコードになります。

Terraformとは

簡単に言えばインフラのコード化。手動で操作することなくインフラ構成を自動で管理できます。インフラの初期プロビジョニング、更新、破棄、いずれもTerraformではコードにより宣言し、実行できる。

環境

OS:Windows10
Terraform version 1.1.8
エディタ: VScode
フォルダPath:C:\terraform\EC
※注意
VScodeにTeraform やAWS CLIをインストール済みになります。

AWSの情報を取得

下記コマンドを実行することでAWS CLIにIAMユーザーで接続するための情報を取得する

$ aws configure
AWS Access Key ID [None]:****************
AWS Secret Access Key [None]:****************
Default region name [None]:ap-northeast-1
Default output format [None]:Json

tfファイルの作成

00_main.tf

Teraformのバージョンなどを記載

# ---------------------------
# Main
# ---------------------------
terraform {
  // Terraform本体に対するバージョン制約
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  #required_version = ">= 0.13.0"
}
// Providerに対するバージョン制約
provider "aws" {
  profile = "default"
  region  = var.aws_region
}

01_vpc.tf

VPCに関する設定を記載

# ---------------------------
# VPC
# ---------------------------

resource "aws_vpc" "Tf_network-test-vpc" {
  cidr_block                       = var.aws_vpc_cidr # VPCに設定したいCIDRを指定
  enable_dns_support               = "true"           # VPC内でDNSによる名前解決を有効化するかを指定
  enable_dns_hostnames             = "true"           # VPC内インスタンスがDNSホスト名を取得するかを指定
  instance_tenancy                 = "default"        # VPC内インスタンスのテナント属性を指定
  assign_generated_ipv6_cidr_block = "false"          # IPv6を有効化するかを指定

  tags = {
    Name = "Tf_network-test-vpc"
  }
}

02_subnet_public.tf

subnetに関する設定を記載

# ---------------------------
# Subnet
# ---------------------------
resource "aws_subnet" "Tf_network-test-public" {
  vpc_id                          = aws_vpc.Tf_network-test-vpc.id # VPCのIDを指定
  cidr_block                      = var.aws_subnet_cidr_public     # サブネットに設定したいCIDRを指定
  assign_ipv6_address_on_creation = "false"                        # IPv6を利用するかどうかを指定
  map_public_ip_on_launch         = "true"                         # VPC内インスタンスにパブリックIPアドレスを付与するかを指定
  availability_zone               = var.aws_region_a               # サブネットが稼働するAZを指定

  tags = {
    Name = "Tf_network-test-public"
  }
}

04_IGW.tf

InternetGatewayに関する設定を記載

#---------------------------
# Internet Gateway
# ---------------------------
resource "aws_internet_gateway" "Tf_igw" {
  vpc_id = aws_vpc.Tf_network-test-vpc.id # VPCのIDを指定

  tags = {
    Name = "Tf_igw"
  }

06_ec2_public.tf

ec2に関する設定を記載

#---------------------------
# EC2
# ---------------------------
resource "aws_instance" "Tf_ec2_public" {
    ami = "ami-005f9685cb30f234b"                     #amiの最新のものを自動で入れたい
    instance_type = var.aws_ec2_instance_type         # 99_terraform.tfvars
    subnet_id = aws_subnet.Tf_network-test-public.id  # 06_ec2_public.tf
    key_name = aws_key_pair.main.key_name             # 81_ec2_key_public.tf

    tags = {
        Name = var.aws_ec2_public_tags_name
    }
}

60_securitygroup.tf

SecurityGroupに関する設定を記載

# ---------------------------
# Security Group
# ---------------------------
resource "aws_security_group" "allow_all" {
  name        = "allow_all"
  description = "Allow all inbound traffic"
  vpc_id      = aws_vpc.Tf_network-test-vpc.id   # 01_vpc.tf
  ingress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

##Security groupを紐づける
resource "aws_network_interface_sg_attachment" "sg_attachment" {
  security_group_id    = aws_security_group.allow_all.id
  network_interface_id = aws_instance.Tf_ec2_public.primary_network_interface_id
}

70_routetable.tf

RouteTableに関する設定を記載

# ---------------------------
# Route Table
# ---------------------------
resource "aws_route_table" "Ft_rt_public" {
  vpc_id = aws_vpc.Tf_network-test-vpc.id # VPCのIDを指定

  # 外部向け通信を可能にするためのルート設定
  route {
    cidr_block = var.aws_igw_cidr
    gateway_id = aws_internet_gateway.Tf_igw.id  # 04_IGW.tf
  }

  tags = {
    Name  = "Ft_rt_public"
  }
}

#ルートテーブルをpublic subnet側にアタッチ
resource "aws_route_table_association" "public_route_table_1a" {
  route_table_id = aws_route_table.Ft_rt_public.id 
  subnet_id = aws_subnet.Tf_network-test-public.id # 02_subnet_public.tf
}

81_ec2_key_public.tf

公開鍵に関する設定を記載

# 公開鍵(OPENSSHフォーマット)
#tls_private_key.pub.public_key_openssh
resource "tls_private_key" "main" {
    algorithm = "RSA"
    rsa_bits = 4096
}

resource "aws_key_pair" "main" {
    key_name = var.aws_ec2_public_key
    public_key = tls_private_key.main.public_key_openssh
    tags = {
        Name = var.aws_ec2_public_key
    }
}

resource "local_file" "keypair_pem" {
    filename = "${path.module}/ec2_public_keypair.pem"
    sensitive_content = tls_private_key.main.private_key_pem
    file_permission = "0600" # 秘密鍵は権限を0600に変更する。
}

resource "local_file" "keypair_pub" {
    filename = "${path.module}/ec2_public_keypair.pub"
    sensitive_content = tls_private_key.main.public_key_openssh
    file_permission = "0600" # 公開鍵も権限を0600に変更する。(必須ではない。)
}

90_variables.tf

変数に関する設定を記載

# ---------------------------
# Variables
# ---------------------------

variable aws_region {}
variable aws_region_a {}
variable aws_vpc_cidr {}
variable aws_subnet_cidr_public {}

variable aws_igw_cidr  {}
variable aws_ec2_public_key  {}
variable aws_ec2_private_key {}

variable aws_ec2_instance_type {}
variable aws_ec2_public_tags_name {}

variable aws_elastic_ip_tags_name {}
variable aws_natgateway_tags_name {}

99_terraform.tfvars

変数などで使用する数値に関する設定を記載

# ---------------------------
# Variables tfvars Faile
# ---------------------------
aws_region              = "us-east-1"
aws_region_a            = "us-east-1a"
aws_vpc_cidr            = "172.16.1.0/24"
aws_subnet_cidr_public  = "172.16.1.0/25"
aws_igw_cidr            = "0.0.0.0/0"

aws_ec2_public_key      = "ec2_public_keypair"

aws_ec2_instance_type   = "t2.micro"
aws_ec2_public_tags_name   = "Tf_ec2_public"


aws_elastic_ip_tags_name   = "Tf_Elastic_IP"
aws_natgateway_tags_name   = "Tf_natgateway"

Terraform の実行

terraform init
terraform plan -var-file .\99_terraform.tfvars
terraform apply -var-file .\99_terraform.tfvars

実行結果

PS C:\terraform\EC> terraform apply -var-file .\99_terraform.tfvars
var.aws_ec2_private_key
  Enter a value: 


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.Tf_ec2_public will be created
  + resource "aws_instance" "Tf_ec2_public" {
      + ami                                  = "ami-005f9685cb30f234b"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = "ec2_public_keypair"
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "Tf_ec2_public"
        }
      + tags_all                             = {
          + "Name" = "Tf_ec2_public"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + vpc_security_group_ids               = (known after apply)

      + capacity_reservation_specification {
          + capacity_reservation_preference = (known after apply)

          + capacity_reservation_target {
              + capacity_reservation_id = (known after apply)
            }
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + enclave_options {
          + enabled = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_internet_gateway.Tf_igw will be created
  + resource "aws_internet_gateway" "Tf_igw" {
      + arn      = (known after apply)
      + id       = (known after apply)
      + owner_id = (known after apply)
      + tags     = {
          + "Name" = "Tf_igw"
        }
      + tags_all = {
          + "Name" = "Tf_igw"
        }
      + vpc_id   = (known after apply)
    }

  # aws_key_pair.main will be created
  + resource "aws_key_pair" "main" {
      + arn             = (known after apply)
      + fingerprint     = (known after apply)
      + id              = (known after apply)
      + key_name        = "ec2_public_keypair"
      + key_name_prefix = (known after apply)
      + key_pair_id     = (known after apply)
      + public_key      = (known after apply)
      + tags            = {
          + "Name" = "ec2_public_keypair"
        }
      + tags_all        = {
          + "Name" = "ec2_public_keypair"
        }
    }

  # aws_network_interface_sg_attachment.sg_attachment will be created
  + resource "aws_network_interface_sg_attachment" "sg_attachment" {
      + id                   = (known after apply)
      + network_interface_id = (known after apply)
      + security_group_id    = (known after apply)
    }

  # aws_route_table.Ft_rt_public will be created
  + resource "aws_route_table" "Ft_rt_public" {
      + arn              = (known after apply)
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = [
          + {
              + carrier_gateway_id         = ""
              + cidr_block                 = "0.0.0.0/0"
              + destination_prefix_list_id = ""
              + egress_only_gateway_id     = ""
              + gateway_id                 = (known after apply)
              + instance_id                = ""
              + ipv6_cidr_block            = ""
              + local_gateway_id           = ""
              + nat_gateway_id             = ""
              + network_interface_id       = ""
              + transit_gateway_id         = ""
              + vpc_endpoint_id            = ""
              + vpc_peering_connection_id  = ""
            },
        ]
      + tags             = {
          + "Name" = "Ft_rt_public"
        }
      + tags_all         = {
          + "Name" = "Ft_rt_public"
        }
      + vpc_id           = (known after apply)
    }

  # aws_route_table_association.public_route_table_1a will be created
  + resource "aws_route_table_association" "public_route_table_1a" {
      + id             = (known after apply)
      + route_table_id = (known after apply)
      + subnet_id      = (known after apply)
    }

  # aws_security_group.allow_all will be created
  + resource "aws_security_group" "allow_all" {
      + arn                    = (known after apply)
      + description            = "Allow all inbound traffic"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 65535
            },
        ]
      + name                   = "allow_all"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags_all               = (known after apply)
      + vpc_id                 = (known after apply)
    }

  # aws_subnet.Tf_network-test-public will be created
  + resource "aws_subnet" "Tf_network-test-public" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "us-east-1a"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "172.16.1.0/25"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = true
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags                                           = {
          + "Name" = "Tf_network-test-public"
        }
      + tags_all                                       = {
          + "Name" = "Tf_network-test-public"
        }
      + vpc_id                                         = (known after apply)
    }

  # aws_vpc.Tf_network-test-vpc will be created
  + resource "aws_vpc" "Tf_network-test-vpc" {
      + arn                                  = (known after apply)
      + assign_generated_ipv6_cidr_block     = false
      + cidr_block                           = "172.16.1.0/24"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_classiclink                   = (known after apply)
      + enable_classiclink_dns_support       = (known after apply)
      + enable_dns_hostnames                 = true
      + enable_dns_support                   = true
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "Tf_network-test-vpc"
        }
      + tags_all                             = {
          + "Name" = "Tf_network-test-vpc"
        }
    }

  # local_file.keypair_pem will be created
  + resource "local_file" "keypair_pem" {
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0600"
      + filename             = "./ec2_public_keypair.pem"
      + id                   = (known after apply)
      + sensitive_content    = (sensitive value)
    }

  # local_file.keypair_pub will be created
  + resource "local_file" "keypair_pub" {
      + content_base64sha256 = (known after apply)
      + content_base64sha512 = (known after apply)
      + content_md5          = (known after apply)
      + content_sha1         = (known after apply)
      + content_sha256       = (known after apply)
      + content_sha512       = (known after apply)
      + directory_permission = "0777"
      + file_permission      = "0600"
      + filename             = "./ec2_public_keypair.pub"
      + id                   = (known after apply)
      + sensitive_content    = (sensitive value)
    }

  # tls_private_key.main will be created
  + resource "tls_private_key" "main" {
      + algorithm                     = "RSA"
      + ecdsa_curve                   = "P224"
      + id                            = (known after apply)
      + private_key_openssh           = (sensitive value)
      + private_key_pem               = (sensitive value)
      + private_key_pem_pkcs8         = (sensitive value)
      + public_key_fingerprint_md5    = (known after apply)
      + public_key_fingerprint_sha256 = (known after apply)
      + public_key_openssh            = (known after apply)
      + public_key_pem                = (known after apply)
      + rsa_bits                      = 4096
    }

Plan: 12 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes 

tls_private_key.main: Creating...
aws_vpc.Tf_network-test-vpc: Creating...
tls_private_key.main: Creation complete after 3s [id=99f9a6adeb50f973553f407600b3fd7b9a0937a5]
aws_key_pair.main: Creating...
local_file.keypair_pub: Creating...
local_file.keypair_pem: Creating...
local_file.keypair_pem: Creation complete after 0s [id=9d78d07cb3fd4bb27ac604856972a20b572d7935]
local_file.keypair_pub: Creation complete after 0s [id=c8ce745cee5cd101c9cd25a2ecf6a6a9db25f1cf]
aws_key_pair.main: Creation complete after 2s [id=ec2_public_keypair]
aws_vpc.Tf_network-test-vpc: Still creating... [10s elapsed]
aws_vpc.Tf_network-test-vpc: Creation complete after 20s [id=vpc-04cc39a441e40b740]
aws_internet_gateway.Tf_igw: Creating...
aws_subnet.Tf_network-test-public: Creating...
aws_security_group.allow_all: Creating...
aws_internet_gateway.Tf_igw: Creation complete after 3s [id=igw-0c72537dc9102d785]
aws_route_table.Ft_rt_public: Creating...
aws_security_group.allow_all: Creation complete after 7s [id=sg-02b0f2ea833e2fdae]
aws_route_table.Ft_rt_public: Creation complete after 5s [id=rtb-0d7b82c07bc31b449]
aws_subnet.Tf_network-test-public: Still creating... [10s elapsed]
aws_subnet.Tf_network-test-public: Creation complete after 14s [id=subnet-0981f127b7fa0bd56]
aws_route_table_association.public_route_table_1a: Creating...
aws_instance.Tf_ec2_public: Creating...
aws_route_table_association.public_route_table_1a: Creation complete after 2s [id=rtbassoc-0edd899988a373485]
aws_instance.Tf_ec2_public: Still creating... [10s elapsed]
aws_instance.Tf_ec2_public: Still creating... [20s elapsed]
aws_instance.Tf_ec2_public: Still creating... [30s elapsed]
aws_instance.Tf_ec2_public: Still creating... [40s elapsed]
aws_instance.Tf_ec2_public: Creation complete after 40s [id=i-0a36677f30ee8e264]
aws_network_interface_sg_attachment.sg_attachment: Creating...
aws_network_interface_sg_attachment.sg_attachment: Creation complete after 3s [id=sg-02b0f2ea833e2fdae_eni-0d5a7e06c166a517b]

Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
PS C:\terraform\EC> 

AWS GUI 実行結果

EC2にログインしてみる

TeraTermを使用し、EC2のPublic IPアドレスを使用します。
またkeyをC:\terraform\EC以下のec2_public_keypair.pemを使用してEC2にログインします。

無事ログインできました。