Open5

terraformを用いて、最小構成でEC2サーバーを立ち上げる

O.SO.S

参考にするもの

以下の記事が良さそう。
https://zenn.dev/supersatton/articles/c87853cc5a3dbd

以下はchatGPTに聞いた。

chatgptが教えてくれたやり方

Terraformを使って最小構成でEC2サーバーを立ち上げる手順を説明します。Terraformは、インフラストラクチャーをコードとして管理するためのツールです。以下の手順に従ってください。

前提条件

  • AWSアカウント: EC2インスタンスを作成するためには、AWSアカウントが必要です。
  • Terraformのインストール: Terraformのウェブサイトからダウンロードしてインストールしてください。

ステップバイステップのガイド

1. Terraform設定ファイルの作成

  • 新しいディレクトリを作成し、そこにTerraform設定ファイルを作成します。例えば、main.tf という名前でファイルを作成します。

2. プロバイダの設定

  • TerraformにAWSを使うことを伝えるために、プロバイダを設定します。main.tf ファイルに以下のコードを追加します。

    provider "aws" {
      region = "us-west-2"  # 任意のリージョンに変更してください
    }
    

3. EC2インスタンスの設定

  • EC2インスタンスを作成するための設定を追加します。以下は最小構成の例です。

    resource "aws_instance" "example" {
      ami           = "ami-0c55b159cbfafe1f0"  # AMI IDを適切なものに変更してください
      instance_type = "t2.micro"  # インスタンスタイプ
    }
    
    • ami: Amazon Machine ImageのIDです。リージョンごとに異なるので、適切なものを選んでください。
    • instance_type: EC2インスタンスのタイプです。t2.micro は無料枠に含まれます。

4. Terraformの初期化

  • 作成したディレクトリ内で、コマンドラインを開いて、以下のコマンドを実行します。

    terraform init
    

    これにより、Terraformが初期化され、必要なプラグインがダウンロードされます。

5. プランの実行

  • Terraformによる変更内容を確認するために、以下のコマンドを実行します。

    terraform plan
    

6. インスタンスの作成

  • 問題がなければ、以下のコマンドでEC2インスタンスを作成します。

    terraform apply
    

    実行時にyesと入力して、変更を承認します。

7. 確認

  • AWSコンソールにログインして、EC2インスタンスが正常に作成されたことを確認します。

これで、Terraformを使用して最小構成のEC2サーバーが立ち上がります。より高度な設定や、セキュリティグループの設定などは、Terraformのドキュメントを参照してください。

前提

  • terraformをインストールしていること
  • aws configureを設定していること

作業手順

  • 以下のように、terraformを書く。
    • subnet_idは自分のVPCに存在するsubnetに変更してください。
    • tags.NameはEC2インスタンスの名前になるので、自分の好きな名前にしてください。

https://github.com/ochi-sho-private-study/terraform-practice/blob/2df01f35f0c47cea09235bd65f41aca1323a5668/minimum_ec2_server/main.tf#L1-L14

O.SO.S

実行結果

terraform init

