【備忘録】Terraform入門(Terraformとは〜基本的なEC2の作成)

# 1. 初めに
今の現場でterraformやchefといったIaCツールを使用する機会がありましたので、簡単な仕組みや環境構築方法などを調べてみました。
また、調べるだけでは徐々に記憶が薄れていってしまうので、Qiitaに残すことで後から見返す目的でもこちらにアウトプットをしていこうと思います。

## 1-1 Terraformとは
Terraformとは、 HashiCorp社によって開発された オープンソースのサービス で、 開発環境を効率的に構築できるIaC（Infrastructure as Code）ツールの一種です。クラウドサーバーなどシステム開発に必要なインフラを、コードを記述することにより自動で構築できます。また、インフラの構成管理などもTerraformのコードによる宣言が可能な事も特徴です。

[参照サイト](https://udemy.benesse.co.jp/development/system/what-is-terraform.html#:~:text=Terraform%E3%81%A8%E3%81%AF%E3%80%81%20HashiCorp%E7%A4%BE,%E8%87%AA%E5%8B%95%E3%81%A7%E6%A7%8B%E7%AF%89%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)
# 4 HCL2とは
HCL2= HashiCorp Language2
形式はjsonに類似
※以下jsonとの相違点
#(コメント)可能
キーバリューのくくり方　→ 　=
例: profile = "terraform"

ブロックタイプの種類
|種類  |説明 | 
|---|---|
|locals　|外部から変更不可のローカル変数|
|variable  |外から変更可能な変数  |
|terraform |terraformの設定 |
|provider |プロバイダ(今回はaws) |
|data |Terraformが管理していないリソースの取り込み|
|resource | terraform管理対象となるリソース
|output |外部から参照できるようにする値

# 5, ブロック
## resource ~terraform管理対象となるリソース~
※テンプレート
resource "第一引数(terraform内で定義されている)"　"第二引数(terraform内での一意の名称)" {
  リソース情報
}
```hcl:network.tf
resource "aws_subnet" "public_subnet_1a" {
  vpc_id                  = aws_vpc.vpc.id
  availability_zone       = "ap-northeast-1a"
  cidr_block              = "172.16.1.0/24"
  map_public_ip_on_launch = true

  tags = {
    Name    = "${var.project}-public_subnet_1a"
    Project = var.project
    type    = "public"
  }
}
```

## locals
外部から変更が不可能なローカル変数
```hcl
locals {
  profile = "terraform"
  region  = "ap-northeast-1"
}

resource "aws_instance" "hello-world" {
・・・
tags = {
    Name = "${local.profile}-${local.region}"
#${local.key}で記載する
```

## variable
外部から変更可能な変数
```hcl:/variables.tf
variable "project"#変数名{ 
    type = string #変数の型
    default = "test" #変数のデフォルト値
}
```
```hcl:./main.tf
tags = {
    Name = "${var.project}" 
}
#${var.変数名}で記載する
```

※変数の指定方法
1, 環境変数・・・TF_VAR_{変数名}
2, 変数ファイル・・・変数ファイルを用意(terraform.tfvars)
3, コマンド引数・・・-var {変数名}={value}, -var-file {FILE_PATH}
※1→2→3の順で優先順位が高くなる
→順番に書いた場合は後に書いたほうが上書きされる

<details><summary>データ型</summary>

## 1, プリミティブ
```hcl:variable.tf
variable "test" {
#string
    type    = string
    default = "Hello World"
#number
    type    = number
    default = 100
#bool (true or false)
    type    = bool
    default = true
}
```

## 2, 構造体
```hcl
# object({<NAME>=<TYPE>, ...})
variable "test" {
    type = object({
     name = string
     age  = number
})
    default = {
     name = "Yamada"
     age  = 35
username = var.test.name
userage  = var.test.age
    }
}
```
```hcl
# 配列の順番でどのような方が使うかが決められたデータ型
# tuple([<TYPE>, ...])
variable "test" {
    type = tuple([
     string, number
    ])
    default = [Yamada, 35] #N番目の型が指定される
}
username = var.test[0]
```

## 3, コレクション
```hcl
# 全て同じ型で指定される配列
# list(<TYPE>)
variable "test" {
    type = list(string)
    dafault = ["tanaka", "sato"]
username = var.test[0]
}
```
```hcl
#キーが文字列、バリューが指定された型となる配列
#map(<TYPE>)
variable "test" {
    type    = map(string)
    default = {
        "High"   = "X7.BMW"
        "Middle" = "X5.BMW"
        "Low"    = "X3.BMW"
    }
}
car = var.test.High
```
```hcl
#バリューの配列が排除される配列
#set(<TYPE>)
variable "test" {
    type    = set(string)
    default = [
        "Sato",
        "Ito",
        "Sato",
        "Ito",
    ]
}
```
</details>

```hcl:/variable.tf
variable "test" {
    type    = string
    default = "Nothing"
}
```
<details><summary>詳細説明</summary>

### 1, 環境変数
特徴：鍵情報などの秘密情報などを記載(ログが残らないため)
```
#環境変数を設定
export TF_VAR_test="Good Morning"
```
### 2, 変数ファイル
特徴：実行ファイルと変数を分けて管理することで、変更管理が容易
```hcl:/terraform.tfvars
#変数ファイルを設定
test = "Good Morning"
```
### 3, コマンドを使用
特徴：テスト的に変更したい時に使用する
```hcl:
terraform apply -var test="Good Morning"
```
</details>

## terraform
terraform全体に関わる設定を記載
Terraform, Provider(AWS, GCP,Azure etc.)のバージョン指定
```hcl:./main.tf
terraform {
    required_version = ">=0.13"
    required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "~>3.0"
        }
    }
}
```

## provider
使用する製品(aws等)を宣言し、接続環境の設定(profile、regionなど)を行う
```hcl:./main.tf
provider "aws" {
# ~/.aws/credentialで設定した値
  profile    = "terraform" 

#~/.aws/configで設定した値
  region     = var.region 
  access_key = var.access_key
  secret_key = var.secret_key
}
```
## data
Terraformの管理対象外のサービスを取り込む
```hcl:data.tf
# --------------------------
# ami情報取得
# --------------------------
data "aws_ami" "app" {
  most_recent = true
  owners      = ["self", "amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-kernel-5.10-hvm-2.0.*-x86_64-gp2"]
  }
  filter {
    name   = "root-device-type"
    values = ["ebs"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}
```

## 5-6 output
外部から参照できるようにする値