0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Terraformを使って覚える。(その3:Terraformの実行)

Posted at

はじめに

Terraformの開発環境が整ったので、今回からTerraformを使ってAWSへの構築を進めてみようと思います。

Terraform実行方法

実際にAWSのEC2インスタンスを作成する例を基にTerraformを実行してみます。

  • コーディング
  • terraform initの実行(初回のみ)
  • terraform fmtの実行
  • terraform planの実行
  • terraform applyの実行

コーディング

前回インストールしたVS Codeでコーディングを行う場合、「~.tf」という拡張子にすることでTerraformのフォーマットだと認識されます。

EC2インスタンスを作成する場合、最低限以下のようなコーディングを行うことで作成することができます。

main.tfの作成
provider "aws" {
  region = "ap-northeast-1"
  profile = "default"
}

resource "aws_instance" "testtf" {
    ami = "ami-0b7546e839d7ace12"
    instance_type = "t3.micro"
}

各種リソースで指定可能な設定やオプションは以下のオンラインドキュメントを参照することで確認できます。

今回の場合、Terraformが暗黙でAWSへの実行だと判断し、セットアップ済みのAWS CLIのデフォルトクレデンシャル情報を使用して接続しに行くため、providerブロックは無くても動作しますが、意図しない動作とならないよう、明示するようにしましょう。

terraform initの実行(初回のみ)

terraform initコマンドを実行することで、カレントディレクトリに.terraform.locl.hclファイルと.terraformフォルダが作成され、その中に各種プロバイダのリソース作成に必要となるバイナリファイルがダウンロードされます。

ファイル・フォルダ名 説明
main.tf 作成したソースコード
.terraform AWS等の各種プロバイダリソース作成用バイナリファイル格納
.terraform.lock.hcl 各種プロバイダファイルのロックファイル

.terraform.lock.hclは以下のようなファイルとなります。

実行環境が変わったとしてもProviderの動作が変わらないようにするためのファイルとのこと。

.terraform.lock.hclファイルの例
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.

provider "registry.terraform.io/hashicorp/aws" {
  version = "4.20.1"
  hashes = [
    "h1:mU0Rl9mMkny1Q34aiQMSTA2R/wfVPJgHQGM+/GYUfG0=",
    "zh:21d064d8fac08376c633e002e2f36e83eb7958535e251831feaf38f51c49dafd",
    "zh:3a37912ff43d89ce8d559ec86265d7506801bccb380c7cfb896e8ff24e3fe79d",
    "zh:795eb175c85279ec51dbe12e4d1afa0860c2c0b22e5d36a8e8869f60a93b7931",
    "zh:8afb61a18b17f8ff249cb23e9d3b5d2530944001ef1d56c1d53f41b0890c7ab8",
    "zh:911701040395e0e4da4b7252279e7cf1593cdd26f22835e1a9eddbdb9691a1a7",
    "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
    "zh:a46d54a6a5407f569f8178e916af888b2b268f86448c64cad165dc89759c8399",
    "zh:c5f71fd5e3519a24fd6af455ef1c26a559cfdde7f626b0afbd2a73bb79f036b1",
    "zh:df3b69d6c9b0cdc7e3f90ee08412b22332c32e97ad8ce6ccad528f89f235a7d3",
    "zh:e99d6a64c03549d60c2accf792fa04466cfb317f72e895c8f67eff8a02920887",
    "zh:eea7a0df8bcb69925c9ce8e15ef403c8bbf16d46c43e8f5607b116531d1bce4a",
    "zh:f6a26ce77f7db1d50ce311e32902fd001fb365e5e45e47a9a5cd59d734c89cb6",
  ]
}

また、terraform initを実行した場合、以下のような結果が出力され、各種プロバイダリソース作成用バイナリのダウンロードや初期化が行われます。

terraform_init実行時の結果例
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.20.1...
- Installed hashicorp/aws v4.20.1 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

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.

terraform fmtの実行

terraform fmtは毎回実行しなくても良いですが、terraform fmtを実行すると、先ほどコーディングしたソースファイルのフォーマットを整えてくれるため、コーディング後には実行したほうがよいでしょう。

terraform_fmtの実行
terraform fmt

ちなみに先ほどコーディングしたmain.tfterraform fmtコマンドを実行した場合、以下のように整形されます。

terraform_fmt実行後のmain.tf
provider "aws" {
  region  = "ap-northeast-1"
  profile = "default"
}

resource "aws_instance" "testtf" {
  ami           = "ami-0b7546e839d7ace12"
  instance_type = "t3.micro"
}

terraform planの実行

terraform planを実行すると、どのようなリソースが作成・変更・削除されるかといった情報を確認することができます。

確認だけで作成はされないため、次のterraform applyコマンドを実行する前の確認用途で使います。

以下「+」で表示されるリソースは、terraform apply実行時に作成されるリソース、(今回はありませんが)「~」で表示されるリソースはterraform apply実行時に削除されるリソースとなります。

