EC2(amazon inux2)にterraform実行環境を構築する


誰でも環境が作れるEC2でterraformの環境構築・動作試験をしてみました。


# 環境構築
Terraform用のIAMユーザーの作成
Terraform用のIAMユーザーを作成します。以下URLを参考にしながらIAMユーザーを作成します。
今回はハンズオンなので、Admin権限を持つユーザーを作成します。
SecretAccessKey は再発行されないので、無くしてしまったらアカウントを作り直してください。

IAM ユーザーの作成 (コンソール)




# AWS CLI のインストール
AWS CLI をインストールし、設定を行います。
※pip3でawscliのアップグレードしたいのでそのモジュールらをインストールしていきます。


```
yum -y install python3         # パイソン3のインストール
yum -y install python-pip      # pipのインストール
pip3 install boto3             # boto3のインストール
pip3 install awscli --upgrade  # pip3でawscliのアップグレード
yum install git-all            # gitインストール
```


インストールが完了したら AWS CLI の設定を行い、AWS CLI が実行できることを確認します。

```
aws --version
aws configure
aws s3api list-buckets  # S3 のバケット一覧を表示するコマンド
```


# terraformをtfenvを介してインストール
Terraform は更新が早いため、気軽にバージョンを変えられるように tfenv を使うことが推奨。


```
git clone https://github.com/tfutils/tfenv.git ~/.tfenv        # gitによるtfenvインストール
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile

tfenv --version         # インストールされてるかの確認
tfenv list-remote       # インストール可能なバージョンをリモートから取得して列挙します。

tfenv install 0.12.5    # 0.12.5 をインストール

tfenv use 0.12.5        # 0.12.5を使用する
tfenv list            # インストール済み
terraform --version   # バージョン一覧

```


# terraformの動作テスト・まずはterraformでs3バケットを作ってみよう！


1.実行ファイルの作成

mkdir terra-test; cd terra-test
vi main.tf 

```main.tf 
terraform {
  required_version = ">= 0.12.5"
}

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

resource "aws_s3_bucket" "terraform_state" {
  bucket = "kaku-example-terraform-state"
  versioning {
    enabled = true
  }
}
```


```
terraform init
terraform plan
terraform apply
aws s3api list-buckets | grep バケット名
```




```
[root@ip-172-31-40-118 terra-test]# terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

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_s3_bucket.terraform_state will be created
  + resource "aws_s3_bucket" "terraform_state" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = "kaku-example-terraform-state"
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + versioning {
          + enabled    = true
          + mfa_delete = false
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
```




```
-----------------------
[root@ip-172-31-40-118 terra-test]# 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_s3_bucket.terraform_state will be created
  + resource "aws_s3_bucket" "terraform_state" {
      + acceleration_status         = (known after apply)
      + acl                         = "private"
      + arn                         = (known after apply)
      + bucket                      = "kaku-example-terraform-state"
      + bucket_domain_name          = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + versioning {
          + enabled    = true
          + mfa_delete = false
        }
    }

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

aws_s3_bucket.terraform_state: Creating...
aws_s3_bucket.terraform_state: Creation complete after 2s [id=kaku-example-terraform-state]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

Enter a value:と来たら 
yesと入力しないと適応されません。
作成がうまくいったかgrepで確認します。
aws s3api list-buckets | grep バケット名


# 作成したS3バケットでtfstateファイルを管理するよう設定する



```main.tf
terraform {
  required_version = ">= 0.12.5"
  backend "s3" {
    bucket = "kaku-example-terraform-state" # 作成したS3バケット
    region = "ap-northeast-1"
    key = "terraform.tfstate"
    encrypt = true
  }
}

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

resource "aws_s3_bucket" "terraform_state" {
  bucket = "kaku-example-terraform-state"
  versioning {
    enabled = true
  }
}
```


このbackendの記述を挿入してから、terraform initコマンドで
yesを行うことで、s3バケットにterraform.tfstateファイルがコピーされます。



# 作成したS3バケットを削除する

terraform destroy


--------------------------------------------------------
----------------------------------------------------------


### コマンド引数による指定
コマンド実行時 `-var` オプションを利用して値を指定する。
試しに `terraform plan -var 'foo=test-bucket'` を実行してみると、ちゃんと注入されている。

### 環境変数による指定
`TF_VAR_` のプレフィックスを付けて環境変数を設定すると、その値が変数にロードされる。
`TF_VAR_foo='env-test' terraform plan` を実行すると同様の結果が得られる。

### 設定ファイルによる指定
変数の値を指定する設定ファイルを作成し、`-var-file`で指定すると同様のことが出来る。

#### vars.tfvars
```hcl
foo = "tfvars-file"
```

`terraform plan -var-file=vars.tfvars` を実行すると同様の結果が得られる。

## 変数戦略/設計

Terrafromは `*.tf` ファイルを全て読み込むので、
変数定義を`variables.tf`などに記述しておき、
実行時に`-var-file`で値ファイルを指定して環境などを切り替えると良いかもしれない。

- `terrafrom plan -var-file=dev.tfvars`
- `terrafrom plan -var-file=prod.tfvars`

ディレクトリとか、ファイルはこんな感じにすると雰囲気はつかめると思う。

### `main.tf`
```hcl
provider "aws" { region = "ap-northeast-1" }
resource "aws_s3_bucket" "s3_bucket" {
  bucket = "${var.foo}"
  acl = "private"
}
```

### `variables.tf`
```
variable "foo" {}
```

### `dev.tfvars`
```
foo="dev-var"
```

### `prod.tfvars`
```
foo="prod-var"
```


## その他Tips

`default` を記述するとファイルを指定しなくてもそれになる。
また、`type` などで型も指定できる。
`description`で、変数の説明もかけるので書いたほうがいい。

```
variable "foo" {
  type = "string"
  default = "default-var"
  description = "Sample Variable"
}
```