Terraformを2ヶ月学んで覚えたことを自分なりにoutputする(基礎編)

自分がこの2ヶ月前後で学んだ内容について記載します｡(基礎編｡ 長くなるため､応用的な話はまた次回｡)
ただ､個人的主観も入れてあるため､何かあれば突っ込んでもらえるとありがたいです｡
また､基本的な話しかしない(これを読むと､何が書かれているのかが少しでもわかるようになる想定です｡)ため､突っ込んだ話はやりません｡ 興味がある方は教科書を読んでみるといいです(わかりやすくてすごくおすすめ)



## 使った教科書

- [pragmatic terraform on aws](http://pragmatic terraform on aws)
- [実践Terraform](https://www.amazon.co.jp/実践Terraform-AWSにおけるシステム設計とベストプラクティス-技術の泉シリーズ（NextPublishing）-野村-友規/dp/4844378139) 

実践TerraformはPragmatic terraform on AWSの増量版(カラー印刷)｡
なので､買うなら実践Terraformをおすすめする｡

##  基礎的なお話

### 単語の名称について

以下の単語を多用するため､事前にその意味を記載する

- provider
  - 使用するサービスのこと｡ AWSやGCPなどを指す｡
- resource
  - EC2やECSなどユーザがコンソール上で操作できる要素を指す｡

### tfStateファイルについて

- terraformの構成を記述したファイル｡ `.terraform/`にあります
- このファイルをもとにresourceの追加や削除が行われるため､基本的には触らないのがおすすめ｡

### 使用するコマンドについて

- terraform init
  - まずはじめに実行するであろうコマンド｡
  - terraformで設定している内容(providerやbackendなどの設定)の初期化を行ってくれる｡
  - ちなみにproviderやbackendを変更したときは必ず実行しないといけない
- terraform plan
  - 書いたterraformコードをもとに実行計画(providerでどう反映されるかをまとめたもの)が作られる｡
  - 実行計画の見方
      - `+`は`resource`が追加される
      - `-`は`resource`が削除される
      - `-/+`はresourceが再構築される(※この変更が一番危険なため､出てたら要注意)
  - 反映自体はまだされないので､安心して実行しよう｡
- terraform apply
  - 実際にproviderに反映する｡
  - Terraform applyして初めて気づくエラーも多々ある(例: サブネットの競合など)
  - やるときは実行計画を入念に確認して実行しよう
- terraform destory
  - terraformで構築した内容をすべて削除する
  - terraformで構築した箇所をprovider側で変更した場合､削除できなくなるので注意

### コードで記載する内容について
- 基本的な構文
  以下の通り｡

  ```terraform
  定義する要素 "要素の名前(何でもOK)" {
    オプション = "値"
  }
  ```

- providerについて
  - terraformで使用するproviderを設定する｡

  ```terraform
  provider "aws" {
    region = "ap-northeast-1"
  }
  ```

- backendについて
  - tfstateファイルをproviderのステート管理サービスに格納することができる
  - このメリットについてはリモートステートを参照｡

  ```terraform
  terraform {
    backend "s3" {
      region = "ap-northeast-1"
      bucket = "hoge-terraform"
      key    = "hoge-network.tfstate"
    }
  }
  ```

- resourceについて
  - EC2やECSなどユーザがコンソール上で操作できる要素を構成する｡
  - 主にresourceを記述して､設定を入力していく｡

  ```terraform
  // サブネットを構成するresource
  resource "aws_subnet" "hoge_subnet" {
    count                   = 1
    vpc_id                  = 'hogehoge'
    availability_zone       = 'hogehoge'
    cidr_block              = '10.12.111.111'
    map_public_ip_on_launch = false
  
    tags = {
      Name = hoge_subnet
    }
  }
  ```

  

- dataについて
  - providerにある既存のリソースを取得できるブロック｡
  - 既存のリソースのidを参照して構築したい場合に使用する

  ```terraform
  data "terraform_remote_state" "データ名" {
    backend = "s3"
  
    config = {
      region = "ap-northeast-1"
      bucket = "hoge-hoge-terraform"
      key    = "hoge-vpc.tfstate"
    }
  }
  ```

  

- variableについて
  - terraformで設定できる変数｡
  - 実行時に変数の上書きが可能｡(コマンド実行時に変数を設定して実行することができるため)
  - 変数の実体はtfvarsで管理する(詳しくは応用的な話を参照)
  - たとえ自明であってもdescriptionはつけておくことをおすすめする｡
  - 変数がどの型で来るのかを明示的に表示させることも可能(バリデーションの役割にもなる)
  - 型は以下の通り(あくまで一例｡ 詳しくは[こちら](https://www.terraform.io/docs/configuration/variables.html#type-constraints)を参照)
      - string
      - number
      - bool
      - List(Type) 

  ```terraform
  variable "変数名" {
    description = "設定する環境の接頭語"
    type = string
  }
  ```

- localについて
  - terraformで設定できる変数
  - variableとは違い､コマンド実行時に上書きできない変数｡

  ```terraform
  locals {
    hogehoge = "hoge"
  }
  ```
- outputについて
  - resourceの実行結果を表示するブロック｡
  - 後述するmoduleの値から値を取得したいときに使用される
  - descriptionはつけておいたほうがいい(なんの値なのかを明示させるため)

  ```terraform
  output "hogehoge_subnet_id" {
    description = "hogehoge用プライベートサブネットのid"
    value       = aws_subnet.hoge_private_subnet.id
  }
  ```

- moduleについて
  - resource, dataなどの塊を再利用可能にさせるために使用する｡
  - 読み込むリソースのパス､ module内で使用されているvariableを設定し､構築できる

  ```terraform
  module "manage_public_subnet" {
    source                 = "./hoge"
    name                   = hoge
    vpc_id                 = "hogehoge"
    availability_zones     = "hogehoge"
    cidr_blocks            = ["10.10.111.111", "10.10.111.112"]
    gateway_id             = "hogehoge"
    destination_cidr_block = "10.11.111.111"
  }
  ```

以上｡
応用的な話はまた次回書きます｡