mito’s blog

IT技術メインの雑記。思い立ったが吉日。

Terraformに入門、AWS EC2でインスタンスを立てた

この記事は、Terraform Advent Calendar 2021 23日目のエントリです。


はじめに

Terraformは名前だけ知ってました。なお、Windows端末で立てていきます。


まとめ

Terraformでガワを作って、Ansibleで中身整えるで良さそう。
あと勉強しながらこの記事を書いていましたが、ながら執筆って良いかもしれない。
こういうログのほうが記事に良いなって思うたびにやり直すので。


AzureでVM作成と比較した

なるほど、Terraformってほぼ同じ感じで使いまわせるんだなぁと思いました。

qiita.com


まずは用語や雰囲気をおさえた

まずは、社内でお勧めされていた以下の動画を視聴し、用語と雰囲気を知りました。
https://www.youtube.com/watch?v=h1MDCp7blmg


次にWindows端末で環境構築した

1. Pathが通ってるフォルダ(例えばc:\Windows直下)に、terraform.exeを置きます。
https://www.terraform.io/downloads

2. AWS CLIをインストールします。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-windows.html

公式ドキュメントだと、Chocolateyを利用する方法のようです(本記事では未実施)
https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started


コマンドを打った

まずはバージョンの確認とhelpを見てみます。

C:\Users\ユーザ名>terraform version
Terraform v1.1.0
on windows_amd64

C:\Users\ユーザ名>aws --version
aws-cli/2.4.6 Python/3.8.8 Windows/10 exe/AMD64 prompt/off

C:\Users\ユーザ名>terraform -help
Usage: terraform [global options] <subcommand> [args]

The available commands for execution are listed below.
The primary workflow commands are given first, followed by
less common or more advanced commands.

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

All other commands:
  console       Try Terraform expressions at an interactive command prompt
  fmt           Reformat your configuration in the standard style
  force-unlock  Release a stuck lock on the current workspace
  get           Install or upgrade remote Terraform modules
()

Global options (use these before the subcommand, if any):
  -chdir=DIR    Switch to a different working directory before executing the
                given subcommand.
  -help         Show this help output, or the help for a specified subcommand.
  -version      An alias for the "version" subcommand.

いろいろ機能があるんだなぁと思いつつ、Main commandsを実行するため、各種ファイルを作成していきます。


  • 認証情報の作成

「C:\Users\ユーザ名\」配下に「.aws」フォルダを作り、「credentials」ファイルを作成します。
メモ帳で作成、改行コードもCRLFで大丈夫です。
しばらくCMDでコマンド打ってなかったので、lsでもviでもcatでもない、なんだっけと調べるほうが時間かかりました。

[default]
aws_access_key_id=AKI***********
aws_secret_access_key=***********


適当な名前のディレクトリを作って、移動しましょう。

C:\Users\ユーザ名>mkdir study_terraform
C:\Users\ユーザ名>cd study_terraform


  • main.tfの作成

main.tfファイルに、作成するインスタンスのリソース情報を記載します。
リソース情報はなるべく少なくし、デフォルト設定任せにしています。
AMIは好きなものを選んでください。
main.tfも、認証情報同様メモ帳などで作って大丈夫です。

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

resource "aws_instance" "mito-ec2" {
    ami           = "ami-********"
    instance_type = "t2.micro"
    key_name = "キー名"
    associate_public_ip_address = "true"
    tags = {
        Name = "mito-ec2"
    }
}

output "ec2-ip"{
    value = aws_instance.mito-ec2.public_ip
}


  • terraform initの実行

ワークスペースの初期化や、実行に必要なバイナリファイルをダウンロードします。

C:\Users\ユーザ名\study_terraform>terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v3.69.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

C:\Users\ユーザ名\study_terraform>
C:\Users\ユーザ名\study_terraform>dir
 Volume in drive C is Windows
 Volume Serial Number is ****

 Directory of C:\Users\ユーザ名\study_terraform

2021/12/22  23:07    <DIR>          .
2021/12/22  23:07    <DIR>          ..
2021/12/22  23:07    <DIR>          .terraform
2021/12/22  23:07             1,077 .terraform.lock.hcl
2021/12/22  22:36               358 main.tf
               2 File(s)          1,435 bytes
               3 Dir(s)  53,891,817,472 bytes free

C:\Users\ユーザ名\study_terraform>


  • terraform validateの実行

構文チェックを行います。

C:\Users\ユーザ名\study_terraform>terraform validate
Success! The configuration is valid.