実行結果
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v5.31.0...
- Installed hashicorp/aws v5.31.0 (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 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.minimum_ec2_server will be created
  + resource "aws_instance" "minimum_ec2_server" {
      + ami                                  = "ami-0dfa284c9d7b2adad"
      + 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)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_lifecycle                   = (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                             = (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
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = "subnet-0274f6b9bdd43120c"
      + tags                                 = {
          + "Name" = "minimum_ec2_server"
        }
      + tags_all                             = {
          + "Name" = "minimum_ec2_server"
        }
      + 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)
    }

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

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.minimum_ec2_server will be created
  + resource "aws_instance" "minimum_ec2_server" {
      + ami                                  = "ami-0dfa284c9d7b2adad"
      + 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)
      + host_resource_group_arn              = (known after apply)
      + iam_instance_profile                 = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_lifecycle                   = (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                             = (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
      + spot_instance_request_id             = (known after apply)
      + subnet_id                            = "subnet-0274f6b9bdd43120c"
      + tags                                 = {
          + "Name" = "minimum_ec2_server"
        }
      + tags_all                             = {
          + "Name" = "minimum_ec2_server"
        }
      + 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)
    }

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.minimum_ec2_server: Creating...
aws_instance.minimum_ec2_server: Still creating... [10s elapsed]
aws_instance.minimum_ec2_server: Still creating... [20s elapsed]
aws_instance.minimum_ec2_server: Still creating... [30s elapsed]
aws_instance.minimum_ec2_server: Creation complete after 33s [id=i-0250a5dc656e0f3b2]

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

</details>

terraform destroy

実行結果
$ terraform destroy

aws_instance.minimum_ec2_server: Refreshing state... [id=i-0e0adcb2f07d6982a]

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.minimum_ec2_server will be destroyed
  - resource "aws_instance" "minimum_ec2_server" {
      - ami                                  = "ami-0dfa284c9d7b2adad" -> null
      - arn                                  = "arn:aws:ec2:ap-northeast-1:414470437161:instance/i-0e0adcb2f07d6982a" -> null
      - associate_public_ip_address          = false -> null
      - availability_zone                    = "ap-northeast-1a" -> null
      - cpu_core_count                       = 1 -> null
      - cpu_threads_per_core                 = 1 -> 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-0e0adcb2f07d6982a" -> null
      - instance_initiated_shutdown_behavior = "stop" -> null
      - instance_state                       = "running" -> null
      - instance_type                        = "t2.micro" -> null
      - ipv6_address_count                   = 0 -> null
      - ipv6_addresses                       = [] -> null
      - monitoring                           = false -> null
      - placement_partition_number           = 0 -> null
      - primary_network_interface_id         = "eni-03e7e708c5a6a628b" -> null
      - private_dns                          = "ip-192-168-0-172.ap-northeast-1.compute.internal" -> null
      - private_ip                           = "192.168.0.172" -> null
      - secondary_private_ips                = [] -> null
      - security_groups                      = [] -> null
      - source_dest_check                    = true -> null
      - subnet_id                            = "subnet-0274f6b9bdd43120c" -> null
      - tags                                 = {} -> null
      - tags_all                             = {} -> null
      - tenancy                              = "default" -> null
      - user_data_replace_on_change          = false -> null
      - vpc_security_group_ids               = [
          - "sg-0986959ef5604e483",
        ] -> null

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

      - cpu_options {
          - core_count       = 1 -> null
          - threads_per_core = 1 -> null
        }

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

      - enclave_options {
          - enabled = false -> null
        }

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

      - metadata_options {
          - http_endpoint               = "enabled" -> null
          - http_protocol_ipv6          = "disabled" -> null
          - http_put_response_hop_limit = 2 -> null
          - http_tokens                 = "required" -> 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                  = 3000 -> null
          - tags                  = {} -> null
          - throughput            = 125 -> null
          - volume_id             = "vol-0a6ad65ebd936e89e" -> null
          - volume_size           = 8 -> null
          - volume_type           = "gp3" -> 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.minimum_ec2_server: Destroying... [id=i-0e0adcb2f07d6982a]
aws_instance.minimum_ec2_server: Still destroying... [id=i-0e0adcb2f07d6982a, 10s elapsed]
aws_instance.minimum_ec2_server: Still destroying... [id=i-0e0adcb2f07d6982a, 20s elapsed]
aws_instance.minimum_ec2_server: Still destroying... [id=i-0e0adcb2f07d6982a, 30s elapsed]
aws_instance.minimum_ec2_server: Still destroying... [id=i-0e0adcb2f07d6982a, 40s elapsed]
aws_instance.minimum_ec2_server: Destruction complete after 40s

Destroy complete! Resources: 1 destroyed.

AWSのEC2のマネジメントコンソール

O.SO.S

terraform applyterraform planterraform initで何が行われているのかをまとめる。

各コマンドでやってること

terraform init

  • このコマンドは、Terraformプロジェクトを初期化する。
  • 必要なTerraformプラグインやプロバイダーをダウンロードし、設定する。
  • .terraform ディレクトリを作成し、その中にプラグインなどの設定を格納する。

terraform plan

  • Terraformの設定ファイル(通常は .tf ファイル)に基づいて、実行計画を作成します。
  • どのようなインフラストラクチャーが作成、変更、または削除されるかを示します。
  • 実際に変更を加える前に、予定されている変更内容をレビューするために使用されます。

terraform apply

  • terraform plan で作成された実行計画を実行し、インフラストラクチャーを作成または変更します。
  • 実際のリソースをクラウドプロバイダー上に作成、更新、または削除します。
  • 実際の変更が適用されるため、このコマンドを実行する前に計画を注意深くレビューすることが重要です。

terraform destroy

  • Terraformによって管理されているインフラストラクチャーを破棄します。
  • terraform apply で作成されたリソースをすべて削除します。
  • このコマンドを使用する際は特に慎重になる必要があります。誤って重要なリソースを削除するリスクがあります。

記述について

resource

provider

O.SO.S

今後の展望

  • 今回は、サブネットはデフォルトのものを使用したので、サブネットもterraformで構築してみる。
  • tfstateをS3で管理できるようにする。
  • terraformで作成される以下のファイル・ディレクトリ群の役割がよくわからん。(デバッグに役立ちそう。)
    • .terraform/providers/registry.terraform.io/hashicorp/aws/5.31.0/darwin_arm64/terraform-provider-aws_v5.31.0_x5
    • .terraform.lock.hcl
    • terraform.tfstate
    • terraform.tfstate.backup
  • AMIを作ってみるのも良いかも?
    • Railsの環境デプロイ
    • (ISUCON環境デプロイ)
  • RDSでデータベースを作成してみよう
    • テラフォームで作成してみる
    • 踏み台サーバーを設置して、SSHしてみる
  • ECSでデプロイしてみよう
    • 最小構成のRails環境をテラフォームでデプロイする
    • nextjsをテラフォームでデプロイする
    • ロードバランサーを使う
    • 実務のインフラを真似してみる