Terraform getting-startedをやってみた

何番煎じかわかりませんがTerraformのgetting-startedをやってみました。
インストールからデストロイまでになります。

## インストール

2019/07/27

terraformの最新バージョンのURLを確認するには下記ダウンロードページからURLを調べる

```console:console
mkdir ~/.terraform
cd ~/.terraform
wget URL
unzip ダウンロードしたファイル
```

## PATH設定
terraformに対してPATHを通しておく

```
echo 'export $PATH:~/terraform'
```

## インストール確認
```console:console
terraform --version
Terraform v0.12.3
+ provider.aws v2.20.0

Your version of Terraform is out of date! The latest version
is 0.12.5. You can update by downloading from www.terraform.io/downloads.html
```
## アクセスキーの設定

terraformは下記の優先順位アクセスキーの情報を取得して認証を行う。
1. tfファイル
2. 環境変数 ```AWS_ACCESS_KEY_ID```、```AWS_SECRET_ACCESS_KEY```
3. ```~/.credential```

今回はterraform用のIAMユーザを発行するのでtfファイルを使用する。
じゃあ、tfファイルにアクセスキーを記載しよう！と思うところだがtfファイルを公開することがあると
アクセスキーがバレてしまうので変数を使用してアクセスキーは別ファイルに外だししたほうが良い。
変数の外だしはtfvarsファイルを作成する。
デフォルトではterraform.tfvarsを自動で読み込む。別名にする場合はコマンド実行時に```--var-file```で指定する必要がある。

```config:terraform.tfvars
my_region = "リージョン"
my_access_key = "アクセスキー"
my_secret_key = "シークレットキー"
```

変数は```"${変数名}"```で指定する
.tfファイル側でも変数を宣言する必要がある。
宣言は```variable 変数名 {}```

```
variable my_region {}
variable my_access_key {}
variable my_secret_key {}

provider "aws" {
  access_key = "${var.my_access_key}"
  secret_key = "${var.my_secret_key}"
  region     = "${var.my_region}"
}
```

チュートリアルに記載されていたami-idは使えなかったのでAmazonLinux2のamiを適当に使う

```
resource "aws_instance" "example" {
  ami = "ami-0c3fd0f5d33134a76"
  instance_type = "t2.micro"
}
```

最終的には下記のようになった。

```config:example.tf
variable my_region {}
variable my_access_key {}
variable my_secret_key {}

provider "aws" {
  access_key = "${var.my_access_key}"
  secret_key = "${var.my_secret_key}"
  region     = "${var.my_region}"
}

resource "aws_instance" "example" {
  ami = "ami-0c3fd0f5d33134a76"
  instance_type = "t2.micro"
}
```

## 初期化
下記コマンドで初期化を行う

```
terraform init
```

## 実行
terraform applyを実行するとdiffのような形式で作成されるリソースが+付きで表示される。
Enter a value:に対して```yes```で応答する。

```console:console
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.example will be created
  + resource "aws_instance" "example" {
      + ami                          = "ami-0c3fd0f5d33134a76"
      + arn                          = (known after apply)
      + associate_public_ip_address  = (known after apply)
      + availability_zone            = (known after apply)
      + cpu_core_count               = (known after apply)
      + cpu_threads_per_core         = (known after apply)
      + get_password_data            = false
      + host_id                      = (known after apply)
      + id                           = (known after apply)
      + instance_state               = (known after apply)
      + instance_type                = "t2.micro"
      + ipv6_address_count           = (known after apply)
      + ipv6_addresses               = (known after apply)
      + key_name                     = (known after apply)
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      + primary_network_interface_id = (known after apply)
      + private_dns                  = (known after apply)
      + private_ip                   = (known after apply)
      + public_dns                   = (known after apply)
      + public_ip                    = (known after apply)
      + security_groups              = (known after apply)
      + source_dest_check            = true
      + subnet_id                    = (known after apply)
      + tenancy                      = (known after apply)
      + volume_tags                  = (known after apply)
      + vpc_security_group_ids       = (known after apply)

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + iops                  = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (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

```