C:\Users\ユーザ名\study_terraform>


  • terraform planの実行

作成されるリソースが確認できます。
なお、作成だけでなく、コードを更新した場合は既存環境との差分やリソースの変更なども確認できます。

C:\Users\ユーザ名\study_terraform>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_instance.mito-ec2 will be created
  + resource "aws_instance" "mito-ec2" {
      + ami                                  = "ami-********"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = true
      + 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                             = "キー名"
      + 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" = "mito-ec2"
        }
      + tags_all                             = {
          + "Name" = "mito-ec2"
        }
      + 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)
        }

      + 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)
        }
    }

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

Changes to Outputs:
  + ec2-ip = (known after apply)

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

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.

C:\Users\ユーザ名\study_terraform>


  • terraform applyの実行

main.tfで設定したリソースを一気に作ります。

C:\Users\ユーザ名\study_terraform>terraform apply

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_instance.mito-ec2 will be created
  + resource "aws_instance" "mito-ec2" {
      + ami                                  = "ami-********"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = true
      + 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                             = "キー名"
      + 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" = "mito-ec2"
        }
      + tags_all                             = {
          + "Name" = "mito-ec2"
        }
      ()
    }

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

Changes to Outputs:
  + ec2-ip = (known after apply)

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

aws_instance.mito-ec2: Creating...
aws_instance.mito-ec2: Still creating... [10s elapsed]
aws_instance.mito-ec2: Still creating... [20s elapsed]
aws_instance.mito-ec2: Still creating... [30s elapsed]
aws_instance.mito-ec2: Creation complete after 36s [id=i-02abe6f0e4497ed52]

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

Outputs:

ec2-ip = "52.199.5.247"

C:\Users\ユーザ名\study_terraform>
C:\Users\ユーザ名\study_terraform>dir
 Volume in drive C is Windows
 Volume Serial Number is ****

 Directory of C:\Users\ユーザ名\study_terraform

2021/12/22  23:15    <DIR>          .
2021/12/22  23:15    <DIR>          ..
2021/12/22  23:07    <DIR>          .terraform
2021/12/22  23:07             1,077 .terraform.lock.hcl
2021/12/22  22:36               358 main.tf
2021/12/22  23:15             3,943 terraform.tfstate
               3 File(s)          5,378 bytes
               3 Dir(s)  53,894,037,504 bytes free

C:\Users\ユーザ名\study_terraform>



ステータスチェック中であり、すぐ起動が完了するわけではないよね。
起動まで待つ仕組みはあるでしょう。

また、tfstateファイルに作成したリソース情報が記載されます。

{
  "version": 4,
  "terraform_version": "1.1.0",
  "serial": 2,
  "lineage": "*********",
  "outputs": {
    "ec2-ip": {
      "value": "52.199.5.247",
      "type": "string"
    }
  },
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "mito-ec2",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "ami": "ami-******",
       ()
        }
      ]
    }
  ]
}


  • terraform destroyの実行

作成した環境を一気に壊します!

C:\Users\ユーザ名\study_terraform>terraform destroy
aws_instance.mito-ec2: Refreshing state... [id=i-02abe6f0e4497ed52]

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

Terraform will perform the following actions:

  # aws_instance.mito-ec2 will be destroyed
  - resource "aws_instance" "mito-ec2" {
      - ami                                  = "ami-********" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:*******:instance/i-02abe6f0e4497ed52" -> null
      - associate_public_ip_address          = true -> null
      - availability_zone                    = "ap-northeast-1a" -> null
      - cpu_core_count                       = 1 -> null
      - cpu_threads_per_core                 = 1 -> null
      ()
      - tags                                 = {
          - "Name" = "mito-ec2"
        } -> null
      - tags_all                             = {
          - "Name" = "mito-ec2"
        } -> null
      ()
    }

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

Changes to Outputs:
  - ec2-ip = "52.199.5.247" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.mito-ec2: Destroying... [id=i-02abe6f0e4497ed52]
aws_instance.mito-ec2: Still destroying... [id=i-02abe6f0e4497ed52, 10s elapsed]
aws_instance.mito-ec2: Still destroying... [id=i-02abe6f0e4497ed52, 20s elapsed]
()
aws_instance.mito-ec2: Still destroying... [id=i-02abe6f0e4497ed52, 2m20s elapsed]
aws_instance.mito-ec2: Destruction complete after 2m25s

Destroy complete! Resources: 1 destroyed.

C:\Users\キー名\study_terraform>

気持ちいい。。。