WordPressのREST APIを使ったSPAを作りたくて、TerraformでまずはAWS環境整えた話

## はじめに
こちらは[Amazon Web Services Advent Calendar 2016](http://qiita.com/advent-calendar/2016/aws)の23日目の記事です。

## 概要
タイトル通りですが、今回はAWSのアドベントカレンダーということで
「Terraformを使ったAWS環境構築」をターゲットとしたお話です。
WordPressのRESTAPIを使った云々の話は、また後日。

### Terraformとは？
https://www.terraform.io/

インフラ構成の定義を記述したテンプレートファイルをinputとし、
`terraform`コマンドを使ってAWS等のクラウド環境に構成反映してくれるツールです。

## 前提
- 開発環境にterraformをインストール済み
    - 筆者の環境は、v0.7.6
- AWSアカウント・環境構築用のIAM作成済み
    - アクセスキーを作成し、アクセスキー＋シークレットキーを控えておいてください
- 独自ドメイン取得済み
    - お名前.comでも、VALUE DOMAINでも、Route53でもどこで取ってもOK
- 独自ドメインのサーバ証明書をACM(AWS Certificate Manager)で作成
    - TerraformでACMの構成管理は出来ないようなので、証明書の作成はコンソールでポチポチと実施
    - admin@<独自ドメイン>等、管理者メールアドレス受信確認できること！
- EC2のキーペア作成済み

### 今回のゴール
最終的にはこんな環境が出来上がります。
![cloudcraft - WP-REST-API-SPA.png](https://qiita-image-store.s3.amazonaws.com/0/100077/e0a9d5a9-b3ee-2a12-0fca-8eebe8a7c5b1.png)

#### アクター
- public user: Webサイトにアクセスする一般ユーザー
- admin user: WordPressから記事を投稿するユーザー

#### AWS各サービスの立ち位置
- EC2: WordPress環境
- RDS: WordPressで利用するDB（MySQL）
- S3: フロントエンド側のコンテンツ配信用
    - EC2で設置したWordPressからREST APIでデータ取得して、Riot.jsやらReactやら何やら使ってSPA実装して、このS3へデプロイする想定
- CloudFront: キャッシュサーバ
    - ACMで作成した証明書を導入しhttps化
- Route53: 独自ドメイン管理

## 環境構築手順
以下全て、自分の開発環境で実施することが前提です。
筆者の場合はOS X El Capitanです。

### 1. リポジトリクローン
今回のterraformソースはコチラに用意しました。
https://github.com/K1-Style/aws-terraform-wp-front

```
git clone https://github.com/K1-Style/aws-terraform-wp-front.git
cd ./terraform
```

### 2. 環境変数ファイル（terraform.tfvars）作成
```
cp terraform.tfvars.sample terraform.tfvars
```
terraform.tfvarsに、以下ご自分の環境に沿った値を入れてください。

- aws_access_key: 前提で作成したIAMのアクセスキーID
- aws_secret_key: 前提で作成したIAMのシークレットキー
- aws_db_username: RDS rootユーザー名（任意）
- aws_db_password: RDS rootパスワード（任意）
- aws_db_wp: WordPress用のDB名（任意）
- aws_db_wp_username: WordPress用のDBユーザー名（任意）
- aws_key_name: 前提で作成したEC2のキーペア名
- ssh_key_file: 前提で作成したEC2のキーペアファイル名（例：**.pem など）
- bucket_name: S3のバケット名（前提で設定した独自ドメイン名にする）（任意）
- index: S3のindexファイル名（任意）
- acm_certificate_arn: 前提で作成したACM証明書のARN

↓以下は、すべて任意の名前を定義してください↓

- aws_vpc_name
- aws_subnet_public_name
- aws_subnet_private_db1
- aws_subnet_private_db2
- aws_internet_gateway_name
- aws_route_table_name
- aws_security_group_web_name
- aws_security_group_db_name
- aws_db_subnet_group_name
- aws_db_instance_identifer
- aws_instance_name

### 3. terraform.tfstate共有設定
Terraformで環境構築を実行すると、状態管理ファイルとして `terraform.tfstate` というファイルが作成されます。
デフォルトはローカルでこのファイルが作成されますが、Amazon S3 で管理する機能もterraformに備わっています。

この状態管理ファイル、むやみに公開できない情報がいっぱい含まれてますし
自分ひとりで構成管理するだけでなく、他の開発者やCIに構成管理を任せる場合も
S3上に共有できるようにしておくと良いです。

tfstateファイル管理用のバケットをS3上にあらかじめ作成しておいてください。
その後、下記コマンドを実行

```
terraform remote config -backend=S3 -backend-config="bucket=<tfstate共有用に作成したS3バケット名>" -backend-config="key=tf" -backend-config="region=<リージョン名>"
```
※リージョン名は、東京だとap-northeast-1

### 3. `terraform plan`(プレビュー実行)
```
terraform plan
```
この時点ではまだAWSへは反映されません。
想定される実行結果がずらずらとコンソール上に現れます。

#### plan実行時の注意！
今回の場合、EC2上でWordPress導入のプロビジョニングを行っているのですが
このプロビジョニング結果まではplanコマンドでは確認できません。
今回はterraformでまとめてEC2内のミドルウェア設定行ってますが、
この辺りはAnsibleとかを利用したほうが、よりテスト確認し易いと思われます。

### 4. `terraform apply`実行！
`terraform plan`で問題なければ、以下実行！

```
terraform apply
```


#### apply実行時の注意！
仮にapply実行中にエラーが発生した場合、
terraformの仕様で、ロールバックされません。
それまでに出来上がった環境はそのまま残ってますのでご注意を。

再度apply実行すると、差分のみ追加／変更が実施されます。

### 5. AWSコンソール上で実際出来ているか確認
まずはEC2上にWPを確認。
`http://<EC2のパブリックDNS>/wordpress/`にアクセス。WordPressの設定を促す画面が出てくることを確認します。

次に、S3＋CloudFrontのフロント側を確認。
Terraformで作成したS3バケットのルートにindex.htmlを配置。
前提で用意した独自ドメインにhttpsアクセスし、index.htmlの内容が反映されていることを確認します。

## 所感
terraform学習である程度時間は要しましたが、
一回定義してしまえば後々のAWS環境の管理が簡単に変更できて良いですね。

## 今後の課題（やりたいこと、やり残したこと）
- EC2上のWPを利用する人は限られているし、管理画面しか使用しないので、<br />
IP制限等セキュリティ設定ちゃんとしといたほうが良いかと
- CI使ってplanのテストやapplyの導入を自動化したい
- EC2は、PackerやAnsibleでAMIを作ってからインスタンス作るべきだったか。。 <br />
[参考][[初心者歓迎] Packer + Ansible + TerraformでWordPressを構築](http://qiita.com/jkkitakita/items/805bc6dcfebcdbd47c00)
- 環境整えたは良いけど、肝心のフロント側を実装せねば。。

## 参考にさせていただきました
- [TerraformだけでAWS環境にWordPressを構築する](http://qiita.com/toshihirock/items/6a46fcba165a0b34a1f4)
- [【速報】TerraformがCloudFrontに対応しました](http://dev.classmethod.jp/cloud/aws/terraform-v0-6-15-supports-cloudfront/)
- [Amazon S3 で Terraform の状態管理ファイル terraform.tfstate を管理 / 共有する](http://qiita.com/dtan4/items/04632f1c2f35388a3283)