Terraform初心者向け

# Terraform 導入のきっかけ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/57490a2f-fb7d-1af9-21d9-42e15b3bf696.png)

私が現在javaのバックエンド開発者として働いている[ZOYI Corporation](https://zoyi.co/ja)においても、[Channel Talk](https://channel.io/ja)の機能拡張により、これまで使っていたCloud Formationよりもより手軽に、そして可読性高くインフラのプロビジョニング※ができるサービスの需要が高まっていました。

※プロビジョニングとは、必要に応じてネットワークやコンピューターの設備などのリソースを提供できるよう予測し、準備しておくことです。供給や設備等の意味を表すプロビジョン（provision）という単語がもととなって派生した言葉です。（出典：https://www.idcf.jp/words/provisioning.html）

先日参加したAWS SummitにてTerraformの説明を受けて以降、本格的な導入に向けて勉強会をスタートしました。

---

# Terraformコマンド
Terraformで使用する基本コマンドは以下の三種類です
- Init → Providerなどのpluginをダウンロードし、ワークスペースを整備
- Plan → 実行計画・差分の確認(どのリソースが作成/修正/削除されるのか)
- Apply →　プロビジョン実行 
それぞれどのように活用するのか見ていきましょう

# 大まかな動作方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/675296c5-ed74-8b83-7790-25a8ea0eb041.png)

1. 拡張子が.tfのHCL codeを作成します。(json形式で記述したい場合の拡張子は.tf.json)こちらにプロビジョンの内容を記入します。
2. 作成したHCL codeに利用したサービスの**Provider**※をダウンロードします。弊社ではAWSのプロビジョンのコード化を検討しているため、AWSのProviderをダウンロードします。
3.AWSをProviderが実際にAWSが提供するインフラ構築用のAPIを叩き、プロビジョンを行います。

※Terraformに対応するProviderは以下の通りです。AWS以外にも様々なサービスをプロビジョンすることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/16d51831-0834-37c0-25dd-fdfcf45c2961.png)
(出典：https://www.terraform.io/docs/providers/index.html)

#アーキテクチャー
もう少し詳しくアーキテクチャーを見ていきましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/f0c07a3c-5bcc-eab8-abcc-0201ccf40c74.png)

1. 作成するHCL codeはTerraform Core上で動作します。
2. HCL codeに従って、該当サービス用の(今回はAWS)PluginsとしてProvidersとProvisionersをダウンロードします。以降、Terraform coreとPluginsはRPCによって通信します。
3. 共通の通信形式であるClient libraryを介し、Upstream APIsを叩くことでプロビジョニングを実現します。


# チュートリアル
TerraformによりAWSのEC2インスタンスとRDSを作成していきましょう。

## インストール
```terminal
brew install terraform 
```

##バージョン確認
```terminal
terraform --version
```

##Provider 設定
###HCL code作成
~/terraform/provider.tf(もしくはprovider.tf.json)というファイル名でコンフィグレーションファイルを作成していきます。
terraform formatもしくはjson形式で作成します。

```
provider "aws" {
 access_key = "your_aws_iam_access_key"
 secret_key = "your_secret_key"
 region = "ap-northeast-2" 
}
```
その他定義方法は[こちら](https://www.terraform.io/docs/providers/aws/index.html)を参照

###initコマンド実行
```terminal
$ terraform init
```

コマンド実行するとこのようにAWS用BのProviderがダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/3c089822-a1d4-8953-a154-7f428e86a83e.png)


##Resource 設定
###Key pairの作成
まずは一般的な方法で、EC2にSSH接続するためのkeyの生成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/f0f8bdde-b5da-7059-2694-27b9ec4da126.png)

####HCL code作成
provider.tf

```js
resource "aws_key_pair" "ec2_admin" {
 key_name = "ec2_admin"
 public_key = "${file(~/.ssh/ec2_admin.pub)}"
}
```
resource に続く "aws_key_pair"はリソースの種類でプレフィックスaws_*のようにあらかじめ決まっています。
"ec2_admin"はローカル変数(リソース名)で自由に命名でき、HCL codeから参照できます。


#### planコマンド実行

ではTerraformの**plan**コマンドを以下のように実行してみましょう。

```terminal
$ terraform plan
```
以下のように実際にプロビジョンを行う**apply**コマンドを実行する前に、AWSの実際の環境との差分を確認できます。
こうすることで慎重にプロビジョニングを実施できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/4850966a-bf5f-3fc6-5664-a374dc308f54.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/9d280272-971f-53e0-b6c6-9987cb523acc.png)

#### applyコマンド実行
ではいよいよプロビジョンを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/f00bc0d3-57b9-cfc9-d496-cad2fe704d35.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/e5906c03-3925-fddd-84c4-d190cdc69aed.png)

###Security groupの設定
ssh接続時のセキュリティグループを設定していきましょう(ファイヤーウォール/ポート設定)

#### HCL code作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/be92d3c3-1637-1b84-033b-9b26f8692a5f.png)

#### planコマンド実行
```terminal
$ terraform plan
```
#### applyコマンド実行
```terminal
$ terraform apply
```
###RDSの生成
#### HCL code作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/14116bda-e5f7-9fca-6bc5-e69d58e110bf.png)

#### planコマンド実行
```terminal
$ terraform plan
```
#### applyコマンド実行
```terminal
$ terraform apply
```
---

## data はどのように使うのか
これまで登場したproviderやresourceの他にも
**data**があります。
dataはすでに作成したインスタンスを検索し、情報を取得できるコマンドです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324313/b32c83ce-22b9-42fb-682a-457d745757fd.png)

----
#参考
https://events.linuxfoundation.org/wp-content/uploads/2017/12/Hashicorp-Terraform-Deep-Dive-with-no-Fear-Victor-Turbinsky-Texuna.pdf
https://www.44bits.io/ko/post/terraform_introduction_infrastrucute_as_code