応答後、作成開始する。作成にかかった時間も表示される。

```console:console
aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Still creating... [20s elapsed]
aws_instance.example: Still creating... [30s elapsed]
aws_instance.example: Creation complete after 32s [id=i-xxxxxxxxxxxxxxxxx]

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

## 状態確認

terraform showコマンドで現在の状態を確認することができる

```console:console
terraform show
# aws_instance.example:
resource "aws_instance" "example" {
    ami                          = "ami-0c3fd0f5d33134a76"
    arn                          = "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-xxxxxxxxxxxxxxxxx"
    associate_public_ip_address  = true
    availability_zone            = "ap-northeast-1a"
    cpu_core_count               = 1
    cpu_threads_per_core         = 1
    disable_api_termination      = false
    ebs_optimized                = false
    get_password_data            = false
    id                           = "i-xxxxxxxxxxxxxxxxx"
    instance_state               = "running"
    instance_type                = "t2.micro"
    ipv6_address_count           = 0
    ipv6_addresses               = []
    monitoring                   = false
    primary_network_interface_id = "eni-xxxxxxxxxxxxxxxxx"
    private_dns                  = "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal"
    private_ip                   = "xxx.xxx.xxx.xxx"
    public_dns                   = "ec2-18-182-16-157.ap-northeast-1.compute.amazonaws.com"
    public_ip                    = "xxx.xxx.xxx.xxx"
    security_groups              = [
        "default",
    ]
    source_dest_check            = true
    subnet_id                    = "subnet-xxxxxxx"
    tenancy                      = "default"
    volume_tags                  = {}
    vpc_security_group_ids       = [
        "sg-xxxxxxxx",
    ]

    credit_specification {
        cpu_credits = "standard"
    }

    root_block_device {
        delete_on_termination = true
        iops                  = 100
        volume_id             = "vol-xxxxxxxxxxxxxxxxx"
        volume_size           = 8
        volume_type           = "gp2"
    }
}
```

# リソースの変更
リソースの変更を行うにはまずtfファイルを編集する。
AmazonLinux2 から AmazonLinuxに変更する
\#でコメントアウト可能

```config:example.tf
resource "aws_instance" "example" {
#  ami = "ami-0c3fd0f5d33134a76"
  ami = "ami-04b2d1589ab1d972c"
  instance_type = "t2.micro"
}
```

変更後terraform applyを実行する。

```console:console
terraform apply
aws_instance.example: Refreshing state... [id=i-xxxxxxxxxxxxxxxxx]

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

Terraform will perform the following actions:

  # aws_instance.example must be replaced
