Terraform - CentOS 7 に Terraform をインストールして AWS へ接続

Terraform の道に入門しました。

事前の想定以上にとっつきずらくて戸惑ってますが、楽しいです。

## 前提条件

```bash
$ terraform -v
Terraform v0.11.13
+ provider.aws v2.6.0
```

## Terraform のインストール (CentOS 7)

Terraform のインストール方法は OS ごとに異なります。以下は CentOS 7 にインストールした際のコマンドです。

```bash
// 必要なソフトのインストール
$ sudo yum install wget unzip

// Package の取得
$ wget https://releases.hashicorp.com/terraform/0.11.13/terraform_0.11.13_linux_amd64.zip

// unzip してコマンドとして配置
$ sudo unzip ./terraform_0.11.13_linux_amd64.zip -d /usr/local/bin/

// バージョンの確認
$ terraform -v
```

Windows や Mac へのインストール方法は以下のサイトが参考になります。

- [Terraformインストール(Windows版) - Qiita](https://qiita.com/miwato/items/b7e66cb087666c3f9583)
- [Installation / インストール - Terraform for さくらのクラウド](https://sacloud.github.io/terraform-provider-sakuracloud/installation/)
- [Download Terraform - Terraform by HashiCorp](https://www.terraform.io/downloads.html)

## 初期設定

まずは Terraform を記載していくフォルダを作成します。

```bash:command
// Terraform の設定情報を配置するフォルダを作成・移動
$ mkdir terraform-dir && cd $_
```

私の場合は AWS の環境を構築したかったので、以下の設定を行いました。

```json:provider.tf
# 変数の設定
variable "aws_access_key" {}
variable "aws_secret_key" {}

# 変数を利用した provider の設定
provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region = "ap-northeast-1"
}
```

上記の `provider` 設定のうち、 変数化した `aws_access_key` と `aws_secret_key` に IAM の認証情報を設定する必要があります。

### 1) Terraformコマンドのオプションで値を渡す

次のように、コマンドのオプションとして値を渡すことができます。

```bash:command
$ terraform apply \
-var 'aws_access_key=AKIAXXXXXXXXXXXXXXXXXX' \
-var 'aws_secret_key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
```

### 2) 環境変数で値を渡す

次のように、 `TF_VAR_` に続いて `変数名` を付け加えた環境変数を設定することで、 `terraform`コマンドの実行時に、自動的に環境変数が読み込まれます。

```bash:command
$ export TF_VAR_aws_access_key="AKIAXXXXXXXXXXXXXXXXXX"
$ export TF_VAR_aws_secret_key="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
```

### 3) ファイルで値を渡す

次のように、 `terraform.tfvars` というファイルの中に設定をしておくと、コマンド実行時に変数が読み込まれます。ただし、この方法は非推奨となっているようです。

```json:terraform.tfvars
aws_access_key = "AKIAXXXXXXXXXXXXXXXXXX"
aws_secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
```

## 基本コマンド

認証情報と `provider` の設定が終わったら、 `terraform init` で初期化します。

```bash
// 初期化
$ terraform init

// ドライ・ラン
$ terraform plan

// 適用
$ terraform apply

// 削除確認
$ terraform plan -destroy

// 削除
$ terraform destroy
```

## workspace の選択

`workspace` という概念で、本番/検証/開発といった環境の概念を取り扱うことができるようになります。

```bash
// terraform workspace
// Usage: terraform workspace <subcommand> [options] [args]

// workspace の一覧を表示する
$ terraform workspace list

// workspace を選択する
$ terraform workspace select [NAME]

// workspace を作成する
$ terraform workspace new [NAME]

// workspace を削除する
$ terraform workspace delete [NAME]

// workspace を表示する
$ terraform workspace show
```

- [Command: workspace - Terraform](https://www.terraform.io/docs/commands/workspace/index.html)

今回は `develop` 環境を作成しました。

```
// develop 環境を作成し、選択
$ terraform workspace new develop
$ terraform workspace select develop
```

## 設定ファイルの作成

ここから細かい設定を記載していきます。

- [Terraform CLI Documentation - Terraform](https://www.terraform.io/docs/cli-index.html)
  - [Configuration Language - Terraform](https://www.terraform.io/docs/configuration/index.html)
  - [Terraform Commands (CLI)](https://www.terraform.io/docs/commands/index.html)
- [AWS Provider - Terraform](https://www.terraform.io/docs/providers/aws/index.html)

### Resources

構築対象のリソースを指定

```json
# Usage
resource "<resource type>" "<local name>" {
  # configuration arguments
  <argument> = "<value>"
}

# Example
resource "aws_instance" "web" {
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
}
```

### Input Variables

```json
variable "image_id" {
  type = string
}

variable "availability_zone_names" {
  type    = list(string)
  default = ["us-west-1a"]
}

# var.<NAME>
resource "aws_instance" "example" {
  instance_type = "t2.micro"
  ami           = var.image_id
}
```

### Output Values

```json
output "instance_ip_addr" {
  value = aws_instance.server.private_ip
}
```

### Data Sources

読み取り専用

```json
data "aws_ami" "example" {
  most_recent = true

  owners = ["self"]
  tags = {
    Name   = "app-server"
    Tested = "true"
  }
}
```

### Modules

```json
module "servers" {
  source = "./app-cluster"

  servers = 5
}
```

### Terraform Settings

```json
terraform {
  backend "s3" {
    # (backend-specific settings...)
  }
}
```


## 参考

- [How to Install Terraform on CentOS 7/Ubuntu 18.04 - LinOxide](https://linoxide.com/linux-how-to/how-to-install-terraform-on-centos-ubuntu/)
- [terraformでEC2+RDS+ElastiCacheを構築してみる(その1 EC2構築まで) - Qiita](https://qiita.com/masa3521/items/215fec35977adc9f0541)
- [既存のAWS環境を後からTerraformでコード化する - Developers.IO](https://dev.classmethod.jp/cloud/aws/aws-with-terraform/)
- [Terraform職人入門: 日々の運用で学んだ知見を淡々とまとめる - Qiita](https://qiita.com/minamijoyo/items/1f57c62bed781ab8f4d7)
- [俺が結論づけたterraformベスト・プラクティスとworkspaceとmodule考え方(AWS Provider編) - Qiita](https://qiita.com/gamisan9999/items/168ff29be70572de7602)
- [miso4ru/aws-terraform-template  - GitHub](https://github.com/miso4ru/aws-terraform-template)
- [Windowsホスト上のVagrantのシンボリックリンクフォルダでyarn installできない問題の解決 - Qiita](https://qiita.com/maikya_gu/items/8e313dcd50c39f5a4b0b)