#16.AWSでTerraform使ってみた。

# はじめに

こんにちは！nayaaaaです。
最近Kubernetesの学習をしていたのですが、そろそろAWSのハンズオンもやっておきたいなぁというところで、Terraformを使ってEC2の立ち上げの設定を行いました。
こちらの記事は、その際の振り返りとなります。

# Terraformとは

Iac(infrastructure as code)ツールの一つでプラットフォームを提供することができます。
Ansible と比較されることが多いですが、`Ansible`はミドルウェアやアプリケーションのデプロイを主な役割とし、`Terraform`はネットワークやストレージ、仮想マシンなどのプラットフォームの構築を担う、という違いがあります。
また、.tf ファイルで設定を定義できることや実行環境が異なるといった違いもあります。


# .tfファイル

EC2の立ち上げのみを行うため、以下の通りに設定しました。

```
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
  }
}

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

resource "aws_instance" "TechBull-server" {
  ami           = "ami-0a6fd4c92fc6ed7d5"
  instance_type = "t2.micro"

  tags = {
    Name = "TechBull-server-Instance"
  }
}
```

`aws` AWS のプロバイダーを使用することを指定
`source` Terraform が使用する AWS プロバイダーのソース
`region` リソースを作成する AWS のリージョン (東京を使用しています。）
`ami` 使用する Amazon マシンイメージ（AMI）
`instance_type` 作成する EC2 インスタンスの種類
`tags` インスタンスに付与するタグ (インスタンスの管理に使用する。）
`Name` EC2インスタンスの名前

# IAMポリシーの設定とTerraform実行

まず、EC2インスタンスにアタッチするIAMポリシーとして以下のように設定しました。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:RunInstances",
                "ec2:CreateTags",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeTags",
                "ec2:TerminateInstances"
            ],
            "Resource": "*"
        }
    ]
```

## 実際にTerraformを実行

- 初回実行

```
# terraform plan
```
```
# terraform apply
```
すると、以下のエラーが発生しました。
```
 Error: reading EC2 Instance (i-0c0d633d0d34e41ac): getting attribute (instanceInitiatedShutdownBehavior): operation error EC2: DescribeInstanceAttribute, https response error StatusCode: 403, RequestID: ddd0459e-da69-41a7-81f8-305e7d13830c, api error UnauthorizedOperation: You are not authorized to perform this operation. User: arn:aws:iam::864899840494:user/naya is not authorized to perform: ec2:DescribeInstanceAttribute on resource: arn:aws:ec2:ap-northeast-1:864899840494:instance/i-0c0d633d0d34e41ac because no identity-based policy allows the ec2:DescribeInstanceAttribute action. Encoded authorization failure message: orBDnWQ2odGNJpRx1EMuS1DJlqUPrnCQLLIFohlJYTkAukYpoxRPyOIhtIeRYrpOor9zn0WDNi1N3qmIfio-1pHkZ_HmSGTTqZQdTdBQOZkHZbdTS8WBODRtFw3HGqRRdKd5SLMstBIlOKd-sRDhItp2LkjtvsPZ7Smk0JZwWBVhAMBJxjIRPsMJAjXBHE6g6oP3MXkR8qePH7_Ns-Umd0tCDv1pCb8VmOMLteWqGs2jyk27exFMP1l3TuoTNp6rarJk4dLghXpe8CttydFV7RBiB97Z32XpCkG2kjLfIBkXM1TosENX-6BxFPB1z7D509yVd97pD_8dD4nDfotf2Vsp_XiJN839wmq71s5xsrySu_6lTXw2TjTNgu3SYZzohfpt-U7m_2V_ufFSjsohQOFbaQtVN4JWKZLxJpRo78A6l7Uj-1ThG8NgiSDIYZlltLko2aMtbECu_keWnqsdurswAm3czvTt9ppNwPiJA_VZIaHUiKRHwKTi-zxyL_LI4zjYk_vPODhZOMHDrxyTRuSk2wyQdFooNa4H-5UmJg5v-f2Yd04llV4Dc0cVFS-n9T-c9kr3XUZFGAYbeDX7mr6LBxCLfXbxIEyqWZ5vSgekuWxa9ax4BSUQNZlJdmInIQnSMwpKG854nmEb7g_47Q2Jmaycmpfi0EZx-GcsKh7QYBCotUgFFNeFV7XlufmHylWXyh6bGRviC7mfZCUddBhTPhNae5OTcxUPzdLLU5903tQdVTJA4kEPU8p1tBHJB7uf6uY5FN75Ful6QknVldTmG9Us6bkAto9snMCpR0sC6IxsVEo9AZPEeNm1VsDnflOznVuJO6s2OlawtqXZanU4uMOhlAr1y1EAEIGm9Q
 ```

アクセス権限が足りなかったようなので、権限を追加してapply
- 2回目の実行
```
 Error: reading EC2 Instance (i-0c0d633d0d34e41ac): reading block devices: operation error EC2: DescribeVolumes, https response error StatusCode: 403, RequestID: fd64cc6b-eb8b-4f67-87f1-543f4df21db0, api error UnauthorizedOperation: You are not authorized to perform this operation. User: arn:aws:iam::864899840494:user/naya is not authorized to perform: ec2:DescribeVolumes because no identity-based policy allows the ec2:DescribeVolumes action
