AWSのインフラをコード化：Terraformで簡単にEC2インスタンスを構築する方法

## はじめに
Terraformは、インフラストラクチャをコードとして管理できるツールで、AWSやAzureなど複数のクラウドプロバイダで利用されています。

この記事では、Terraformを使って米国東部リージョン（``us-east-2``）に最小限の構成でEC2インスタンスを構築する手順について説明します。

:::note warn
Terraformのインストールが完了していることを前提に進めます。
:::

## Terraformとは

Terraformは、インフラストラクチャをコード（Infrastructure as Code, IaC）として管理するためのツールです。

![スクリーンショット 2024-10-26 8.26.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/a1531ea9-3a09-2a88-6aae-c6ee8c04baae.png)
引用画像：https://sdpf.ntt.com/services/docs/fic/tutorials/terraform/rsts/Terraform/about_terraform.html

これにより、サーバーやネットワーク、データベースなどのクラウドリソースをコードで定義し、自動で構築、変更、削除ができるようになります。

## 私が「Terraform」を学ぶ理由

今後のインフラ領域では、コード管理による構築作業の工数削減と人的要因によるミスを減らすために、インフラのコード化が進むと考えています。

![スクリーンショット 2024-10-26 10.53.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/a5a8b1d1-4124-35f2-8f4d-93ee265be040.png)
引用画像：https://cn.teldevice.co.jp/blog/p55426/

そこで、休日も早起きして「Terraform」を学び、今後のインフラ領域で生き残るための戦略としていきます。

## Terraformの特徴

Terraformの大きな特徴は、以下の3つになります。

:::note
**マルチクラウド対応**：
AWS、Azure、Google Cloudなど複数のクラウドプロバイダで利用可能で、異なるクラウド環境を同じコードで管理できます。

**宣言的構文**：
ユーザーがリソースの「最終状態」を記述するだけで、Terraformが必要な構築手順を自動で判断・実行します。

**再現性とバージョン管理**：
コードにより、インフラの設定を再現・管理できるため、チーム開発での一貫性が高まり、過去のバージョンを確認しやすくなります。
:::

さらに詳しく知りたい方は、以下の記事も参考にしてみてください。

https://qiita.com/takengineer1216/items/09e1b840d564a16b84eb

## 補足知識
Terraformを用いたAWSインフラ構築の基本として、以下のポイントを押さえておくと作業がスムーズに進みます。

:::note
**プロバイダ設定**：
TerraformはproviderブロックでAWSのようなクラウドプロバイダを指定します。ここでは、米国東部リージョン（``us-east-2``）を指定します。

**VPCとセキュリティグループ**：
EC2インスタンスを安全に利用するためには、VPCとセキュリティグループの設定が必要です。

**リソース作成と初期化**：
Terraformでリソースを作成するには、設定ファイルを作成した後に``terraform init``コマンドで初期化し、``terraform apply``で適用します。また、不要なリソースは``terraform destroy``コマンドで削除可能です。
:::

不要なリソースもコマンド一発で削除できるのは、大きなメリットですね。

## Terraformを用いたEC2構築ハンズオン

### プロジェクトのディレクトリを作成
Terraform設定ファイルを管理するためにディレクトリを作成し、移動します。

```bash
mkdir terraform-ec2
cd terraform-ec2
```

### main.tf ファイルを作成
AWSプロバイダの設定、セキュリティグループの作成、EC2インスタンスの定義を行うための``main.tf``ファイルを作成します。

```main.tf
provider "aws" {
  region = "us-east-2"  # 米国東部リージョンに変更
}

resource "aws_instance" "example" {
  ami           = "ami-0a31f06d64a91614b"  # amzn2-ami-kernel-5.10
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }
}
```

ご自身の環境に合わせて、使用するリージョンやVPC、サブネットなどを適宜設定してください。

### terraform init コマンドで初期化
Terraformでプロバイダ設定を有効にするために初期化します。

```bash
terraform init
```

実際のコマンド入力後のプロンプト画面は、以下のようになります。

