Closed17

TerraformでAWS EC2を作成してみる

Tsuyoshi WatanabeTsuyoshi Watanabe

AWSプロファイル(設定と認証情報)の設定

参考

https://dev.classmethod.jp/articles/lim-cli-profile/
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html

IAMユーザーを作成

した

新規プロファイルを登録

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

確認

$ cat ~/.aws/config
...
[profile [profile name]]
region = ap-northeast-1
$ cat ~/.aws/credentials
...
[[profile name]]
aws_access_key_id = *****
aws_secret_access_key = *****

ok

Tsuyoshi WatanabeTsuyoshi Watanabe

terraformのインストール

インストールできるバージョンの確認

$ tfenv list-remote
1.7.0-rc1
1.7.0-beta2
1.7.0-beta1
1.7.0-alpha20231130
1.7.0-alpha20231108
1.7.0-alpha20231025
1.6.6
1.6.5
...

1.6.6をインストールする

$ tfenv install 1.6.6

確認

$ tfenv list
  1.6.6
* 1.3.2
  1.3.1

使用するバージョンを切り替える

$ tfenv use 1.6.6

確認

$ terraform --version
Terraform v1.6.6
on darwin_amd64

ok

Tsuyoshi WatanabeTsuyoshi Watanabe

ここで、Terraformのコマンドをざっと見る

$ terraform --help
...
Main commands:
  init          Prepare your working directory for other commands
  validate      Check whether the configuration is valid
  plan          Show changes required by the current configuration
  apply         Create or update infrastructure
  destroy       Destroy previously-created infrastructure
...
Tsuyoshi WatanabeTsuyoshi Watanabe

versions.tfを作成

$ touch versions.tf
versions.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.49.0"
    }
  }

  required_version = "~> 1.6.0"
}

provider "aws" {
    profile = var.profile
}

インプット変数の作成

$ touch variables.tf
variables.tf
variable "profile" {
    type = string
}

variable "project" {
  type = string
}

variable "environment" {
  type = string
}

variable "vpc_cidr" {
  type        = string
  description = "vpc cidrblock"
}

variable "subnet_cidr" {
  type        = string
  description = "public subnet cidr"
}

.tfvarsファイルの作成

$ touch terraform.tfvars
terraform.tfvars
project = "create-EC2"

environment = "dev"

vpc_cidr = "10.0.0.0/16"

subnet_cidr = "10.0.1.0/24"

profile = "[profile name]"

ここで、CIDRとは?

https://zenn.dev/dubianhaozhi/scraps/b362e26fdfc05d

Tsuyoshi WatanabeTsuyoshi Watanabe

VPCとサブネットの作成

$ touch network.tf
network.tf
# VPC
resource "aws_vpc" "main" {
  cidr_block                       = var.vpc_cidr
  instance_tenancy                 = "default"
  assign_generated_ipv6_cidr_block = false

  tags = {
    Name    = "${var.project}-${var.environment}-vpc"
    Project = var.project
    Env     = var.environment
  }
}

# Subnet
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  availability_zone       = "ap-northeast-1a"
  cidr_block              = var.subnet_cidr
  map_public_ip_on_launch = true

  tags = {
    Name    = "${var.project}-${var.environment}-public-subnet"
    Project = var.project
    Env     = var.environment
    Type    = "public"
  }
}
Tsuyoshi WatanabeTsuyoshi Watanabe

プレビューする

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_subnet.public will be created
  + resource "aws_subnet" "public" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "ap-northeast-1a"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.1.0/24"
      + 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                                           = {
          + "Env"     = "dev"
          + "Name"    = "create-EC2-dev-public-subnet"
          + "Project" = "create-EC2"
          + "Type"    = "public"
        }
      + tags_all                                       = {
          + "Env"     = "dev"
          + "Name"    = "create-EC2-dev-public-subnet"
          + "Project" = "create-EC2"
          + "Type"    = "public"
        }
      + vpc_id                                         = (known after apply)
    }

  # aws_vpc.main will be created
  + resource "aws_vpc" "main" {
      + arn                                  = (known after apply)
      + assign_generated_ipv6_cidr_block     = false
      + cidr_block                           = "10.0.0.0/16"
      + 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_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + 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                                 = {
          + "Env"     = "dev"
          + "Name"    = "create-EC2-dev-vpc"
          + "Project" = "create-EC2"
        }
      + tags_all                             = {
          + "Env"     = "dev"
          + "Name"    = "create-EC2-dev-vpc"
          + "Project" = "create-EC2"
        }
    }

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

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
Tsuyoshi WatanabeTsuyoshi Watanabe