```
別の権限エラーが出たので追加してapply
- 3回目の実行
```
Error: reading EC2 Instance (i-0c0d633d0d34e41ac) credit specification: operation error EC2: DescribeInstanceCreditSpecifications, https response error StatusCode: 403, RequestID: 5e40637d-1fda-4f73-acd8-468d2ca68984, api error UnauthorizedOperation: You are not authorized to perform this operation. User: arn:aws:iam::864899840494:user/naya is not authorized to perform: ec2:DescribeInstanceCreditSpecifications because no identity-based policy allows the ec2:DescribeInstanceCreditSpecifications action
```
また出ました。もう一度追加してapply
- 4回目の実行
```
Plan: 1 to add, 0 to change, 1 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.TechBull-server: Destroying... [id=i-0c0d633d0d34e41ac]
aws_instance.TechBull-server: Still destroying... [id=i-0c0d633d0d34e41ac, 10s elapsed]
aws_instance.TechBull-server: Still destroying... [id=i-0c0d633d0d34e41ac, 20s elapsed]
aws_instance.TechBull-server: Still destroying... [id=i-0c0d633d0d34e41ac, 30s elapsed]
aws_instance.TechBull-server: Destruction complete after 30s
aws_instance.TechBull-server: Creating...
aws_instance.TechBull-server: Still creating... [10s elapsed]
aws_instance.TechBull-server: Creation complete after 13s [id=i-02d841658cbacee8b]

Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
```
するとようやっと完了しました。

- 修正後の最終的なIAMポリシーの設定

```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"ec2:RunInstances",
				"ec2:CreateTags",
				"ec2:DescribeInstances",
				"ec2:DescribeInstanceTypes",
				"ec2:DescribeTags",
				"ec2:DescribeInstanceAttribute",
				"ec2:DescribeVolumes",
				"ec2:DescribeInstanceCreditSpecifications",
				"ec2:TerminateInstances"
			],
			"Resource": "*"
		}
	]
}
```
- コンソール画面


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3904736/86483eff-5047-1004-a320-808532c2703e.png)



`ec2:DescribeInstanceAttribute`、`ec2:DescribeInstanceCreditSpecifications`、`ec2:DescribeVolumes` の 3 つの権限について調査したのですが、明確に「必須である理由」を特定するのが難しかったため、
`ChatGPT様`に確認したところ、以下の理由で Terraform による EC2 インスタンスの作成時に必要になる可能性があることが分かりました。

以下、コピペ
***
### 権限が必要になる理由
- ```ec2:DescribeInstanceAttribute```

Terraform は EC2 インスタンスの 詳細属性（例: disable_api_termination） を確認するために DescribeInstanceAttribute を実行します。
たとえ disable_api_termination を .tf ファイルで明示的に設定していなくても、Terraform は デフォルト値を AWS に問い合わせる ため、この権限が必要になる場合があります。
- ```ec2:DescribeInstanceCreditSpecifications```

T2/T3 インスタンス (t2.micro など) は CPU クレジットの仕様 (standard / unlimited) を持っており、Terraform はその設定を確認するために DescribeInstanceCreditSpecifications を実行します。
したがって、T2/T3 系のインスタンスを使用する場合は必須ですが、それ以外のインスタンス（例: m5.large）を使用する場合は不要 です。
- ```ec2:DescribeVolumes```

Terraform は EC2 インスタンスにアタッチされた EBS ボリュームの情報（サイズ、タイプなど）を AWS から取得 しようとするため DescribeVolumes を実行します。
.tf ファイルで root_block_device を 明示的に指定していなくても、AMI に紐づいたデフォルトの EBS ボリュームの情報を取得するために、この権限が必要になることがあります。

***
ここら辺の権限についてご存じの方がいれば教えていただけるとありがたいです。

# まとめ
Terraform は非常に便利なツールですね。CloudFormation とは異なり、AWS 以外のクラウドプロバイダーにも対応しているため、マルチクラウド環境でも利用できる、というのは利点なのかなと思います。
また、IaC（Infrastructure as Code）の記述方法やディレクトリ構成のベストプラクティスを学ぶことができるため、AWS入門者が最初に学ぶツールとしても適していると感じました。