-/+ resource "aws_instance" "example" {
      ~ ami                          = "ami-0c3fd0f5d33134a76" -> "ami-04b2d1589ab1d972c" # forces replacement
      ~ arn                          = "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-xxxxxxxxxxxxxxxxx" -> (known after apply)
      ~ associate_public_ip_address  = true -> (known after apply)
      ~ availability_zone            = "ap-northeast-1a" -> (known after apply)
      ~ cpu_core_count               = 1 -> (known after apply)
      ~ cpu_threads_per_core         = 1 -> (known after apply)
      - disable_api_termination      = false -> null
      - ebs_optimized                = false -> null
        get_password_data            = false
      + host_id                      = (known after apply)
      ~ id                           = "i-xxxxxxxxxxxxxxxxx" -> (known after apply)
      ~ instance_state               = "running" -> (known after apply)
        instance_type                = "t2.micro"
      ~ ipv6_address_count           = 0 -> (known after apply)
      ~ ipv6_addresses               = [] -> (known after apply)
      + key_name                     = (known after apply)
      - monitoring                   = false -> null
      + network_interface_id         = (known after apply)
      + password_data                = (known after apply)
      + placement_group              = (known after apply)
      ~ primary_network_interface_id = "eni-xxxxxxxxxxxxxxxxx" -> (known after apply)
      ~ private_dns                  = "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal" -> (known after apply)
      ~ private_ip                   = "xxx.xxx.xxx.xxx" -> (known after apply)
      ~ public_dns                   = "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com" -> (known after apply)
      ~ public_ip                    = "xxx.xxx.xxx.xxx" -> (known after apply)
      ~ security_groups              = [
          - "default",
        ] -> (known after apply)
        source_dest_check            = true
      ~ subnet_id                    = "subnet-xxxxxxxx" -> (known after apply)
      - tags                         = {} -> null
      ~ tenancy                      = "default" -> (known after apply)
      ~ volume_tags                  = {} -> (known after apply)
      ~ vpc_security_group_ids       = [
          - "sg-xxxxxxxx",
        ] -> (known after apply)

      - credit_specification {
          - cpu_credits = "standard" -> null
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_interface_id  = (known after apply)
        }

      ~ root_block_device {
          ~ delete_on_termination = true -> (known after apply)
          ~ iops                  = 100 -> (known after apply)
          ~ volume_id             = "vol-xxxxxxxxxxxxxxxxx" -> (known after apply)
          ~ volume_size           = 8 -> (known after apply)
          ~ volume_type           = "gp2" -> (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 1 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:
```
## リソースの破棄
リソースの破棄を行うには```terraform destroy```を実行する。

```console:console
terraform destroy
aws_instance.example: Refreshing state... [id=i-xxxxxxxxxxxxxxxxx]

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

Terraform will perform the following actions:

  # aws_instance.example will be destroyed
  - resource "aws_instance" "example" {
      - ami                          = "ami-xxxxxxxxxxxxxxxxx" -> null
      - arn                          = "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxxx:instance/i-xxxxxxxxxxxxxxxxx" -> null
      - associate_public_ip_address  = true -> null
      - availability_zone            = "ap-northeast-1a" -> null
      - cpu_core_count               = 1 -> null
      - cpu_threads_per_core         = 1 -> null
      - disable_api_termination      = false -> null
      - ebs_optimized                = false -> null
      - get_password_data            = false -> null
      - id                           = "i-xxxxxxxxxxxxxxxxx" -> null
      - instance_state               = "running" -> null
      - instance_type                = "t2.micro" -> null
      - ipv6_address_count           = 0 -> null
      - ipv6_addresses               = [] -> null
      - monitoring                   = false -> null
      - primary_network_interface_id = "eni-xxxxxxxxxxxxxxxxx" -> null
      - private_dns                  = "ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal" -> null
      - private_ip                   = "xxx.xxx.xxx.xxx" -> null
      - public_dns                   = "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com" -> null
      - public_ip                    = "xxx.xxx.xxx.xxx" -> null
      - security_groups              = [
          - "default",
        ] -> null
      - source_dest_check            = true -> null
      - subnet_id                    = "subnet-xxxxxxxx" -> null
      - tags                         = {} -> null
      - tenancy                      = "default" -> null
      - volume_tags                  = {} -> null
      - vpc_security_group_ids       = [
          - "sg-xxxxxxxx",
        ] -> null

      - credit_specification {
          - cpu_credits = "standard" -> null
        }

      - root_block_device {
          - delete_on_termination = true -> null
          - iops                  = 100 -> null
          - volume_id             = "vol-xxxxxxxxxxxxxxxxx" -> null
          - volume_size           = 8 -> null
          - volume_type           = "gp2" -> null
        }
    }

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

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.example: Destroying... [id=i-xxxxxxxxxxxxxxxxx]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 10s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 20s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 30s elapsed]
aws_instance.example: Destruction complete after 35s

Destroy complete! Resources: 1 destroyed.
```

## 参考
https://dev.classmethod.jp/cloud/aws/terraform_getting-started/
https://qiita.com/kohey18/items/38400d8c498baa0a0ed8