Terraform入門！それほど敷居は高くない！〜AWSのProviderをベースに〜

# 前書き

- terraformはあくまでインフラリソース管理のためツールの一種だと思うので、何かの言語やフレームワークを習得するよりも敷居はそれほど高くない（はず）なので啓蒙できればなあと。
- もともとアプリケーションエンジニアですが、インフラをさわることが多くなってきたのでできるところからOut Putしようかなと（あと最近転職活動しはじめたのですが、それ用のアウトプットなかったのでちょこちょこやっていこうかなと。。。w）。
- 具体的な手順の解説とかはあまりしてないです、概要と全体像をイメージしてもらえればなと思ってます。
- ノリと勢いで書いているところがあるので、鵜呑みにしないでね☆

# “Terraform” is 何

- IaCの一つ

※IaCとはいんふらすとらくちゃーあずこーどの略で、要するに「インフラの構成とか設定をコード管理して専用のソフトウェアから実行して構築とか運用を自動化しようぜ」という概念（しらんけど）。

- HashiCorp社によって開発された。
- 設定ファイル形式はHCLという独自言語によって作られている。
- IaCサービスは [AWS Cloud Formation](https://aws.amazon.com/jp/cloudformation/) とか [Deployment Manager](https://cloud.google.com/deployment-manager/docs/fundamentals?hl=ja)tとか他にも色々ある。
- 対象のクラウドサービスがAWS限定、とかGCP限定などではなく、幅広くterraformによって取り扱うことができるのが利点の一つである。

# セットうp

- 公式インストールを見よ。

https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started

# 始めようTerraform

## ◾️ 最低限必要だと思われること

- terraformがinstallされている。
- aws cli がinstallされている。
- AWSアカウントが用意されている（および自身のIAMがある）。
- （ゆえに）AWSクレデンシャルを把握している。

## ◾️ 設計について

- 小規模、中規模、大規模など案件規模によって様々。

設計パターンのイメージは以下の動画がわかりやすかった気がします。

「それ、どこに出しても恥ずかしくないTerraformコードになってるか？」

https://www.youtube.com/watch?v=0IQ4IScqQws](https://www.youtube.com/watch?v=0IQ4IScqQws

## ◾️ terraformでインフラリソースをつくる流れ

1. tfファイルの実装 & `terraform init` でディレクトリの初期化
2. `terraform plan` で実行計画を確認
3. `terraform apply` で実行

詳細は後述。

要するにリソース作成（変更）のために「初期化＆コードの実装」 ⇒ 「実行しても問題がないか確認」 ⇒ 「実行」

というざっくり3ステップでリソースができるというイメージ。

下記画像のソースは公式から引用。

https://learn.hashicorp.com/tutorials/terraform/infrastructure-as-code?in=terraform/aws-get-started](https://learn.hashicorp.com/tutorials/terraform/infrastructure-as-code?in=terraform/aws-get-started

![terraform-iac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525590/cb7ce7dc-0679-cb1e-34fe-4cafd1fd6e30.png)


## ◾️ 前提

- terraformの実行はディレクトリ単位で行われる。
- つまり `hogehoge-infrastructure`というディレクトリ内に、`ecs2.tf` 、`s3.tf`、`iam.tf`というtfファイルがあったとして、この配下で `terraform plan`などのコマンドを実行すると全てのファイルを対象にコマンドが走る。

## ◾️ 初期化について

- `terraform init`でディレクトリを初期化します。前述したようにterraformの実行単位がディレクトリなので、ディレクトリごとにこれをやる必要があります。この操作により、指定したproviderが隠しサブディレクトリにインストールされます。また、version指定のためのロックファイルも作成されます（.terraform、.terraform.lock.hcl）。

## ◾️ terraform planについて

- どのリソースが追加されるのか、変更されるのか、削除されるのかといった差分を検出できます。

## ◾️ terraform applyについて

- どのリソースが追加されるのか、変更されるのか、削除されるのかといった情報に基づき実際にそのリソース変更を実行します（ワンライナーでポチッといくと危険なためか、一応インタラクティブに「本当にやるんすか〜？」といったような確認はしてくれます。）。

```go
terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                          = "ami-830c94e3"
      + arn                          = (known after apply)
##...

Plan: 1 to add, 0 to change, 0 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と打てば実行される
```

## ◾️ tfファイルについて

- .tfというファイル拡張子でファイルを作る。
- リソース単位でファイルを分けるのが一般的？っぽい（ec2.tf、s3.tfとか）

例）ec2.tf

```go
resource "aws_instance" "app_server" {
  ami           = "ami-830c94e3"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}
```

`resource "リソース名（これはproviderによって固定）　”リソース名”{`

という書き方になっているが、つまりこれは「EC2をappserverというリソース名で立てます。」ということ。

こういったように、基本的に resource blockで定義したリソースタイプ（aws_instance）をどういったリソース名（app_server）を定義し、block内に各リソースタイプで必要な定義を組み込んでいく流れ。

- はじめにterraform利用の設定を行うファイルが必要

main.tf（config.tfなどもあり）

```go
teffaform {
	// 使用するproviderの読み込み
	required_providers {
		source  = "hashicorp/aws" // providerの指定
      version = "~> 3.27" // versionの指定
	}
}

// 指定したproviderの構成
provider "aws" {
	region = "ap-northeast-1" // リージョンの指定
}
```

どのtfファイルで定義しても良いが、管理の都合上分けておくと良いかと思われる。

## ◾️ ステートファイルについて

これまで言及していなかったですが、ステートファイルというterraformにおいて、最も大事といっても過言ではない概念があります。

- ステートファイルとは？

リソースの状態管理のためのファイルです。terraformでは定義したコードと実際に存在しているリソースの差分をくらべ、しかるべき挙動で実行されます。ただし、「実際のリソースと」と言ってますが、実際にリソースを見に行っているわけではなく、実際にリソースを作った際（applyした際）に書き込まれるリソース情報を集約したステートファイルとの差分をみています。

- ファイルの内容について

対象リソース情報がjson形式で書かれています。こちらの記事がわかりやすいです。

https://qiita.com/masaaania/items/0ed291b267032a7699ad

- なぜステートファイルによる状態管理が必要なの？

実際の存在しているリソースとのマッピング、パフォーマンス、共同作業時のロックなどが理由としてあげられます。詳細は公式を参照。

https://www.terraform.io/language/state/purpose

- デフォだとterraform.tfstateというファイル名でローカルに保存される

ただ、これだと共同作業をする際に各々手元のステートファイルしかみれなくなり、整合性がとれなくなってしまうので、チーム開発においてはステートファイルをリモートで管理するのが望ましいです。AWSであればS3など。

main.tf

```go
terraform {

	...

  // 下記を追記
  backend "s3" {
    bucket = "mybucket" // バケット名
    key    = "path/to/my/key" // ステートファイル名
    region = "ap-northeast-1" // リージョン名
  }
}
```

# 補足

- リソースつくるベースで説明しましたが、基本的に更新も同じ要領です。applyで差分検出していいかんじに変更してくれます。
- リソースの破壊はdestroyコマンドがありますが、結構危険なコマンドで、運用時にはあまり使わないかと思うので、割愛してます。
- 一旦基本的なことは以上かと思いますので、Tips等気が向けばあげて行きます☆