terraform planの実行結果(展開してください)
terraform_planの実行
$ 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.testtf will be created
  + resource "aws_instance" "testtf" {
      + ami                                  = "ami-0b7546e839d7ace12"
      + 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_stop                     = (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                        = "t3.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + 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_all                             = (known after apply)
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + 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)
              + capacity_reservation_resource_group_arn = (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)
        }

      + maintenance_options {
          + auto_recovery = (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_card_index    = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + private_dns_name_options {
          + enable_resource_name_dns_a_record    = (known after apply)
          + enable_resource_name_dns_aaaa_record = (known after apply)
          + hostname_type                        = (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.

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

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.

terraform applyの実行

terraform applyを実行すると、コードの内容が実行されて、各プロバイダ環境(今回はAWS)に各種リソースが作成されます。

また、途中でリソース作成確認があり、入力を求められるため、「yes」と入力して実行します。

自動化等を行っており、「yes」の入力を省きたい場合は-auto-approveオプションを追加して実行すると、入力を省くことができます。

terraform applyの実行結果(展開してください)
terraform_applyの実行
$ 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.testtf will be created
  + resource "aws_instance" "testtf" {
      + ami                                  = "ami-0b7546e839d7ace12"
      + 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_stop                     = (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                        = "t3.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + 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_all                             = (known after apply)
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + 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)
              + capacity_reservation_resource_group_arn = (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)
        }

      + maintenance_options {
          + auto_recovery = (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_card_index    = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + private_dns_name_options {
          + enable_resource_name_dns_a_record    = (known after apply)
          + enable_resource_name_dns_aaaa_record = (known after apply)
          + hostname_type                        = (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.

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.testtf: Creating...
aws_instance.testtf: Still creating... [10s elapsed]
aws_instance.testtf: Creation complete after 13s [id=i-058f9caf6b5fabfd0]

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

また、terraform apply実行後、カレントディレクトリにterraform.tfstateというファイルが作成されます。

terraform.tfstateファイルはterraform apply実行時の各プロバイダ(今回はAWS)環境の状態を記録しているファイルとなり、次回terraform apply実行時には、terraform.tfstateファイルに記載されている環境情報と比較し、差分のみを追加&削除等を行う動作となります。

terraform.tfstateファイルの表示例(展開してください)
terraform.tfstateファイル
{
  "version": 4,
  "terraform_version": "1.2.3",
  "serial": 1,
  "lineage": "f0456b47-464f-3c3f-e246-4aeea30425b8",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "testtf",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 1,
          "attributes": {
            "ami": "ami-0b7546e839d7ace12",
            "arn": "arn:aws:ec2:ap-northeast-1:335417439444:instance/i-058f9caf6b5fabfd0",
            "associate_public_ip_address": true,
            "availability_zone": "ap-northeast-1d",
            "capacity_reservation_specification": [
              {
                "capacity_reservation_preference": "open",
                "capacity_reservation_target": []
              }
            ],
            "cpu_core_count": 1,
            "cpu_threads_per_core": 2,
            "credit_specification": [
              {
                "cpu_credits": "unlimited"
              }
            ],
            "disable_api_stop": false,
            "disable_api_termination": false,
            "ebs_block_device": [],
            "ebs_optimized": false,
            "enclave_options": [
              {
                "enabled": false
              }
            ],
            "ephemeral_block_device": [],
            "get_password_data": false,
            "hibernation": false,
            "host_id": null,
            "iam_instance_profile": "",
            "id": "i-058f9caf6b5fabfd0",
            "instance_initiated_shutdown_behavior": "stop",
            "instance_state": "running",
            "instance_type": "t3.micro",
            "ipv6_address_count": 0,
            "ipv6_addresses": [],
            "key_name": "",
            "launch_template": [],
            "maintenance_options": [
              {
                "auto_recovery": "default"
              }
            ],
            "metadata_options": [
              {
                "http_endpoint": "enabled",
                "http_put_response_hop_limit": 1,
                "http_tokens": "optional",
                "instance_metadata_tags": "disabled"
              }
            ],
            "monitoring": false,
            "network_interface": [],
            "outpost_arn": "",
            "password_data": "",
            "placement_group": "",
            "placement_partition_number": null,
            "primary_network_interface_id": "eni-00a399526fcba5d63",
            "private_dns": "ip-172-31-21-72.ap-northeast-1.compute.internal",
            "private_dns_name_options": [
              {
                "enable_resource_name_dns_a_record": false,
                "enable_resource_name_dns_aaaa_record": false,
                "hostname_type": "ip-name"
              }
            ],
            "private_ip": "172.31.21.72",
            "public_dns": "ec2-35-78-254-110.ap-northeast-1.compute.amazonaws.com",
            "public_ip": "35.78.254.110",
            "root_block_device": [
              {
                "delete_on_termination": true,
                "device_name": "/dev/xvda",
                "encrypted": false,
                "iops": 100,
                "kms_key_id": "",
                "tags": {},
                "throughput": 0,
                "volume_id": "vol-0eb3884c49cb32c24",
                "volume_size": 8,
                "volume_type": "gp2"
              }
            ],
            "secondary_private_ips": [],
            "security_groups": [
              "default"
            ],
            "source_dest_check": true,
            "subnet_id": "subnet-c50cc9ee",
            "tags": null,
            "tags_all": {},
            "tenancy": "default",
            "timeouts": null,
            "user_data": null,
            "user_data_base64": null,
            "user_data_replace_on_change": false,
            "volume_tags": null,
            "vpc_security_group_ids": [
              "sg-70df8a0e"
            ]
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6MTIwMDAwMDAwMDAwMCwidXBkYXRlIjo2MDAwMDAwMDAwMDB9LCJzY2hlbWFfdmVyc2lvbiI6IjEifQ=="
        }
      ]
    }
  ]
}

尚、デフォルトではローカルのカレントディレクトリに作成されますが、複数人で開発したり、複数端末で開発するような場合、それぞれのユーザのローカルで別々に管理されてしまうと、実行するユーザによって挙動が変わってきてしまうため、その場合はローカルではなく、リモートのストレージで管理する必要があります。

リソース削除方法

作成したリソースをまとめて削除したい場合、terraform destroyコマンドを実行することで、環境をすべて削除することができます。

削除時にもリソース削除確認があり、入力が求められるため、「yes」と入力して実行します。

terraform destroy実行時にも-auto-approveオプションを使用できるため、入力を省きたい場合はオプションを追加して実行します。

terraform destroyの実行結果(展開してください)
terraform_destroyの実行
$ terraform destroy
aws_instance.testtf: Refreshing state... [id=i-058f9caf6b5fabfd0]

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.testtf will be destroyed
  - resource "aws_instance" "testtf" {
      - ami                                  = "ami-0b7546e839d7ace12" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:335417439444:instance/i-058f9caf6b5fabfd0" -> null
      - associate_public_ip_address          = true -> null
      - availability_zone                    = "ap-northeast-1d" -> null
      - cpu_core_count                       = 1 -> null
      - cpu_threads_per_core                 = 2 -> null
      - disable_api_stop                     = false -> null
      - disable_api_termination              = false -> null
      - ebs_optimized                        = false -> null
      - get_password_data                    = false -> null
      - hibernation                          = false -> null
      - id                                   = "i-058f9caf6b5fabfd0" -> null
      - instance_initiated_shutdown_behavior = "stop" -> null
      - instance_state                       = "running" -> null
      - instance_type                        = "t3.micro" -> null
      - ipv6_address_count                   = 0 -> null
      - ipv6_addresses                       = [] -> null
      - monitoring                           = false -> null
      - primary_network_interface_id         = "eni-00a399526fcba5d63" -> null
      - private_dns                          = "ip-172-31-21-72.ap-northeast-1.compute.internal" -> null
      - private_ip                           = "172.31.21.72" -> null
      - public_dns                           = "ec2-35-78-254-110.ap-northeast-1.compute.amazonaws.com" -> null
      - public_ip                            = "35.78.254.110" -> null
      - secondary_private_ips                = [] -> null
      - security_groups                      = [
          - "default",
        ] -> null
      - source_dest_check                    = true -> null
      - subnet_id                            = "subnet-c50cc9ee" -> null
      - tags                                 = {} -> null
      - tags_all                             = {} -> null
      - tenancy                              = "default" -> null
      - user_data_replace_on_change          = false -> null
      - vpc_security_group_ids               = [
          - "sg-70df8a0e",
        ] -> null

      - capacity_reservation_specification {
          - capacity_reservation_preference = "open" -> null
        }

      - credit_specification {
          - cpu_credits = "unlimited" -> null
        }

      - enclave_options {
          - enabled = false -> null
        }

      - maintenance_options {
          - auto_recovery = "default" -> null
        }

      - metadata_options {
          - http_endpoint               = "enabled" -> null
          - http_put_response_hop_limit = 1 -> null
          - http_tokens                 = "optional" -> null
          - instance_metadata_tags      = "disabled" -> null
        }

      - private_dns_name_options {
          - enable_resource_name_dns_a_record    = false -> null
          - enable_resource_name_dns_aaaa_record = false -> null
          - hostname_type                        = "ip-name" -> null
        }

      - root_block_device {
          - delete_on_termination = true -> null
          - device_name           = "/dev/xvda" -> null
          - encrypted             = false -> null
          - iops                  = 100 -> null
          - tags                  = {} -> null
          - throughput            = 0 -> null
          - volume_id             = "vol-0eb3884c49cb32c24" -> null
          - volume_size           = 8 -> null
          - volume_type           = "gp2" -> null
        }
    }

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

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.testtf: Destroying... [id=i-058f9caf6b5fabfd0]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 10s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 20s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 30s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 40s elapsed]
aws_instance.testtf: Still destroying... [id=i-058f9caf6b5fabfd0, 50s elapsed]
aws_instance.testtf: Destruction complete after 50s

Destroy complete! Resources: 1 destroyed.

おわりに

今回はTerraformで構築した際の流れを覚えるため、各種基本操作を実行してみました。

次回はTerraformでコーディングする際の基本構文と、構文等調べる際に参照する各種ドキュメントについて学んでいきます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?