AWS Route53(DNS)をTerraformで操作

## 概要
Terraform を使い、Route 53 の DNS の設定変更を試みる。AWS Management Console を使用せず、ゾーン情報の登録やレコードの追加／削除を行う事を確認する。なお、作業は全て Terraform から実施する。

## 事前準備

* Terraform の動作環境

## ゾーン情報の追加

同一ディレクトリに認証情報を定義した `aws_region.tf` と、ゾーン情報を定義する `aws_route53.tf` を作成する。また、ここで使用するドメイン名は `over.moe` とするが、任意のドメイン名を利用可能である。

```file:aws_region.tf
provider "aws" {
    access_key = "自分のアクセスキー"
    secret_key = "自分のシークレットキー"
    region = "us-east-1"
}
```

```file:aws_route53.tf
resource "aws_route53_zone" "over_moe" {
   name = "over.moe"
}
```

これは、`aws_route53_zone`というリソース名に対し、`over_moe`というリソース名称を割り当てている。`name` で指定するのは、実際に使用するドメイン名 `over.moe` を指定する（例：`example.jp`等をここへ書くこと）。

設定を適用する前に、計画 `terrafrom plan` を実行し、変更内容を確認する。

```
$ ./terraform plan
Refreshing Terraform state prior to plan...


The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ aws_route53_zone.over_moe
    name:    "" => "over.moe"
    zone_id: "" => "<computed>"
```

この表示内容は、リソース`aws_route53_zone.over_moe` を `+`(追加)する事を意味しており、実際に追加するドメイン名は `over.moe` である。

設定を反映(apply)するためには、`terraform apply` を実行する。

```
$ ./terraform apply
aws_route53_zone.over_moe: Creating...
  name: "" => "over.moe"
aws_route53_zone.over_moe: Creation complete

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate
```

実行すると十数秒程度の待機の後、画面に処理結果が表示される。結果に `1 added` と表示されており、正常に処理が完了した。

処理結果の詳細は、`terraform show` で確認できる。

```
$ ./terraform show ./terraform.tfstate
aws_route53_zone.over_moe:
  id = ZNUSNIH3530EG
  name = over.moe
  zone_id = ZNUSNIH3530EG
```

これで、AWS Management Console を使わずにゾーン情報の登録が完了している。画面を確認すると、ドメイン情報が確認できるほか、対象のドメイン名の Comment には `Managed by Terraform` と書かれている。

![Route53でドメインを追加した直後.png](https://qiita-image-store.s3.amazonaws.com/0/13002/1d7e4c7f-c5fd-e1ec-95cf-ea3ff82d7704.png)

あとは、`NS` レコードを確認し、各レジストラのネームサーバの情報を更新し、ドメインの設定を反映出来るようにする。

## レコードの追加

ゾーン情報に引き続き、レコードの追加や変更も可能である事を確認する。レコード用のリソースを、先の `aws_route53.tf` に追加する。`www.over.moe` を定義するには、次のようにする

```
resource "aws_route53_zone" "over_moe" {
   name = "over.moe"
}

resource "aws_route53_record" "www" {
   zone_id = "ZNUSNIH3530EG"
   name = "www.over.moe"
   type = "A"
   ttl = "300"
   records = ["210.239.46.254"]
}
```

ここでは、リソース `aws_route53_record` に、`www` というリソース名を割り当てている。また、`zone_id` は先ほど確認したゾーン ID である。`name` は、`www.over.moe`を、`type` は `A` (Address) レコード、`TTL` は TTL 秒、そして、`records` に IP アドレスを記述する。

設定を適用する前に、`terraform plan` で変更内容を確認する。

```
$ ./terraform plan
Refreshing Terraform state prior to plan...

aws_route53_zone.over_moe: Refreshing state... (ID: ZNUSNIH3530EG)

The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ aws_route53_record.www
    name:      "" => "www.over.moe"
    records.#: "" => "1"
    records.0: "" => "210.239.46.254"
    ttl:       "" => "300"
    type:      "" => "A"
    zone_id:   "" => "ZNUSNIH3530EG"
```

このように `www.over.moe` という A レコードを追加しようとしている事が分かる。内容に問題が無ければ、適用`apply`を行う。

```
$ ./terraform apply
aws_route53_zone.over_moe: Refreshing state... (ID: ZNUSNIH3530EG)
aws_route53_record.www: Creating...
  name:      "" => "www.over.moe"
  records.#: "" => "1"
  records.0: "" => "210.239.46.254"
  ttl:       "" => "300"
  type:      "" => "A"
  zone_id:   "" => "ZNUSNIH3530EG"
aws_route53_record.www: Creation complete

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate
```

この段階で処理は成功し、AWS Management Console にも設定が反映している事が確認出来る。

![www.moeが追加されている.png](https://qiita-image-store.s3.amazonaws.com/0/13002/792e5539-2608-5cd1-eb4a-38ad62591528.png)

反映情報の確認は、`terraform show` からも確認する事ができる。

```
$ ./terraform show ./terraform.tfstate
aws_route53_record.www:
  id = ZNUSNIH3530EG_www.over.moe_A
  name = www.over.moe
  records.# = 1
  records.0 = 210.239.46.254
  ttl = 300
  type = A
  zone_id = ZNUSNIH3530EG
aws_route53_zone.over_moe:
  id = ZNUSNIH3530EG
  name = over.moe
  zone_id = ZNUSNIH3530EG
```

なお、レコードを削除したい場合、この `www.over.moe` の設定を削除して `plan` → `apply` を実行することになる。

更にレコードを追加したい場合は、`.tf` ファイルにリソースの追加を記述する。例えば、`game.over.moe` というレコードを追加したい場合は、次のように書き換える。

```file:aws_route53.tf
resource "aws_route53_zone" "over_moe" {
   name = "over.moe"
}

resource "aws_route53_record" "www" {
   zone_id = "ZNUSNIH3530EG"
   name = "www.over.moe"
   type = "A"
   ttl = "300"
   records = ["210.239.46.254"]
}

resource "aws_route53_record" "game" {
   zone_id = "${aws_route53_zone.over_moe.zone_id}"
   name = "game.over.moe"
   type = "A"
   ttl = "300"
   records = ["210.239.46.254"]
}
```

設定を反映させるには、`terraform plan` の後、エラーが無ければ `terraform apply` を実行する。実行して暫くすると、`dig`等で名前絵解決が出来るようになる。

```
$ dig game.over.moe a +norec

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.el6_5.1 <<>> game.over.moe a +norec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24365
;; flags: qr ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 4

;; QUESTION SECTION:
;game.over.moe.                 IN      A

;; ANSWER SECTION:
game.over.moe.          297     IN      A       210.239.46.254
```

なお、レコードの削除・追加を一度に行おうとすると、エラー `Error: Request failed, got status code: 400.` が出てしまう場合がある。 これは、直前のリクエストが終了しないうちに次のリクエストをおこなったためである。現行の Terraform では、削除は削除のタスク、追加は追加のタスクとして分けた方が良いと思われる。

## 参考

* AWS: aws_route53_record - Terraform
 * http://www.terraform.io/docs/providers/aws/r/route53_record.html

* AWS: aws_route53_zone - Terraform
 * http://www.terraform.io/docs/providers/aws/r/route53_zone.html