TerraformでAWS環境構築まで

## 記事の目的
- Terraformについての学習備忘録用
- TerraformでAWS環境構築までのフローの振り返り用

## 前提条件
TerraformでAWS環境を構築するには最低でも以下の前提条件があります
- Terraform CLIをインストールしていること
- AWS CLIをインストールしていること
- AWS accountと関連する認証情報でリソースが作成できる状態にあること

## 記事の概要
- S3バケット作成（`.tfsatate`ファイル保存用）
- S3バケット参照設定
- `terraform init`（初期化）
- VPC構築をコードで記載
- サブネット構築をコードで記載
- `terraform plan`（実行内容確認）
- `terraform apply`（リソース構築実行）
- `terraform destroy`（リソース破棄）

Terraformとは何かなどの基本的な部分やインストールについては[Terraform基本的な説明](https://qiita.com/pikimaru/items/7c13dedf8449db04bd94)でまとめているので、こちらみてみて下さい:raised_hands:
[Terraform公式ドキュメント](https://www.terraform.io/)

## S3バケット作成（`.tfsatate`ファイル保存用）
Terraformで管理しているインフラソースをすべて記録している`.tfsatate`ファイルを保存しておくために、まずはS3バケットを先に作成していく必要があります
### AWS S3サービス画面に遷移しバケット作成を選択
上部の検索欄にS３と入力するとS3選択できS3画面に行けます
![スクリーンショット 2023-04-27 23.39.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/84f5a732-985d-81c4-6f0d-a2d6d8e01a88.png)
今回はテストように`.tfsatate`ファイルを保存したいだけなので、「バケット名」を入力したら他は特に変更せず「作成」を選択して作成しています
![スクリーンショット 2023-04-27 23.40.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/751f5dfe-eed0-9a22-4c55-5414c11c655e.png)
「作成」選択後下の画像のようにバケットが作成できているかと思います
![スクリーンショット 2023-04-27 23.41.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/542fdacc-9b55-afc8-44e1-627e8f1198ff.png)
これでTerraformで管理しているインフラソースをすべて記録している`.tfsatate`ファイルを保存するバケットの作成は完了になります


## S3バケット参照設定
作成したS3バケットを`.tfsatate`ファイルの保存場所に指定しますよ！という設定を行なっていきます。
### AWSプロバイダー情報を記載する`.tf`ファイルを作成
まずは、「作成したS3バケットを`.tfsatate`ファイルの保存場所に指定しますよ！」だったり、AWSプロバイダー情報などのインフラの構成記載するファイルを作成します。
ファイルを作成する場所については、好きなディレクトリを作成しその配下に好きな名前で`.tf`ファイルを作成していきます
今回は下記のような構成でディレクトリをファイルを構成しています。
```
terra
┗ backend.tf　　　　←追加
```
### S3バケットの設定
[Terraform公式ドキュメント（Amazon S3）](https://developer.hashicorp.com/terraform/language/settings/backends/s3)の「Example Configuration」部分をコピーして一旦`backend.tf`に貼り付けます
![スクリーンショット 2023-04-28 0.00.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/cf67b6e7-ccc6-2894-375c-d528a2930f84.png)
貼り付けた後、先ほど作成したバケット情報を設定していきます
- `required_version`　：　Terraformのバージョン指定　
- `bucket`　：　バケット名
- `key`　：　バケットのどこに保存するかの指定（今回はバケット直下にファイルを直接おくためファイル名記載しています）　
- `region`　：　AWS リージョン指定

※`required_version`については使用しているTerraformのバージョンを設定して下さい
```backend.tf
terraform {
    required_version = "1.4.6"　
  backend "s3" {
    bucket = "terraform-tfstate-pikimarutest"
    key    = "terraform.tfstate"
    region = "ap-northeast-1"
  }
}
```
これでどこに`tfstate`を置くかの設定が完了しました
### プロバイダーの設定
```
terra
┗ backend.tf
┗ provider.tf　　　　←追加
```
プロバイダーには`Microsoft Azure`、`Amazon Web Services（AWS）`、`Google Cloud Platform（GCP）`等ありますが今回はAWSであるので`backend.tf`と同じ階層に`provider.tf`を作成し、`provider.tf`内に下記を記載していきます
[Terraform公式ドキュメント（Provider Configuration）](https://developer.hashicorp.com/terraform/language/providers/configuration)
![スクリーンショット 2023-04-29 21.04.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/cfd31753-7d3c-1cc1-284a-ecd323a6ed88.png)
- `region`　：　AWS リージョン指定　
```provider.tf
provider "aws" {
  region = "ap-northeast-1"
}
```

## `terraform init`（初期化）
ターミナルで`backend.tf`が存在する階層で下記コマンドを実行
```
terraform init
```
初期化に成功するとしたの画像のように出てくるかと思います
![スクリーンショット 2023-04-29 21.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/7e68e370-8540-839c-aa2b-1223ddf45acc.png)
また、`backend.tf`と同じ階層に'.terraform'といディレクトリが作成されるかと思います
これで初期化が完了となります！！

### 【補足】エラーが出た場合
![スクリーンショット 2023-04-29 21.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/3f95e297-9ba2-cc8f-0528-0c2e0e7f96a1.png)
このようなエラーが出た場合、AWSアクセスキーIDとシークレットアクセスキーを設定する必要用があるので、下記のコマンドを実行しアクセスキーIDとシークレットアクセスキーを設定していきます
```
aws configure
```
上記コマンド実行すると下記が順番に表示されるかと思うのでそれぞれ入力していきます
```
AWS Access Key ID [None]: YOUR_ACCESS_KEY
AWS Access Key ID [None]: YOUR_SECRET_KEY
Default region name [None]: ap-northeast-1
Default output format [None]: json
```
- `AWS Access Key ID`　：　アクセスキーを入力
- `AWS Access Key ID`　：　シークレットアクセスキーを入力
- `Default region name`　：　`ap-northeast-1`と入力
- `Default output format`　：`json`と入力

※アクセスキーとシークレットアクセスキーについてはAWSのIAMから「アクセスキーを作成」にて作成した際に表示されるものを使用して下さい

## VPC構築をコードで記載
初期化ができたのでここから構築するサービスをコードで記載していきます
まずはVPCの構築内容を記載するので`vpc.tf`ファイルを作成します
```
terra
┗ terraform  ←初期化時に作成されています
┗ backend.tf
┗ provider.tf
┗ vpc.tf　　　　　　　　　　←追加
```
[Terraform公式ドキュメント（VPC）](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc)を参考に設定していきます
![スクリーンショット 2023-04-29 22.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/2d77af1d-f5dd-a5fd-411a-0780caf1b55b.png)
- `aws_vpc`　：　作成するサービスを指定している
- `pre`　：　名前の設定（好きな名前で良い）
- `cidr_block`　：　IPv4 CIDR ブロックの設定
- `pre-vpc`　：　タグの設定（好きな名前で良い）
```vpc.tf
resource "aws_vpc" "pre" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "pre-vpc"
  }
}
```
AWS上で作成する場合、赤枠の部分を上記で設定しています
![スクリーンショット 2023-04-29 22.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/828f815c-159c-7b9d-02a5-b4fc62f418a5.png)

## サブネット構築をコードで記載
初期化ができたのでここから構築するサービスをコードで記載していきます
まずはVPCの構築内容を記載するので`vpc.tf`ファイルを作成します
```
terra
┗ terraform  ←初期化時に作成されています
┗ backend.tf
┗ provider.tf
┗ vpc.tf　　　　　　　　　　
┗ subnet.tf　　　　　　　　←追加

```
[Terraform公式ドキュメント（subnet）](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet)を参考に設定していきます
![スクリーンショット 2023-04-29 22.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/2d77af1d-f5dd-a5fd-411a-0780caf1b55b.png)
- `aws_subnet`　：　作成するサービスを指定している
- `pre_1a`　：　名前の設定（好きな名前で良いが、アベイラビリティーゾーンが分かるような名前が良い）
- `vpc_id`　：　サブネットを作成するVPCの指定(先ほど作成したVPCの名前を`aws_vpc.名前.id`というふうに設定)
- `cidr_block`　：　IPv4 CIDR ブロックの設定
- `availability_zone`　：　アベイラビリティーゾーンの設定
- `pre-subnet`　：　タグの設定（好きな名前で良い）
```subnet.tf
resource "aws_subnet" "pre_1a" {
  vpc_id     = aws_vpc.pre.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "pre-subnet"
  }
}
```
AWS上で作成する場合、赤枠の部分を上記で設定しています
![スクリーンショット 2023-04-29 22.12.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/87f86033-2b1d-c3d8-a3ee-3237eed561f2.png)

## `terraform plan`（実行内容確認）
`terraform plan`はterraformで記載したコードの内容と管理されている`tfstate`の内容を比較して差分（変更内容）を出してくれます。
実行した際に構築する内容を確認する際に使用し、必ず下記コマンドを実行して内容確認を行います！
```
terraform plan
```
管理されている`tfstate`はまだないはずなので、ここまで記載したVPCとサブネットの２つを追加しますといった`Plan: 2 to add, 0 to change, 0 to destroy.`という文言が出ているかと思います
![スクリーンショット 2023-04-29 22.35.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/dd69d9a5-0066-0ccb-c1ce-f18754ec83ac.png)

### 【補足】構文チェック`terraform validate`
これは補足なので実行しなくても良いですが、下記のコマンドを実行することで
これまで書いたコードの記載方法等に間違えがないかを確認できます
```
terraform validate
```
問題なければ下のように表示されます。また問題があれば該当箇所を表示してくれるので修正します
![スクリーンショット 2023-04-29 22.42.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/ea8e5a1b-047a-3158-cfef-a7054cb32273.png)
`terraform plan`でもエラーは出してくれるので念の為実行する感じで問題なさそう、、

## `terraform apply`（リソース構築実行）
下記のコマンドで実際にこれまで記載したリソースの構築を実行します
```
terraform apply
```
コマンドを実行すると`terraform plan`同様変更内容が表示されるので、問題なければ「Enter a value:」の部分に`yes`を記載して実行します
![スクリーンショット 2023-04-29 22.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/dce78eee-f77e-47d4-283c-aa0dca05411a.png)
下のように表示されれば実行成功です！！
![スクリーンショット 2023-04-29 22.42.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/acc5583c-fa06-00c6-2222-c0c6d2a96612.png)
### AWS画面で確認
AWSコンソールに移動してVPCとサブネットを確認すると実際に作成されているかと思います:ok_hand:
![スクリーンショット 2023-04-29 22.53.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/c510deb8-85db-eda3-6334-0613d5bc48a4.png)
![スクリーンショット 2023-04-29 22.53.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/e8d71bbb-797c-2097-cf36-f59ecc333996.png)
最初の方で`.tfsatate`ファイルの保存先のS3バケット設定をしたバケットに行き「ダウンロード」を実行するとjsonファイルで構築した内容（terraformの全て）を確認することができます
![スクリーンショット 2023-04-29 23.06.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/63b8d9db-1688-e4c8-f41d-db857b4aca7d.png)

### 【補足】この状態で`terraform plan`
```
terraform plan
```
これは補足なので実行しなくても良いですが、現在の状態で再度上記のコマンドを実行すると
下のように表示され何も変更がなく管理ができていることを確認することができます！
![スクリーンショット 2023-04-29 23.02.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/6cf3531f-b500-dbd0-18d2-417fbb8b9a0f.png)

## `terraform destroy`（リソース破棄）
ここまでで、TerraformでAWS環境構築までを行なってきたのでここからはお片付けになります。
単純にこれまでTerraform記載したものを全て削除し`terraform plan`を実行すると削除できますが、
コードを残しておいてコマンドで削除する方法を行っていきます
下記のコマンドを実行することで、コード上にあるTerraformで管理している全てのリソースを削除することができます
```
terraform destroy`
```
コマンドを実行後、問題なければ「Enter a value:」の部分に`yes`を記載して実行します
**<font color="Red">当たり前ですが本当に削除されるので、削除時は確認を行なった上で削除するようにして下さい</font>**:disappointed_relieved:
![スクリーンショット 2023-04-29 23.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/47f25be8-7f7a-5b80-3bbb-4c3e4bb7b5d8.png)
下のように表示されれば削除完了になります。
![スクリーンショット 2023-04-29 23.24.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/f5eac4f6-0266-d494-2f19-6573891efeef.png)
コマンド一つで全て削除されるのは怖いですが、逆にコマンド一つで全て削除できるのはめっちゃ便利だなとも思います。
削除し忘れとかでコストが発生したりするするので:disappointed_relieved:
### AWS画面で確認
AWSコンソールに移動してVPCとサブネットを確認すると実際に削除されているかと思います
![スクリーンショット 2023-04-29 23.27.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/5f7e00e9-629a-d562-76ff-01a9b1050965.png)
![スクリーンショット 2023-04-29 23.28.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/22f13499-74bc-d87c-8238-1f57fafc5c13.png)

### 【補足】`terraform destroy -target=リソース.名前`
全てではなくて指定したものだけ削除したい場合は`terraform destroy -target=リソース.名前`コマンドを実行することで指定したリソースのみ削除することができます。
例として指定のサブネットのみ削除するコマンドを下記に記載しています
```
terraform destroy -target=aws_subnet.pre_1a
```