Terraformでインフラのコード化を体験してみよう ~ その③VPC環境を作って、その中にEC2インスタンスを作ってみる


[前回](http://qiita.com/ritukiii/items/abbd164ad39965c25c42)、terraformを使ったEC2インスタンスの立ち上げ、そして即destroyで壊してみる。
という一連の流れを体験しました。

今回は、VPCを作り、その中にEC2インスタンスを立ち上げるという割りと一般的になってきた構成を作ってみようと思います。

## 前提知識

今回、下記のような`{awsのリソース名}.{リソースの名前}.id`とかをよく出てきます。

例. ここでは、`"${aws_vpc.test_vpc.id}"`として、`test_vpc`という名前のついたvpcリソースのidを引っ張ってきてます。


```
resource "aws_subnet" "public-1a" {
    vpc_id = "${aws_vpc.test_vpc.id}"
    cidr_block = "10.0.0.0/24"
    availability_zone = "ap-northeast-1a"
    tags {
     Name = "test_1a"
   }
}
```

この様に、terrafomでは、他のリソースのIDやname等を上述したルールで使うことが可能です。

## 早速作ってみる

今回はもう前提を話すより、実際のterraformのファイルを見たほうが早いと思うので見てみます。

### 構成

```
terraform-test/
├── aws.tf
├── main.tf
├── terraform.tfstate
└── terraform.tfvars
```

- `aws.tf`
	- awsというproviderを使うための設定を記載してます
- `terraform.tfvars`
	- AWSのaccess_keyとsecret_keyを記載してます(githubにcommitしたら死ぬやつです)
- `terraform.tfstate`
	- 現状のインフラの状況を表したjsonファイルです
	- 一度でも`terraform`でインフラを構築すると、自動的に生成してくれます


## aws.tf

```
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {}

provider "aws" {
    access_key = "${var.aws_access_key}"
    secret_key = "${var.aws_secret_key}"
    region     = "${var.region}"
}
```

## main.tf

```
# VPCの設定
resource "aws_vpc" "test_vpc" {
    cidr_block = "10.0.0.0/16"
    instance_tenancy = "default"
    tags {
     Name = "test_vpc_"
   }
}

## 以下サブネットの設定(各AZ毎に設定する)
resource "aws_subnet" "public-1a" {
    vpc_id = "${aws_vpc.test_vpc.id}"
    cidr_block = "10.0.0.0/24"
    availability_zone = "ap-northeast-1a"
    tags {
     Name = "test_1a"
   }
}

resource "aws_subnet" "public-1c" {
    vpc_id = "${aws_vpc.test_vpc.id}"
    cidr_block = "10.0.1.0/24"
    availability_zone = "ap-northeast-1c"
    tags {
     Name = "test_2a"
   }
}

## ゲートウェイの設定
resource "aws_internet_gateway" "igw_for_test_vpc" {
    vpc_id = "${aws_vpc.test_vpc.id}"
}

## 以下ルーティングテーブルの設定

resource "aws_route_table" "public-route" {
    vpc_id = "${aws_vpc.test_vpc.id}"
    route {
      cidr_block = "0.0.0.0/0"
      gateway_id = "${aws_internet_gateway.igw_for_test_vpc.id}"
   }
}

resource "aws_route_table_association" "puclic-1a" {
    subnet_id = "${aws_subnet.public-1a.id}"
    route_table_id = "${aws_route_table.public-route.id}"
}

resource "aws_route_table_association" "puclic-1c" {
    subnet_id = "${aws_subnet.public-1c.id}"
    route_table_id = "${aws_route_table.public-route.id}"
}


# セキュリティグループ
resource "aws_security_group" "test_vpc_sg" {
    name = "test_vpc_sg"
    description = "testing security group for test_vpc"
    vpc_id = "${aws_vpc.test_vpc.id}"
    ingress {
      from_port = 80
      to_port = 80
      protocol = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
    ingress {
      from_port = 443
      to_port = 443
      protocol = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
    egress {
      from_port = 0
      to_port = 0
      protocol = "-1"
      cidr_blocks = ["0.0.0.0/0"]
    }

    tags {
      Name = "test_vpc"
   }
}

# EC2インスタンス

resource "aws_instance" "test_rikkey" {
  # Amazon Linux AMI
  ami           = "ami-4af5022c"
  instance_type = "t2.micro"
  # 予め作っておいたkey pairの名前を指定する(存在しないとエラーになります)
  key_name      = "test_key_pair"
  vpc_security_group_ids = ["${aws_security_group.test_vpc_sg.id}"]
  subnet_id = "${aws_subnet.public-1a.id}"
  ebs_block_device = {
    device_name = "/dev/sdf"
    volume_type = "gp2"
    volume_size = "30"
  }
  tags {
   Name = "test-vpc"
  }
}

# EIP

resource "aws_eip" "eip_for_test_rikkey" {
    instance = "${aws_instance.test_rikkey.id}"
    vpc = true
}
```


## applyしてみる

```
$ terraform apply
aws_vpc.test_vpc: Refreshing state... (ID: vpc-c4dbefa0)
aws_subnet.public-1a: Refreshing state... (ID: subnet-1a18da53)
aws_internet_gateway.igw_for_test_vpc: Refreshing state... (ID: igw-3e6ca65a)
aws_subnet.public-1c: Refreshing state... (ID: subnet-15f4f34d)
aws_security_group.test_vpc_sg: Refreshing state... (ID: sg-86e993e0)
aws_route_table.public-route: Refreshing state... (ID: rtb-543ce333)
aws_route_table_association.puclic-1a: Refreshing state... (ID: rtbassoc-9bc6cefc)
aws_route_table_association.puclic-1c: Refreshing state... (ID: rtbassoc-1bded67c)
aws_instance.test_rikkey: Creating...
  ami:                                               "" => "ami-4af5022c"
  associate_public_ip_address:                       "" => "<computed>"
  availability_zone:                                 "" => "<computed>"
  ebs_block_device.#:                                "" => "1"
  ebs_block_device.2659407853.delete_on_termination: "" => "true"
  ebs_block_device.2659407853.device_name:           "" => "/dev/sdf"
  ebs_block_device.2659407853.encrypted:             "" => "<computed>"
  ebs_block_device.2659407853.iops:                  "" => "<computed>"
  ebs_block_device.2659407853.snapshot_id:           "" => "<computed>"
  ebs_block_device.2659407853.volume_size:           "" => "30"
  ebs_block_device.2659407853.volume_type:           "" => "gp2"
  ephemeral_block_device.#:                          "" => "<computed>"
  instance_state:                                    "" => "<computed>"
  instance_type:                                     "" => "t2.micro"
  ipv6_addresses.#:                                  "" => "<computed>"
  key_name:                                          "" => "test_key_pair"
  network_interface.#:                               "" => "<computed>"
  network_interface_id:                              "" => "<computed>"
  placement_group:                                   "" => "<computed>"
  primary_network_interface_id:                      "" => "<computed>"
  private_dns:                                       "" => "<computed>"
  private_ip:                                        "" => "<computed>"
  public_dns:                                        "" => "<computed>"
  public_ip:                                         "" => "<computed>"
  root_block_device.#:                               "" => "<computed>"
  security_groups.#:                                 "" => "<computed>"
  source_dest_check:                                 "" => "true"
  subnet_id:                                         "" => "subnet-1a18da53"
  tags.%:                                            "" => "1"
  tags.Name:                                         "" => "test-vpc"
  tenancy:                                           "" => "<computed>"
  vpc_security_group_ids.#:                          "" => "1"
  vpc_security_group_ids.2953584881:                 "" => "sg-86e993e0"
aws_instance.test_rikkey: Still creating... (10s elapsed)
aws_instance.test_rikkey: Still creating... (20s elapsed)
aws_instance.test_rikkey: Creation complete (ID: i-00eb71e709f8b1f25)
aws_eip.eip_for_test_rikkey: Creating...
  allocation_id:     "" => "<computed>"
  association_id:    "" => "<computed>"
  domain:            "" => "<computed>"
  instance:          "" => "i-00eb71e709f8b1f25"
  network_interface: "" => "<computed>"
  private_ip:        "" => "<computed>"
  public_ip:         "" => "<computed>"
  vpc:               "" => "true"
aws_eip.eip_for_test_rikkey: Creation complete (ID: eipalloc-8abadcb0)

Apply complete! Resources: 2 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:
```

良さそうです。

## 出来上がった結果を確認してみる

- VPC
	- ルーティングテーブル
	- サブネット
	- 等が想定どおりに設定されてました


![スクリーンショット 2017-09-02 13.56.15.png](https://qiita-image-store.s3.amazonaws.com/0/23276/29cdde3f-347d-3a57-ff33-58fd269a0599.png "スクリーンショット 2017-09-02 13.56.15.png")



- EC2インスタンス
  - VPCが想定どおりに指定されてる
  - セキュリティグループも設定されてる
  - key pair名も指定されてる
  - Elastic IPも設定できてる
  - securty groupのingress(インバウンド)とegress(アウトバウンド)も設定出来てる


![スクリーンショット 2017-09-02 13.50.10.png](https://qiita-image-store.s3.amazonaws.com/0/23276/f29bb571-8992-5094-7513-7ca8544a619a.png "スクリーンショット 2017-09-02 13.50.10.png")

![スクリーンショット 2017-09-02 13.51.15.png](https://qiita-image-store.s3.amazonaws.com/0/23276/d23b241b-e7c0-94cd-88f0-03291245f19d.png "スクリーンショット 2017-09-02 13.51.15.png")


## 次回予告

だんだんterraformの記法やルールも慣れてきたので、
一般的なwebサーバの構成や、S3/SQS等のサービスもterraformで作っていきます。