Terraform歴1ヵ月半で学んだ「Terraform基礎」

Terraform歴一か月半の私が、Terraformをこれから始めていきたいという方や、Terraformの使い方がよくわからないという方向けに、「Terraformの基礎部分」を書いていこうと思います。

## Terraformってなに？
インフラをコードで管理するものです。
インフラといえば、コンソールでポチポチして構築するイメージがあるかと思いますが、これをコードを書いて構築することができます。このような、コードを書いてインフラ構築するものをInfrastructure as Code（IaC）と言います。



## どうやって書くの？
書くコード自体は「Terraformの公式ドキュメント」を参考にします。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs

<br>

VPCを書きたい場合は、左側の検索から「vpc」と検索すればそれっぽいもの(aws_vpc)が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625477/6b07fc90-3c89-c1e6-6957-351eec436722.png)

<br>

公式ドキュメントは英語で初めは読みにくいかと思いますが、少しずつ翻訳すれば理解しやすくなるかと思います。
自分は**DeepL翻訳**という拡張機能を使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625477/dd2ee3bb-82a7-e517-66a1-ceea81c4f43d.png)

<br>

書き方は上部の「Example Usage」を参考にしながら書いています。初めは、とりあえずコードをコピーしておくのが良いかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625477/c75510d9-9bff-1528-b7da-0a7c7a1acc50.png)

<br>

下部の「Argument Reference」では、追加して設定したい項目を選択し、「Example Usage」のコードに追記していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625477/dc6ef204-63a8-b5d2-5c97-38956087e27a.png)

項目ごとに、これはtrueかfalseで書いてください、これらの値から選択してください、数値で書いてくださいなどの
指定があるのでそれに従って書きましょう。

<br>

他、設定するもので必須で書くものとオプションで書くものがあります。必須はRequired、オプションはOptionalという記載があります。必須のものは設定値に入れないとリソースが立ち上がらずエラーが出るので注意です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625477/89a76522-a056-8240-f40a-6de35b6c1c9f.png)


また、これらのリソースをどの環境に立てるのかというのも指定する必要があります。その時は、providerのファイルでAWSのどのリージョンに置くのかなどを指定することができます。



## コードを実行する
コードを書き終えたら、コードをコンソール上に反映させます。

自分は基本的に以下の4つを使っています。
- terraform init
- terraform plan
- terraform apply
- terraform destroy
<br>

**init**：ワークスペースを初期化するという意味があるらしく、これを実行することでデプロイに必要なファイルなどを自動的に用意してくれます。

**plan**：リソースの作成/変更/削除を表示してくれます。

**apply**：実際にデプロイを行います。
リソースが作成された後は、initした時に追加されたterraform.stateというファイルにリソースの情報が記載されます。

**destroy**：デプロイしたリソースを削除することができます。

自分もまだまだ勉強中の身ですが、こんな感じでなんとなく理解しています。


## Terraformをもっと使いやすくするために
ここではTerraformを見やすく、または使いやすくするために行った内容を書いていきます。
- module
- for_each
- target

<br>

**module**：すべてのリソースを1つのファイルに書くのではなく、moduleとしてリソースごとなどに分け、参照したものをメインのファイルに記載するという感じです。
moduleで変数を宣言しておき、その値をmainファイルで記載するというイメージです。
メリットは様々ですが、ファイルがリソースごとに分割されるため、構成が把握しやすくなり、可読性が上がります。また、変更があった場合に共通する値を変数で置き換えれば一箇所の変更で済みます。

下記はEC2のmodule例です。
```ruby:main.tf
  resource "aws_instance" "ec2svc01" {
       instance_type                        = var.instance_type
       ami                                  = var.ami
       subnet_id                            = var.subnet_id
       disable_api_termination              = true
       instance_initiated_shutdown_behavior = "stop"
  }
  ```
<br>

**for_each**：同じリソースをいくつも複製して作りたい！という場合に便利です。
ほぼ同じ内容なのにひたすら羅列して書くと、コードが下に長くなっていってしまいます。
そこでfor_eachを使うと、コードを短くしてスッキリ見せることができるのでとても便利です。

```ruby:書き方例
  resource "aws_s3_bucket" "test" {

       for_each    = var.s3_config
       bucket      = each.value.bucket_name
  }

  ```
<br>

**target**：コードを実行するときにオプションとして使います。
基本的に、plan/apply/destroyをすると、そのファイルに書いてあるすべてのコードが実行されてしまいます。
そのため、このリソースだけを立ち上げたいな～ていう時に役立ってくれるのがtargetです。

```ruby:書き方例
  terraform plan --target=module.mo_ec2
  ```

このようにtargetの後ろに立ち上げたいリソースを記載することで、そのリソースのみが立ち上がります。
どのように指定したらわからないという場合は、一度targetを指定せずにplanを実行し、その結果を見て指定すると良いかと思います。

## 最後に
実際にTerraformとコンソール両方で構築をして、やはりどちらにもメリット・デメリットがあるなと感じています。
Terraformは最初のうちは書くのが難しく、自分は一つのリソースに何日もかけていました。

しかし、一度リソースを書いてしまえば二回目の構築の時には「この設定値はこの項目」というのが理解できている状態なので大分早く構築できるものではないかと思います。
自分は実際にTerraformを触ってみて好きになった人間なので、この記事を読んで少しでも「Terraformを理解できた」「Terraformを触ってみたい」と思ってくれたら嬉しいです。