![スクリーンショット 2024-10-26 8.56.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/8a770f47-6cee-99ff-ab3d-21d738ec5851.png)

この出力結果から、``terraform init``コマンドが正常に完了し、Terraformのプロジェクトが初期化されていることが確認できました。

### terraform apply コマンドで適用
設定に基づいてEC2インスタンスを作成します。確認後、yesと入力して適用します。

```bash
terraform apply
```

コマンド実行後、私の環境では以下のエラーが発生しました。

```bash
➜  terraform-ec2 git:(honda-branch) ✗ terraform apply
╷
│ Error: Failed to load plugin schemas
│ 
│ Error while loading schemas for plugin components: Failed to obtain provider schema: Could not load the
│ schema for provider registry.terraform.io/hashicorp/aws: failed to instantiate provider
│ "registry.terraform.io/hashicorp/aws" to obtain schema: timeout while waiting for plugin to start..
```

### 原因調査とエラー対応

最初は、プラグインのインストールが壊れている可能性があると疑い、インストール済みのプロバイダプラグインを削除し、再度インストールしてみましたが、解決はしませんでした。

結果的には、Terraformのキャッシュをクリアしてから、再度初期化と適用を試すことで事象は改善されました。

```bash
rm -rf ~/.terraform.d/plugin-cache/
terraform init
terraform apply
```

その後は、再度、``terraform apply``コマンド実行後に、正常に対象のリージョンに1台のEC2インスタンスが作成されていることが確認できました。

```bash
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.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Creation complete after 16s [id=i-0fb0543cec2e55494]

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

Terraformに関するエラー記事は少なく、トラブルシューティングに時間がかかってしまいました。

## 実行確認

では、実際にAWSのマネジメントコンソール上から確認していきます。

米国東部リージョンに「``example-instance``」という名前のEC2インスタンスが新規で構築されていることが正常に確認できました。

![スクリーンショット 2024-10-26 10.08.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c8ff94e5-f733-ac1f-1dc1-9fd15eacb5d1.png)

今回は、特に明示的にVPCやサブネットなどを指定していないため、基本的にデフォルトがそのまま使われていることも確認できました。

### 作成したリソースの確認と後片付け
不要になったらterraform destroyコマンドでリソースを削除します。

```bash
terraform destroy
```

コマンド実行後は、以下のように「``Destroy complete!``」と出力されていたら成功になります。

```bash
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.example: Destroying... [id=i-0fb0543cec2e55494]
aws_instance.example: Still destroying... [id=i-0fb0543cec2e55494, 10s elapsed]
aws_instance.example: Still destroying... [id=i-0fb0543cec2e55494, 20s elapsed]
aws_instance.example: Still destroying... [id=i-0fb0543cec2e55494, 30s elapsed]
aws_instance.example: Still destroying... [id=i-0fb0543cec2e55494, 40s elapsed]
aws_instance.example: Destruction complete after 43s

Destroy complete! Resources: 1 destroyed
```

実際のAWSマネジメントコンソール上でも、インスタンスが「**終了済み**」となっていることが確認できました。

![スクリーンショット 2024-10-26 10.28.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/f30d6578-ab2e-6887-252c-c67078400f53.png)

これでインフラのコード化は成功と言えますね！

また、過去の記事でもインフラのコード化としてAWS CloudFormationを使ってRDSパラメータグループとオプショングループを作成した記事がありますので、ぜひ読んでみてください。

https://qiita.com/free-honda/items/e972710ed65c5c4afb4e


## まとめ
以上の手順で、Terraformを使って対象のリージョンにEC2インスタンスを簡単に構築することができます。

:::note warn
**Terraformを利用すると、手動操作なしでインフラを構築・管理でき、インフラのコード化により一貫した設定が可能です。**
:::

今後も個人的に「Terraform」を積極的に利用していき、コードの書けるインフラエンジニアとして活躍していきたいと思います。

## 参考文献

https://qiita.com/souhei-etou/items/7876767f041543321006

https://qiita.com/free-honda/items/682e29d92e60e2d17681