デプロイする

$ terraform apply
...
aws_vpc.main: Creating...
aws_vpc.main: Creation complete after 1s [id=vpc-***]
aws_subnet.public: Creating...
aws_subnet.public: Still creating... [10s elapsed]
aws_subnet.public: Creation complete after 11s [id=subnet-***]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

成功!

確認する

vpcできてる

subnetできてる

ok

Tsuyoshi WatanabeTsuyoshi Watanabe

削除してみる

$ terraform destroy
aws_subnet.public: Destroying... [id=subnet-***]
aws_subnet.public: Destruction complete after 1s
aws_vpc.main: Destroying... [id=vpc-***]
aws_vpc.main: Destruction complete after 1s

Destroy complete! Resources: 2 destroyed.

成功!

確認する

AWS consoleで削除されていることが確認できた。

Tsuyoshi WatanabeTsuyoshi Watanabe

ルートテーブルの作成

network.tf
# VPC
...

# Subnet
...

# Route table
resource "aws_route_table" "rtb" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name    = "${var.project}-${var.environment}-rtb"
    Project = var.project
    Env     = var.environment
  }
}

# Route table と subnet の関連付け
resource "aws_route_table_association" "public_rtb" {
  route_table_id = aws_route_table.rtb.id
  subnet_id      = aws_subnet.public.id
}

インターネットゲートウェイの作成

network.tf
# VPC
...

# Subnet
...

# Route table
...

# Route table と subnet の関連付け
...

# Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name    = "${var.project}-${var.environment}-igw"
    Project = var.project
    Env     = var.environment
  }
}

# Route table と IGW の関連付け
resource "aws_route" "rtb_igw_route" {
  route_table_id         = aws_route_table.rtb.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

セキュリティグループの作成

network.tf
# VPC
...

# Subnet
...

# Route table
...

# Route table と subnet の関連付け
...

# Internet Gateway
...

# Route table と IGW の関連付け
...

# Security Group
resource "aws_security_group" "sg" {
  name        = "${var.project}-${var.environment}-sg"
  description = "security group"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

  tags = {
    Name    = "${var.project}-${var.environment}-sg"
    Project = var.project
    Env     = var.environment
  }
}

ここで、AWS EC2周りのリソースについてキャッチアップする

https://zenn.dev/dubianhaozhi/scraps/fbd178bd926ec4

Tsuyoshi WatanabeTsuyoshi Watanabe

EC2の作成

$ touch data.tf
data.tf
data "aws_ami" "amazonlinux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }

  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  filter {
    name   = "block-device-mapping.volume-type"
    values = ["gp2"]
  }
}
$ touch ec2.tf
ec2.tf
resource "aws_instance" "main" {
  ami                         = data.aws_ami.amazonlinux.id
  instance_type               = "t3.micro"
  subnet_id                   = aws_subnet.public.id
  associate_public_ip_address = true
  vpc_security_group_ids      = [aws_security_group.sg.id]

  tags = {
    Name    = "${var.project}-${var.environment}-ec2"
    Project = var.project
    Env     = var.environment
  }
}
Tsuyoshi WatanabeTsuyoshi Watanabe

いざデプロイ!

プレビュー

$ terraform plan
...
  # aws_instance.main will be created
  + resource "aws_instance" "main" {
...
  # aws_internet_gateway.igw will be created
  + resource "aws_internet_gateway" "igw" {
...
  # aws_route.rtb_igw_route will be created
  + resource "aws_route" "rtb_igw_route" {
...
  # aws_route_table.rtb will be created
  + resource "aws_route_table" "rtb" {
...
  # aws_route_table_association.public_rtb will be created
  + resource "aws_route_table_association" "public_rtb" {
...
  # aws_security_group.sg will be created
  + resource "aws_security_group" "sg" {
...
  # aws_subnet.public will be created
  + resource "aws_subnet" "public" {
...
  # aws_vpc.main will be created
  + resource "aws_vpc" "main" {
...
Plan: 8 to add, 0 to change, 0 to destroy.

実行

$ terraform apply
...
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.

確認

AWS consoleで確認できた

AWS consoleから接続もできた

yeah!

削除

$ terraform destroy
...
Destroy complete! Resources: 8 destroyed.

確認

AWS consoleで削除されてることが確認できた

このスクラップは4ヶ月前にクローズされました