Terraform Registry と仲良くなって、AWSリソースを作成しよう

# この記事で達成できること
- Terraform Registryを効率的に検索・活用できるようになります
- EC2インスタンスの作成を例に、実践的なTerraform開発手法を習得できます
# 想定読者
- 以下のような本でTerraformの構文を学んだことのある人
    - [詳解 Terraform 第3版 ―Infrastructure as Codeを実現する](https://amzn.asia/d/1RuwVJS)
    - [Terraformの教科書 (Compass Booksシリーズ)](https://amzn.asia/d/ff7CFgM)
    - [基礎から学ぶ Terraform](https://amzn.asia/d/eVTAxvo)
- Terraformの構文は学んだが、AWSリソースを記そうとしたときに何を元に書けば良いかわからない人
# 注意事項
- 今回はあくまでTerraform Registryと仲良くなるための方法を記すものなので、作成するリソースはシンプルにEC2インスタンスとします
    - VPC/subnetなどのリソースは事前に作成済みを前提としています
- stateファイルはローカルに保持する前提で記載をしていますが、本番環境ではS3などのクラウドストレージに配置することが望ましいです
# 実行環境
- MacOS Sequoia 15.0.1
- Terraform 1.8.2
- AWS接続に必要なIAMロールまたは認証情報が設定済み
- AWS CLI a2.15.42
# Terraform Registryの効率的な使い方
※一気に4スタートでもOK
1. (オプション)お気に入りのブラウザで"Terraform Registry"と検索する
![スクリーンショット 2024-10-31 21.29.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/7a3d229a-842c-8e16-4c6c-bb46f65672ca.png)
1. (オプション)Providerのページに遷移する
![スクリーンショット 2024-10-31 21.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/ee8c57a7-0533-6f75-4993-7a783b313272.png)
1. (オプション)AWSのProviderのページに遷移する
![スクリーンショット 2024-10-31 21.32.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/98bae12b-e63c-ba4c-f6ee-dd55f272d865.png)
1. ということでAWSのProviderページに到着します
    - このページに直接遷移してもOK
    - [AWS Provider](https://registry.terraform.io/providers/hashicorp/aws/latest)
1. AWSのProviderの記載方法をチェックする
![スクリーンショット 2024-10-31 21.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/99e94e3a-6e6a-938b-a90f-c2d93711d38e.png)

    ```hcl
    terraform {
    required_providers {
      aws = {
        source = "hashicorp/aws"
        version = "5.73.0"
      }
    }
    }
    
    provider "aws" {
    # Configuration options
    }
    ```
    
1. リソースの記載方法を確認するためのDocumentページに遷移する
![スクリーンショット 2024-10-31 21.54.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/1cb972ba-69dd-85f9-5c6b-ac60d8456aca.png)
1. 今回作成したいリソース名で検索する
    - 今回は"ec2"
![スクリーンショット 2024-11-03 19.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/0dea7fda-4d14-863a-7d4a-02216078673c.png)
1. Resourceの中から作成したいリソース名をクリックする
    - 今回は"aws_instance"
    - ResourcesとData Sourcesの違いは？
        - Resourcesは同一Terraformコード上でこれから作成するリソース
        - Data Sourcesは同一Terraformコード外(例えば既存)で作成済みのリソースを参照する場合に使用
![スクリーンショット 2024-11-03 19.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/e218ec49-2d13-ccd2-3676-b3be5aacb01b.png)
1. aws_instanceセクションを作成する

    ```hcl    
    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "5.73.0"
        }
      }
    }

    provider "aws" {
      # Configuration options
    }

    resource "aws_instance" "web" {
    } 
    ```

    - "aws_instance"
        - AWSリソースの種類
    - "web"
        - Terraformコード内で"aws_instance"を一意に示す

1. Example Usageの中から、上の項目に合致する項目を取得する
![スクリーンショット 2024-11-03 19.51.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1276335/b5fcb8d5-0bde-0963-fdee-b7cb58d23be5.png)

    ```hcl
    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "5.73.0"
        }
      }
    }

    provider "aws" {
      # Configuration options
    }

    resource "aws_instance" "web" {
      ami           = data.aws_ami.ubuntu.id
      instance_type = "t3.micro"

      tags = {
        Name = "HelloWorld"
      }
    }
    ```

1. Argument Referenceの中で"(Required)"と記載があるものをpickし、Example Usageの中で必要な項目を確認する
    - EC2の場合はRequiredがないため、極論、項番9の内容を指定するだけでEC2インスタンスが作成できる
    - RequiredはEBSの以下を参照
        - [ebs_volume-availability_zone](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume#availability_zone)
1. Example Usageでは不足している、追加で指定したい項目をArgument Referenceの中からpickする
    - EC2の中でよく使われるだろう、、と思われるのは以下
        - [ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#ami)
            - 例として、AmazonLinux2023を直指定する場合は"ami-03f584e50b2d32776"
        - [instance_type](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#instance_type)
            - 例として、"t3.micro"
        - [subnet_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#subnet_id)
            - 例として、"subnet-xxxxxxxxxxxxxxxxx"
            - 正しいsubnet IDはGUIやdataセクションを用いて指定すること
    - 上記を組み込むと以下にようになる   

    ```hcl
    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "5.73.0"
        }
      }
    }

    provider "aws" {
      # Configuration options
    }

    resource "aws_instance" "web" {
      # 東京リージョンのAmazon Linux 2023
      ami = "ami-03f584e50b2d32776"
      instance_type = "t3.micro"
      subnet_id = "subnet-xxxxxxxxxxxxxxxxx"

      tags = {
        Name = "HelloWorld"
      }
    }
    ```

1. ここまで書ければ、あとはTerraformコマンドを実行すればOK

    ```shell
    % terraform init    # 初期化とプロバイダーのインストール
    % terraform fmt     # コードのフォーマット
    % terraform plan    # 実行計画の確認
    % terraform apply   # リソースの作成
    ```

# まとめ
- 以上が、実際にTerraformでリソースを記載する際に、0からコードを記載する例です
- 実際には1リソースだけをわざわざ作成するコードを書く、、ということはほぼなく、dataセクションで既存のリソースを参照したり、複数リソースを組み合わせることが多いです
- 今回の内容を元に、重厚なコードを記載できるようになる方が増えると嬉しいです